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 10 unsigned int OPENSSL_armcap_P; 11 12 static sigset_t all_masked; 13 14 static sigjmp_buf ill_jmp; 15 static 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 */ 21 void _armv7_neon_probe(void); 22 void _armv8_aes_probe(void); 23 void _armv8_sha1_probe(void); 24 void _armv8_sha256_probe(void); 25 void _armv8_pmull_probe(void); 26 unsigned long _armv7_tick(void); 27 28 unsigned long OPENSSL_rdtsc(void) 29 { 30 if (OPENSSL_armcap_P & ARMV7_TICK) 31 return _armv7_tick(); 32 else 33 return 0; 34 } 35 36 /* 37 * Use a weak reference to getauxval() so we can use it if it is available but 38 * don't break the build if it is not. 39 */ 40 #if defined(__GNUC__) && __GNUC__>=2 41 void OPENSSL_cpuid_setup(void) __attribute__((constructor)); 42 extern unsigned long getauxval(unsigned long type) __attribute__((weak)); 43 #else 44 static unsigned long (*getauxval)(unsigned long) = NULL; 45 #endif 46 47 /* 48 * ARM puts the the feature bits for Crypto Extensions in AT_HWCAP2, whereas 49 * AArch64 used AT_HWCAP. 50 */ 51 #if defined(__arm__) || defined (__arm) 52 # define HWCAP 16 /* AT_HWCAP */ 53 # define HWCAP_NEON (1 << 12) 54 55 # define HWCAP_CE 26 /* AT_HWCAP2 */ 56 # define HWCAP_CE_AES (1 << 0) 57 # define HWCAP_CE_PMULL (1 << 1) 58 # define HWCAP_CE_SHA1 (1 << 2) 59 # define HWCAP_CE_SHA256 (1 << 3) 60 #elif defined(__aarch64__) 61 # define HWCAP 16 /* AT_HWCAP */ 62 # define HWCAP_NEON (1 << 1) 63 64 # define HWCAP_CE HWCAP 65 # define HWCAP_CE_AES (1 << 3) 66 # define HWCAP_CE_PMULL (1 << 4) 67 # define HWCAP_CE_SHA1 (1 << 5) 68 # define HWCAP_CE_SHA256 (1 << 6) 69 #endif 70 71 void OPENSSL_cpuid_setup(void) 72 { 73 char *e; 74 struct sigaction ill_oact,ill_act; 75 sigset_t oset; 76 static int trigger=0; 77 78 if (trigger) return; 79 trigger=1; 80 81 if ((e=getenv("OPENSSL_armcap"))) 82 { 83 OPENSSL_armcap_P=(unsigned int)strtoul(e,NULL,0); 84 return; 85 } 86 87 sigfillset(&all_masked); 88 sigdelset(&all_masked,SIGILL); 89 sigdelset(&all_masked,SIGTRAP); 90 sigdelset(&all_masked,SIGFPE); 91 sigdelset(&all_masked,SIGBUS); 92 sigdelset(&all_masked,SIGSEGV); 93 94 OPENSSL_armcap_P = 0; 95 96 memset(&ill_act,0,sizeof(ill_act)); 97 ill_act.sa_handler = ill_handler; 98 ill_act.sa_mask = all_masked; 99 100 sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset); 101 sigaction(SIGILL,&ill_act,&ill_oact); 102 103 if (getauxval != NULL) 104 { 105 if (getauxval(HWCAP) & HWCAP_NEON) 106 { 107 unsigned long hwcap = getauxval(HWCAP_CE); 108 109 OPENSSL_armcap_P |= ARMV7_NEON; 110 111 if (hwcap & HWCAP_CE_AES) 112 OPENSSL_armcap_P |= ARMV8_AES; 113 114 if (hwcap & HWCAP_CE_PMULL) 115 OPENSSL_armcap_P |= ARMV8_PMULL; 116 117 if (hwcap & HWCAP_CE_SHA1) 118 OPENSSL_armcap_P |= ARMV8_SHA1; 119 120 if (hwcap & HWCAP_CE_SHA256) 121 OPENSSL_armcap_P |= ARMV8_SHA256; 122 } 123 } 124 else if (sigsetjmp(ill_jmp,1) == 0) 125 { 126 _armv7_neon_probe(); 127 OPENSSL_armcap_P |= ARMV7_NEON; 128 if (sigsetjmp(ill_jmp,1) == 0) 129 { 130 _armv8_pmull_probe(); 131 OPENSSL_armcap_P |= ARMV8_PMULL|ARMV8_AES; 132 } 133 else if (sigsetjmp(ill_jmp,1) == 0) 134 { 135 _armv8_aes_probe(); 136 OPENSSL_armcap_P |= ARMV8_AES; 137 } 138 if (sigsetjmp(ill_jmp,1) == 0) 139 { 140 _armv8_sha1_probe(); 141 OPENSSL_armcap_P |= ARMV8_SHA1; 142 } 143 if (sigsetjmp(ill_jmp,1) == 0) 144 { 145 _armv8_sha256_probe(); 146 OPENSSL_armcap_P |= ARMV8_SHA256; 147 } 148 } 149 if (sigsetjmp(ill_jmp,1) == 0) 150 { 151 _armv7_tick(); 152 OPENSSL_armcap_P |= ARMV7_TICK; 153 } 154 155 sigaction (SIGILL,&ill_oact,NULL); 156 sigprocmask(SIG_SETMASK,&oset,NULL); 157 } 158