armcap.c revision 31cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895
131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include <stdio.h>
231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include <stdlib.h>
331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include <string.h>
431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include <setjmp.h>
531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include <signal.h>
631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include <crypto.h>
731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include "arm_arch.h"
931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
1031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootunsigned int OPENSSL_armcap_P;
1131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
1231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootstatic sigset_t all_masked;
1331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
1431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootstatic sigjmp_buf ill_jmp;
1531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootstatic void ill_handler (int sig) { siglongjmp(ill_jmp,sig); }
1631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
1731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root/*
1831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root * Following subroutines could have been inlined, but it's not all
1931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root * ARM compilers support inline assembler...
2031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root */
2131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootvoid _armv7_neon_probe(void);
2231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootunsigned int _armv7_tick(void);
2331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
2431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootunsigned int OPENSSL_rdtsc(void)
2531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	{
2631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	if (OPENSSL_armcap_P & ARMV7_TICK)
2731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		return _armv7_tick();
2831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	else
2931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		return 0;
3031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	}
3131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
3231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#if defined(__GNUC__) && __GNUC__>=2
3331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootvoid OPENSSL_cpuid_setup(void) __attribute__((constructor));
3431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#endif
3531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootvoid OPENSSL_cpuid_setup(void)
3631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	{
3731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	char *e;
3831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	struct sigaction	ill_oact,ill_act;
3931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigset_t		oset;
4031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	static int trigger=0;
4131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
4231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	if (trigger) return;
4331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	trigger=1;
4431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
4531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	if ((e=getenv("OPENSSL_armcap")))
4631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		{
4731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		OPENSSL_armcap_P=strtoul(e,NULL,0);
4831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		return;
4931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		}
5031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
5131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigfillset(&all_masked);
5231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigdelset(&all_masked,SIGILL);
5331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigdelset(&all_masked,SIGTRAP);
5431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigdelset(&all_masked,SIGFPE);
5531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigdelset(&all_masked,SIGBUS);
5631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigdelset(&all_masked,SIGSEGV);
5731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
5831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	OPENSSL_armcap_P = 0;
5931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
6031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	memset(&ill_act,0,sizeof(ill_act));
6131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	ill_act.sa_handler = ill_handler;
6231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	ill_act.sa_mask    = all_masked;
6331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
6431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset);
6531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigaction(SIGILL,&ill_act,&ill_oact);
6631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
6731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	if (sigsetjmp(ill_jmp,1) == 0)
6831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		{
6931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		_armv7_neon_probe();
7031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		OPENSSL_armcap_P |= ARMV7_NEON;
7131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		}
7231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	if (sigsetjmp(ill_jmp,1) == 0)
7331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		{
7431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		_armv7_tick();
7531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		OPENSSL_armcap_P |= ARMV7_TICK;
7631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		}
7731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
7831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigaction (SIGILL,&ill_oact,NULL);
7931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigprocmask(SIG_SETMASK,&oset,NULL);
8031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	}
81