1 /*
2 * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
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
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <setjmp.h>
14 #include <signal.h>
15 #include <sys/time.h>
16 #include <unistd.h>
17 #include <openssl/bn.h>
18 #include "internal/cryptlib.h"
19 #include "crypto/sparc_arch.h"
20
21 #if defined(__GNUC__) && defined(__linux)
22 __attribute__((visibility("hidden")))
23 #endif
24 unsigned int OPENSSL_sparcv9cap_P[2]
25 = { SPARCV9_TICK_PRIVILEGED, 0 };
26
27 unsigned long _sparcv9_rdtick(void);
28 void _sparcv9_vis1_probe(void);
29 unsigned long _sparcv9_vis1_instrument(void);
30 void _sparcv9_vis2_probe(void);
31 void _sparcv9_fmadd_probe(void);
32 unsigned long _sparcv9_rdcfr(void);
33 void _sparcv9_vis3_probe(void);
34 void _sparcv9_fjaesx_probe(void);
35 unsigned long _sparcv9_random(void);
36 size_t _sparcv9_vis1_instrument_bus(unsigned int *, size_t);
37 size_t _sparcv9_vis1_instrument_bus2(unsigned int *, size_t, size_t);
38
OPENSSL_rdtsc(void)39 uint32_t OPENSSL_rdtsc(void)
40 {
41 if (OPENSSL_sparcv9cap_P[0] & SPARCV9_TICK_PRIVILEGED)
42 #if defined(__sun) && defined(__SVR4)
43 return gethrtime();
44 #else
45 return 0;
46 #endif
47 else
48 return _sparcv9_rdtick();
49 }
50
OPENSSL_instrument_bus(unsigned int * out,size_t cnt)51 size_t OPENSSL_instrument_bus(unsigned int *out, size_t cnt)
52 {
53 if ((OPENSSL_sparcv9cap_P[0] & (SPARCV9_TICK_PRIVILEGED | SPARCV9_BLK)) == SPARCV9_BLK)
54 return _sparcv9_vis1_instrument_bus(out, cnt);
55 else
56 return 0;
57 }
58
OPENSSL_instrument_bus2(unsigned int * out,size_t cnt,size_t max)59 size_t OPENSSL_instrument_bus2(unsigned int *out, size_t cnt, size_t max)
60 {
61 if ((OPENSSL_sparcv9cap_P[0] & (SPARCV9_TICK_PRIVILEGED | SPARCV9_BLK)) == SPARCV9_BLK)
62 return _sparcv9_vis1_instrument_bus2(out, cnt, max);
63 else
64 return 0;
65 }
66
67 static sigjmp_buf common_jmp;
common_handler(int sig)68 static void common_handler(int sig)
69 {
70 siglongjmp(common_jmp, sig);
71 }
72
73 #if defined(__sun) && defined(__SVR4)
74 #if defined(__GNUC__) && __GNUC__ >= 2
75 extern unsigned int getisax(unsigned int vec[], unsigned int sz) __attribute__((weak));
76 #elif defined(__SUNPRO_C)
77 #pragma weak getisax
78 extern unsigned int getisax(unsigned int vec[], unsigned int sz);
79 #else
80 static unsigned int (*getisax)(unsigned int vec[], unsigned int sz) = NULL;
81 #endif
82 #endif
83
OPENSSL_cpuid_setup(void)84 void OPENSSL_cpuid_setup(void)
85 {
86 char *e;
87 struct sigaction common_act, ill_oact, bus_oact;
88 sigset_t all_masked, oset;
89 static int trigger = 0;
90
91 if (trigger)
92 return;
93 trigger = 1;
94
95 if ((e = getenv("OPENSSL_sparcv9cap"))) {
96 OPENSSL_sparcv9cap_P[0] = strtoul(e, NULL, 0);
97 if ((e = strchr(e, ':')))
98 OPENSSL_sparcv9cap_P[1] = strtoul(e + 1, NULL, 0);
99 return;
100 }
101
102 #if defined(__sun) && defined(__SVR4)
103 if (getisax != NULL) {
104 unsigned int vec[2] = { 0, 0 };
105
106 if (getisax(vec, 2)) {
107 if (vec[0] & 0x00020)
108 OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS1;
109 if (vec[0] & 0x00040)
110 OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS2;
111 if (vec[0] & 0x00080)
112 OPENSSL_sparcv9cap_P[0] |= SPARCV9_BLK;
113 if (vec[0] & 0x00100)
114 OPENSSL_sparcv9cap_P[0] |= SPARCV9_FMADD;
115 if (vec[0] & 0x00400)
116 OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS3;
117 if (vec[0] & 0x01000)
118 OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJHPCACE;
119 if (vec[0] & 0x02000)
120 OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJDESX;
121 if (vec[0] & 0x08000)
122 OPENSSL_sparcv9cap_P[0] |= SPARCV9_IMA;
123 if (vec[0] & 0x10000)
124 OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJAESX;
125 if (vec[1] & 0x00008)
126 OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS4;
127
128 /* reconstruct %cfr copy */
129 OPENSSL_sparcv9cap_P[1] = (vec[0] >> 17) & 0x3ff;
130 OPENSSL_sparcv9cap_P[1] |= (OPENSSL_sparcv9cap_P[1] & CFR_MONTMUL) << 1;
131 if (vec[0] & 0x20000000)
132 OPENSSL_sparcv9cap_P[1] |= CFR_CRC32C;
133 if (vec[1] & 0x00000020)
134 OPENSSL_sparcv9cap_P[1] |= CFR_XMPMUL;
135 if (vec[1] & 0x00000040)
136 OPENSSL_sparcv9cap_P[1] |= CFR_XMONTMUL | CFR_XMONTSQR;
137
138 /* Some heuristics */
139 /* all known VIS2-capable CPUs have unprivileged tick counter */
140 if (OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS2)
141 OPENSSL_sparcv9cap_P[0] &= ~SPARCV9_TICK_PRIVILEGED;
142
143 OPENSSL_sparcv9cap_P[0] |= SPARCV9_PREFER_FPU;
144
145 /* detect UltraSPARC-Tx, see sparccpud.S for details... */
146 if ((OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS1) && _sparcv9_vis1_instrument() >= 12)
147 OPENSSL_sparcv9cap_P[0] &= ~(SPARCV9_VIS1 | SPARCV9_PREFER_FPU);
148 }
149
150 if (sizeof(size_t) == 8)
151 OPENSSL_sparcv9cap_P[0] |= SPARCV9_64BIT_STACK;
152
153 return;
154 }
155 #endif
156
157 /* Initial value, fits UltraSPARC-I&II... */
158 OPENSSL_sparcv9cap_P[0] = SPARCV9_PREFER_FPU | SPARCV9_TICK_PRIVILEGED;
159
160 sigfillset(&all_masked);
161 sigdelset(&all_masked, SIGILL);
162 sigdelset(&all_masked, SIGTRAP);
163 #ifdef SIGEMT
164 sigdelset(&all_masked, SIGEMT);
165 #endif
166 sigdelset(&all_masked, SIGFPE);
167 sigdelset(&all_masked, SIGBUS);
168 sigdelset(&all_masked, SIGSEGV);
169 sigprocmask(SIG_SETMASK, &all_masked, &oset);
170
171 memset(&common_act, 0, sizeof(common_act));
172 common_act.sa_handler = common_handler;
173 common_act.sa_mask = all_masked;
174
175 sigaction(SIGILL, &common_act, &ill_oact);
176 sigaction(SIGBUS, &common_act, &bus_oact); /* T1 fails 16-bit ldda [on
177 * Linux] */
178
179 if (sigsetjmp(common_jmp, 1) == 0) {
180 _sparcv9_rdtick();
181 OPENSSL_sparcv9cap_P[0] &= ~SPARCV9_TICK_PRIVILEGED;
182 }
183
184 if (sigsetjmp(common_jmp, 1) == 0) {
185 _sparcv9_vis1_probe();
186 OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS1 | SPARCV9_BLK;
187 /* detect UltraSPARC-Tx, see sparccpud.S for details... */
188 if (_sparcv9_vis1_instrument() >= 12)
189 OPENSSL_sparcv9cap_P[0] &= ~(SPARCV9_VIS1 | SPARCV9_PREFER_FPU);
190 else {
191 _sparcv9_vis2_probe();
192 OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS2;
193 }
194 }
195
196 if (sigsetjmp(common_jmp, 1) == 0) {
197 _sparcv9_fmadd_probe();
198 OPENSSL_sparcv9cap_P[0] |= SPARCV9_FMADD;
199 }
200
201 /*
202 * VIS3 flag is tested independently from VIS1, unlike VIS2 that is,
203 * because VIS3 defines even integer instructions.
204 */
205 if (sigsetjmp(common_jmp, 1) == 0) {
206 _sparcv9_vis3_probe();
207 OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS3;
208 }
209
210 if (sigsetjmp(common_jmp, 1) == 0) {
211 _sparcv9_fjaesx_probe();
212 OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJAESX;
213 }
214
215 /*
216 * In wait for better solution _sparcv9_rdcfr is masked by
217 * VIS3 flag, because it goes to uninterruptible endless
218 * loop on UltraSPARC II running Solaris. Things might be
219 * different on Linux...
220 */
221 if ((OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3) && sigsetjmp(common_jmp, 1) == 0) {
222 OPENSSL_sparcv9cap_P[1] = (unsigned int)_sparcv9_rdcfr();
223 }
224
225 sigaction(SIGBUS, &bus_oact, NULL);
226 sigaction(SIGILL, &ill_oact, NULL);
227
228 sigprocmask(SIG_SETMASK, &oset, NULL);
229
230 if (sizeof(size_t) == 8)
231 OPENSSL_sparcv9cap_P[0] |= SPARCV9_64BIT_STACK;
232 #ifdef __linux
233 else {
234 int ret = syscall(340);
235
236 if (ret >= 0 && ret & 1)
237 OPENSSL_sparcv9cap_P[0] |= SPARCV9_64BIT_STACK;
238 }
239 #endif
240 }
241