armcap.c revision 272461
1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#include <setjmp.h> 5#include <signal.h> 6#include <crypto.h> 7 8#include "arm_arch.h" 9 10unsigned int OPENSSL_armcap_P; 11 12static sigset_t all_masked; 13 14static sigjmp_buf ill_jmp; 15static void ill_handler (int sig) { siglongjmp(ill_jmp,sig); } 16 17/* 18 * Following subroutines could have been inlined, but it's not all 19 * ARM compilers support inline assembler... 20 */ 21void _armv7_neon_probe(void); 22unsigned int _armv7_tick(void); 23 24unsigned int OPENSSL_rdtsc(void) 25 { 26 if (OPENSSL_armcap_P & ARMV7_TICK) 27 return _armv7_tick(); 28 else 29 return 0; 30 } 31 32#if defined(__GNUC__) && __GNUC__>=2 33void OPENSSL_cpuid_setup(void) __attribute__((constructor)); 34#endif 35void OPENSSL_cpuid_setup(void) 36 { 37 char *e; 38 struct sigaction ill_oact,ill_act; 39 sigset_t oset; 40 static int trigger=0; 41 42 if (trigger) return; 43 trigger=1; 44 45 if ((e=getenv("OPENSSL_armcap"))) 46 { 47 OPENSSL_armcap_P=strtoul(e,NULL,0); 48 return; 49 } 50 51 sigfillset(&all_masked); 52 sigdelset(&all_masked,SIGILL); 53 sigdelset(&all_masked,SIGTRAP); 54 sigdelset(&all_masked,SIGFPE); 55 sigdelset(&all_masked,SIGBUS); 56 sigdelset(&all_masked,SIGSEGV); 57 58 OPENSSL_armcap_P = 0; 59 60 memset(&ill_act,0,sizeof(ill_act)); 61 ill_act.sa_handler = ill_handler; 62 ill_act.sa_mask = all_masked; 63 64 sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset); 65 sigaction(SIGILL,&ill_act,&ill_oact); 66 67 if (sigsetjmp(ill_jmp,1) == 0) 68 { 69 _armv7_neon_probe(); 70 OPENSSL_armcap_P |= ARMV7_NEON; 71 } 72 if (sigsetjmp(ill_jmp,1) == 0) 73 { 74 _armv7_tick(); 75 OPENSSL_armcap_P |= ARMV7_TICK; 76 } 77 78 sigaction (SIGILL,&ill_oact,NULL); 79 sigprocmask(SIG_SETMASK,&oset,NULL); 80 } 81