]>
Commit | Line | Data |
---|---|---|
d2e9e320 | 1 | /* |
6738bf14 | 2 | * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. |
d2e9e320 | 3 | * |
0e9725bc | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
d2e9e320 RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
87873f43 AP |
10 | #include <stdio.h> |
11 | #include <stdlib.h> | |
12 | #include <string.h> | |
13 | #include <setjmp.h> | |
14 | #include <signal.h> | |
313e6ec1 | 15 | #include <openssl/crypto.h> |
d807db26 | 16 | #include "internal/cryptlib.h" |
87873f43 AP |
17 | |
18 | #include "arm_arch.h" | |
19 | ||
0f113f3e | 20 | unsigned int OPENSSL_armcap_P = 0; |
5ea64b45 | 21 | unsigned int OPENSSL_arm_midr = 0; |
87873f43 | 22 | |
c1669e1c | 23 | #if __ARM_MAX_ARCH__<7 |
0f113f3e MC |
24 | void OPENSSL_cpuid_setup(void) |
25 | { | |
26 | } | |
27 | ||
d807db26 | 28 | uint32_t OPENSSL_rdtsc(void) |
0f113f3e MC |
29 | { |
30 | return 0; | |
31 | } | |
c1669e1c | 32 | #else |
87873f43 AP |
33 | static sigset_t all_masked; |
34 | ||
35 | static sigjmp_buf ill_jmp; | |
0f113f3e MC |
36 | static void ill_handler(int sig) |
37 | { | |
38 | siglongjmp(ill_jmp, sig); | |
39 | } | |
87873f43 AP |
40 | |
41 | /* | |
42 | * Following subroutines could have been inlined, but it's not all | |
43 | * ARM compilers support inline assembler... | |
44 | */ | |
45 | void _armv7_neon_probe(void); | |
4afa9f03 AP |
46 | void _armv8_aes_probe(void); |
47 | void _armv8_sha1_probe(void); | |
48 | void _armv8_sha256_probe(void); | |
49 | void _armv8_pmull_probe(void); | |
77f3612e AP |
50 | # ifdef __aarch64__ |
51 | void _armv8_sha512_probe(void); | |
5ea64b45 | 52 | unsigned int _armv8_cpuid_probe(void); |
77f3612e | 53 | # endif |
d807db26 | 54 | uint32_t _armv7_tick(void); |
87873f43 | 55 | |
d807db26 | 56 | uint32_t OPENSSL_rdtsc(void) |
0f113f3e MC |
57 | { |
58 | if (OPENSSL_armcap_P & ARMV7_TICK) | |
59 | return _armv7_tick(); | |
60 | else | |
61 | return 0; | |
62 | } | |
87873f43 | 63 | |
9b05cbc3 AP |
64 | # if defined(__GNUC__) && __GNUC__>=2 |
65 | void OPENSSL_cpuid_setup(void) __attribute__ ((constructor)); | |
66 | # endif | |
5f40dd15 RL |
67 | |
68 | # if defined(__GLIBC__) && defined(__GLIBC_PREREQ) | |
69 | # if __GLIBC_PREREQ(2, 16) | |
70 | # include <sys/auxv.h> | |
71 | # define OSSL_IMPLEMENT_GETAUXVAL | |
72 | # endif | |
0f113f3e | 73 | # endif |
e8d93e34 AP |
74 | |
75 | /* | |
c9a41d7d | 76 | * ARM puts the feature bits for Crypto Extensions in AT_HWCAP2, whereas |
e8d93e34 AP |
77 | * AArch64 used AT_HWCAP. |
78 | */ | |
0f113f3e MC |
79 | # if defined(__arm__) || defined (__arm) |
80 | # define HWCAP 16 | |
81 | /* AT_HWCAP */ | |
82 | # define HWCAP_NEON (1 << 12) | |
83 | ||
84 | # define HWCAP_CE 26 | |
85 | /* AT_HWCAP2 */ | |
86 | # define HWCAP_CE_AES (1 << 0) | |
87 | # define HWCAP_CE_PMULL (1 << 1) | |
88 | # define HWCAP_CE_SHA1 (1 << 2) | |
89 | # define HWCAP_CE_SHA256 (1 << 3) | |
90 | # elif defined(__aarch64__) | |
91 | # define HWCAP 16 | |
92 | /* AT_HWCAP */ | |
93 | # define HWCAP_NEON (1 << 1) | |
94 | ||
95 | # define HWCAP_CE HWCAP | |
96 | # define HWCAP_CE_AES (1 << 3) | |
97 | # define HWCAP_CE_PMULL (1 << 4) | |
98 | # define HWCAP_CE_SHA1 (1 << 5) | |
99 | # define HWCAP_CE_SHA256 (1 << 6) | |
5ea64b45 | 100 | # define HWCAP_CPUID (1 << 11) |
77f3612e | 101 | # define HWCAP_CE_SHA512 (1 << 21) |
0f113f3e | 102 | # endif |
e8d93e34 | 103 | |
87873f43 | 104 | void OPENSSL_cpuid_setup(void) |
0f113f3e | 105 | { |
6ea3bca4 | 106 | const char *e; |
0f113f3e MC |
107 | struct sigaction ill_oact, ill_act; |
108 | sigset_t oset; | |
109 | static int trigger = 0; | |
110 | ||
111 | if (trigger) | |
112 | return; | |
113 | trigger = 1; | |
114 | ||
115 | if ((e = getenv("OPENSSL_armcap"))) { | |
116 | OPENSSL_armcap_P = (unsigned int)strtoul(e, NULL, 0); | |
117 | return; | |
118 | } | |
119 | ||
8653e78f AP |
120 | # if defined(__APPLE__) && !defined(__aarch64__) |
121 | /* | |
122 | * Capability probing by catching SIGILL appears to be problematic | |
123 | * on iOS. But since Apple universe is "monocultural", it's actually | |
124 | * possible to simply set pre-defined processor capability mask. | |
125 | */ | |
126 | if (1) { | |
127 | OPENSSL_armcap_P = ARMV7_NEON; | |
128 | return; | |
129 | } | |
130 | /* | |
131 | * One could do same even for __aarch64__ iOS builds. It's not done | |
132 | * exclusively for reasons of keeping code unified across platforms. | |
133 | * Unified code works because it never triggers SIGILL on Apple | |
134 | * devices... | |
135 | */ | |
136 | # endif | |
137 | ||
5f40dd15 RL |
138 | OPENSSL_armcap_P = 0; |
139 | ||
140 | # ifdef OSSL_IMPLEMENT_GETAUXVAL | |
141 | if (getauxval(HWCAP) & HWCAP_NEON) { | |
142 | unsigned long hwcap = getauxval(HWCAP_CE); | |
143 | ||
144 | OPENSSL_armcap_P |= ARMV7_NEON; | |
145 | ||
146 | if (hwcap & HWCAP_CE_AES) | |
147 | OPENSSL_armcap_P |= ARMV8_AES; | |
148 | ||
149 | if (hwcap & HWCAP_CE_PMULL) | |
150 | OPENSSL_armcap_P |= ARMV8_PMULL; | |
151 | ||
152 | if (hwcap & HWCAP_CE_SHA1) | |
153 | OPENSSL_armcap_P |= ARMV8_SHA1; | |
154 | ||
155 | if (hwcap & HWCAP_CE_SHA256) | |
156 | OPENSSL_armcap_P |= ARMV8_SHA256; | |
157 | ||
158 | # ifdef __aarch64__ | |
159 | if (hwcap & HWCAP_CE_SHA512) | |
160 | OPENSSL_armcap_P |= ARMV8_SHA512; | |
5ea64b45 FF |
161 | |
162 | if (hwcap & HWCAP_CPUID) | |
163 | OPENSSL_armcap_P |= ARMV8_CPUID; | |
5f40dd15 RL |
164 | # endif |
165 | } | |
166 | # endif | |
167 | ||
0f113f3e MC |
168 | sigfillset(&all_masked); |
169 | sigdelset(&all_masked, SIGILL); | |
170 | sigdelset(&all_masked, SIGTRAP); | |
171 | sigdelset(&all_masked, SIGFPE); | |
172 | sigdelset(&all_masked, SIGBUS); | |
173 | sigdelset(&all_masked, SIGSEGV); | |
174 | ||
0f113f3e MC |
175 | memset(&ill_act, 0, sizeof(ill_act)); |
176 | ill_act.sa_handler = ill_handler; | |
177 | ill_act.sa_mask = all_masked; | |
178 | ||
179 | sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); | |
180 | sigaction(SIGILL, &ill_act, &ill_oact); | |
181 | ||
5f40dd15 RL |
182 | /* If we used getauxval, we already have all the values */ |
183 | # ifndef OSSL_IMPLEMENT_GETAUXVAL | |
184 | if (sigsetjmp(ill_jmp, 1) == 0) { | |
0f113f3e MC |
185 | _armv7_neon_probe(); |
186 | OPENSSL_armcap_P |= ARMV7_NEON; | |
187 | if (sigsetjmp(ill_jmp, 1) == 0) { | |
188 | _armv8_pmull_probe(); | |
189 | OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES; | |
190 | } else if (sigsetjmp(ill_jmp, 1) == 0) { | |
191 | _armv8_aes_probe(); | |
192 | OPENSSL_armcap_P |= ARMV8_AES; | |
193 | } | |
194 | if (sigsetjmp(ill_jmp, 1) == 0) { | |
195 | _armv8_sha1_probe(); | |
196 | OPENSSL_armcap_P |= ARMV8_SHA1; | |
197 | } | |
198 | if (sigsetjmp(ill_jmp, 1) == 0) { | |
199 | _armv8_sha256_probe(); | |
200 | OPENSSL_armcap_P |= ARMV8_SHA256; | |
201 | } | |
5f40dd15 | 202 | # if defined(__aarch64__) && !defined(__APPLE__) |
77f3612e AP |
203 | if (sigsetjmp(ill_jmp, 1) == 0) { |
204 | _armv8_sha512_probe(); | |
205 | OPENSSL_armcap_P |= ARMV8_SHA512; | |
206 | } | |
5f40dd15 | 207 | # endif |
0f113f3e | 208 | } |
5f40dd15 RL |
209 | # endif |
210 | ||
211 | /* Things that getauxval didn't tell us */ | |
0f113f3e MC |
212 | if (sigsetjmp(ill_jmp, 1) == 0) { |
213 | _armv7_tick(); | |
214 | OPENSSL_armcap_P |= ARMV7_TICK; | |
215 | } | |
216 | ||
217 | sigaction(SIGILL, &ill_oact, NULL); | |
218 | sigprocmask(SIG_SETMASK, &oset, NULL); | |
5ea64b45 FF |
219 | |
220 | # ifdef __aarch64__ | |
221 | if (OPENSSL_armcap_P & ARMV8_CPUID) | |
222 | OPENSSL_arm_midr = _armv8_cpuid_probe(); | |
223 | # endif | |
0f113f3e | 224 | } |
c1669e1c | 225 | #endif |