1 | #include <machine/rtems-bsd-user-space.h> |
---|
2 | |
---|
3 | #include <stdio.h> |
---|
4 | #include <stdlib.h> |
---|
5 | #include <string.h> |
---|
6 | #include <setjmp.h> |
---|
7 | #include <signal.h> |
---|
8 | #include <crypto.h> |
---|
9 | |
---|
10 | #include "arm_arch.h" |
---|
11 | |
---|
12 | unsigned int OPENSSL_armcap_P = 0; |
---|
13 | |
---|
14 | #if __ARM_MAX_ARCH__<7 |
---|
15 | void OPENSSL_cpuid_setup(void) |
---|
16 | { |
---|
17 | } |
---|
18 | |
---|
19 | unsigned long OPENSSL_rdtsc(void) |
---|
20 | { |
---|
21 | return 0; |
---|
22 | } |
---|
23 | #else |
---|
24 | static sigset_t all_masked; |
---|
25 | |
---|
26 | static sigjmp_buf ill_jmp; |
---|
27 | static 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 | */ |
---|
36 | void _armv7_neon_probe(void); |
---|
37 | void _armv8_aes_probe(void); |
---|
38 | void _armv8_sha1_probe(void); |
---|
39 | void _armv8_sha256_probe(void); |
---|
40 | void _armv8_pmull_probe(void); |
---|
41 | unsigned long _armv7_tick(void); |
---|
42 | |
---|
43 | unsigned 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 |
---|
56 | void OPENSSL_cpuid_setup(void) __attribute__ ((constructor)); |
---|
57 | extern unsigned long getauxval(unsigned long type) __attribute__ ((weak)); |
---|
58 | # else |
---|
59 | static 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 | |
---|
89 | void 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 |
---|