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