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