1238384Sjkim#include <stdio.h> 2238384Sjkim#include <stdlib.h> 3238384Sjkim#include <string.h> 4238384Sjkim#include <setjmp.h> 5238384Sjkim#include <signal.h> 6238384Sjkim#include <crypto.h> 7238384Sjkim 8352193Sjkim#include "cryptlib.h" 9238384Sjkim#include "arm_arch.h" 10238384Sjkim 11325334Sjkim__attribute__ ((visibility("hidden"))) 12290207Sjkimunsigned int OPENSSL_armcap_P = 0; 13238384Sjkim 14290207Sjkim#if __ARM_MAX_ARCH__<7 15290207Sjkimvoid OPENSSL_cpuid_setup(void) 16290207Sjkim{ 17290207Sjkim} 18290207Sjkim 19290207Sjkimunsigned long OPENSSL_rdtsc(void) 20290207Sjkim{ 21290207Sjkim return 0; 22290207Sjkim} 23290207Sjkim#else 24238384Sjkimstatic sigset_t all_masked; 25238384Sjkim 26238384Sjkimstatic sigjmp_buf ill_jmp; 27280297Sjkimstatic void ill_handler(int sig) 28280297Sjkim{ 29280297Sjkim siglongjmp(ill_jmp, sig); 30280297Sjkim} 31238384Sjkim 32238384Sjkim/* 33238384Sjkim * Following subroutines could have been inlined, but it's not all 34238384Sjkim * ARM compilers support inline assembler... 35238384Sjkim */ 36238384Sjkimvoid _armv7_neon_probe(void); 37290207Sjkimvoid _armv8_aes_probe(void); 38290207Sjkimvoid _armv8_sha1_probe(void); 39290207Sjkimvoid _armv8_sha256_probe(void); 40290207Sjkimvoid _armv8_pmull_probe(void); 41290207Sjkimunsigned long _armv7_tick(void); 42238384Sjkim 43290207Sjkimunsigned long OPENSSL_rdtsc(void) 44280297Sjkim{ 45280297Sjkim if (OPENSSL_armcap_P & ARMV7_TICK) 46280297Sjkim return _armv7_tick(); 47280297Sjkim else 48280297Sjkim return 0; 49280297Sjkim} 50238384Sjkim 51290207Sjkim/* 52290207Sjkim * Use a weak reference to getauxval() so we can use it if it is available but 53290207Sjkim * don't break the build if it is not. 54290207Sjkim */ 55290207Sjkim# if defined(__GNUC__) && __GNUC__>=2 56280297Sjkimvoid OPENSSL_cpuid_setup(void) __attribute__ ((constructor)); 57290207Sjkimextern unsigned long getauxval(unsigned long type) __attribute__ ((weak)); 58290207Sjkim# else 59290207Sjkimstatic unsigned long (*getauxval) (unsigned long) = NULL; 60290207Sjkim# endif 61290207Sjkim 62290207Sjkim/* 63290207Sjkim * ARM puts the the feature bits for Crypto Extensions in AT_HWCAP2, whereas 64290207Sjkim * AArch64 used AT_HWCAP. 65290207Sjkim */ 66290207Sjkim# if defined(__arm__) || defined (__arm) 67290207Sjkim# define HWCAP 16 68290207Sjkim /* AT_HWCAP */ 69290207Sjkim# define HWCAP_NEON (1 << 12) 70290207Sjkim 71290207Sjkim# define HWCAP_CE 26 72290207Sjkim /* AT_HWCAP2 */ 73290207Sjkim# define HWCAP_CE_AES (1 << 0) 74290207Sjkim# define HWCAP_CE_PMULL (1 << 1) 75290207Sjkim# define HWCAP_CE_SHA1 (1 << 2) 76290207Sjkim# define HWCAP_CE_SHA256 (1 << 3) 77290207Sjkim# elif defined(__aarch64__) 78290207Sjkim# define HWCAP 16 79290207Sjkim /* AT_HWCAP */ 80290207Sjkim# define HWCAP_NEON (1 << 1) 81290207Sjkim 82290207Sjkim# define HWCAP_CE HWCAP 83290207Sjkim# define HWCAP_CE_AES (1 << 3) 84290207Sjkim# define HWCAP_CE_PMULL (1 << 4) 85290207Sjkim# define HWCAP_CE_SHA1 (1 << 5) 86290207Sjkim# define HWCAP_CE_SHA256 (1 << 6) 87290207Sjkim# endif 88290207Sjkim 89238384Sjkimvoid OPENSSL_cpuid_setup(void) 90280297Sjkim{ 91280297Sjkim char *e; 92280297Sjkim struct sigaction ill_oact, ill_act; 93280297Sjkim sigset_t oset; 94280297Sjkim static int trigger = 0; 95238384Sjkim 96280297Sjkim if (trigger) 97280297Sjkim return; 98280297Sjkim trigger = 1; 99238384Sjkim 100280297Sjkim if ((e = getenv("OPENSSL_armcap"))) { 101290207Sjkim OPENSSL_armcap_P = (unsigned int)strtoul(e, NULL, 0); 102280297Sjkim return; 103280297Sjkim } 104238384Sjkim 105280297Sjkim sigfillset(&all_masked); 106280297Sjkim sigdelset(&all_masked, SIGILL); 107280297Sjkim sigdelset(&all_masked, SIGTRAP); 108280297Sjkim sigdelset(&all_masked, SIGFPE); 109280297Sjkim sigdelset(&all_masked, SIGBUS); 110280297Sjkim sigdelset(&all_masked, SIGSEGV); 111238384Sjkim 112280297Sjkim OPENSSL_armcap_P = 0; 113238384Sjkim 114280297Sjkim memset(&ill_act, 0, sizeof(ill_act)); 115280297Sjkim ill_act.sa_handler = ill_handler; 116280297Sjkim ill_act.sa_mask = all_masked; 117238384Sjkim 118280297Sjkim sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); 119280297Sjkim sigaction(SIGILL, &ill_act, &ill_oact); 120238384Sjkim 121290207Sjkim if (getauxval != NULL) { 122290207Sjkim if (getauxval(HWCAP) & HWCAP_NEON) { 123290207Sjkim unsigned long hwcap = getauxval(HWCAP_CE); 124290207Sjkim 125290207Sjkim OPENSSL_armcap_P |= ARMV7_NEON; 126290207Sjkim 127290207Sjkim if (hwcap & HWCAP_CE_AES) 128290207Sjkim OPENSSL_armcap_P |= ARMV8_AES; 129290207Sjkim 130290207Sjkim if (hwcap & HWCAP_CE_PMULL) 131290207Sjkim OPENSSL_armcap_P |= ARMV8_PMULL; 132290207Sjkim 133290207Sjkim if (hwcap & HWCAP_CE_SHA1) 134290207Sjkim OPENSSL_armcap_P |= ARMV8_SHA1; 135290207Sjkim 136290207Sjkim if (hwcap & HWCAP_CE_SHA256) 137290207Sjkim OPENSSL_armcap_P |= ARMV8_SHA256; 138290207Sjkim } 139290207Sjkim } else if (sigsetjmp(ill_jmp, 1) == 0) { 140280297Sjkim _armv7_neon_probe(); 141280297Sjkim OPENSSL_armcap_P |= ARMV7_NEON; 142290207Sjkim if (sigsetjmp(ill_jmp, 1) == 0) { 143290207Sjkim _armv8_pmull_probe(); 144290207Sjkim OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES; 145290207Sjkim } else if (sigsetjmp(ill_jmp, 1) == 0) { 146290207Sjkim _armv8_aes_probe(); 147290207Sjkim OPENSSL_armcap_P |= ARMV8_AES; 148290207Sjkim } 149290207Sjkim if (sigsetjmp(ill_jmp, 1) == 0) { 150290207Sjkim _armv8_sha1_probe(); 151290207Sjkim OPENSSL_armcap_P |= ARMV8_SHA1; 152290207Sjkim } 153290207Sjkim if (sigsetjmp(ill_jmp, 1) == 0) { 154290207Sjkim _armv8_sha256_probe(); 155290207Sjkim OPENSSL_armcap_P |= ARMV8_SHA256; 156290207Sjkim } 157280297Sjkim } 158280297Sjkim if (sigsetjmp(ill_jmp, 1) == 0) { 159280297Sjkim _armv7_tick(); 160280297Sjkim OPENSSL_armcap_P |= ARMV7_TICK; 161280297Sjkim } 162280297Sjkim 163280297Sjkim sigaction(SIGILL, &ill_oact, NULL); 164280297Sjkim sigprocmask(SIG_SETMASK, &oset, NULL); 165280297Sjkim} 166290207Sjkim#endif 167