]>
Commit | Line | Data |
---|---|---|
87873f43 AP |
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 | ||
0f113f3e | 10 | unsigned int OPENSSL_armcap_P = 0; |
87873f43 | 11 | |
c1669e1c | 12 | #if __ARM_MAX_ARCH__<7 |
0f113f3e MC |
13 | void OPENSSL_cpuid_setup(void) |
14 | { | |
15 | } | |
16 | ||
17 | unsigned long OPENSSL_rdtsc(void) | |
18 | { | |
19 | return 0; | |
20 | } | |
c1669e1c | 21 | #else |
87873f43 AP |
22 | static sigset_t all_masked; |
23 | ||
24 | static sigjmp_buf ill_jmp; | |
0f113f3e MC |
25 | static void ill_handler(int sig) |
26 | { | |
27 | siglongjmp(ill_jmp, sig); | |
28 | } | |
87873f43 AP |
29 | |
30 | /* | |
31 | * Following subroutines could have been inlined, but it's not all | |
32 | * ARM compilers support inline assembler... | |
33 | */ | |
34 | void _armv7_neon_probe(void); | |
4afa9f03 AP |
35 | void _armv8_aes_probe(void); |
36 | void _armv8_sha1_probe(void); | |
37 | void _armv8_sha256_probe(void); | |
38 | void _armv8_pmull_probe(void); | |
e8d93e34 | 39 | unsigned long _armv7_tick(void); |
87873f43 | 40 | |
e8d93e34 | 41 | unsigned long OPENSSL_rdtsc(void) |
0f113f3e MC |
42 | { |
43 | if (OPENSSL_armcap_P & ARMV7_TICK) | |
44 | return _armv7_tick(); | |
45 | else | |
46 | return 0; | |
47 | } | |
87873f43 | 48 | |
9b05cbc3 AP |
49 | # if defined(__GNUC__) && __GNUC__>=2 |
50 | void OPENSSL_cpuid_setup(void) __attribute__ ((constructor)); | |
51 | # endif | |
e8d93e34 AP |
52 | /* |
53 | * Use a weak reference to getauxval() so we can use it if it is available but | |
54 | * don't break the build if it is not. | |
55 | */ | |
9b05cbc3 | 56 | # if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) |
0f113f3e MC |
57 | extern unsigned long getauxval(unsigned long type) __attribute__ ((weak)); |
58 | # else | |
59 | static unsigned long (*getauxval) (unsigned long) = NULL; | |
60 | # endif | |
e8d93e34 AP |
61 | |
62 | /* | |
63 | * ARM puts the the feature bits for Crypto Extensions in AT_HWCAP2, whereas | |
64 | * AArch64 used AT_HWCAP. | |
65 | */ | |
0f113f3e MC |
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 | |
e8d93e34 | 88 | |
87873f43 | 89 | void OPENSSL_cpuid_setup(void) |
0f113f3e MC |
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 | } | |
c1669e1c | 166 | #endif |