8 #include <openssl/bn.h>
10 #include "sparc_arch.h"
12 #if defined(__GNUC__) && defined(__linux)
13 __attribute__ ((visibility("hidden")))
15 unsigned int OPENSSL_sparcv9cap_P[2] = { SPARCV9_TICK_PRIVILEGED, 0 };
17 int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
18 const BN_ULONG *np, const BN_ULONG *n0, int num)
20 int bn_mul_mont_vis3(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
21 const BN_ULONG *np, const BN_ULONG *n0, int num);
22 int bn_mul_mont_fpu(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
23 const BN_ULONG *np, const BN_ULONG *n0, int num);
24 int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
25 const BN_ULONG *np, const BN_ULONG *n0, int num);
27 if (!(num & 1) && num >= 6) {
28 if ((num & 15) == 0 && num <= 64 &&
29 (OPENSSL_sparcv9cap_P[1] & (CFR_MONTMUL | CFR_MONTSQR)) ==
30 (CFR_MONTMUL | CFR_MONTSQR)) {
31 typedef int (*bn_mul_mont_f) (BN_ULONG *rp, const BN_ULONG *ap,
35 int bn_mul_mont_t4_8(BN_ULONG *rp, const BN_ULONG *ap,
36 const BN_ULONG *bp, const BN_ULONG *np,
38 int bn_mul_mont_t4_16(BN_ULONG *rp, const BN_ULONG *ap,
39 const BN_ULONG *bp, const BN_ULONG *np,
41 int bn_mul_mont_t4_24(BN_ULONG *rp, const BN_ULONG *ap,
42 const BN_ULONG *bp, const BN_ULONG *np,
44 int bn_mul_mont_t4_32(BN_ULONG *rp, const BN_ULONG *ap,
45 const BN_ULONG *bp, const BN_ULONG *np,
47 static const bn_mul_mont_f funcs[4] = {
48 bn_mul_mont_t4_8, bn_mul_mont_t4_16,
49 bn_mul_mont_t4_24, bn_mul_mont_t4_32
51 bn_mul_mont_f worker = funcs[num / 16 - 1];
53 if ((*worker) (rp, ap, bp, np, n0))
55 /* retry once and fall back */
56 if ((*worker) (rp, ap, bp, np, n0))
58 return bn_mul_mont_vis3(rp, ap, bp, np, n0, num);
60 if ((OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3))
61 return bn_mul_mont_vis3(rp, ap, bp, np, n0, num);
64 * bn_mul_mont_fpu doesn't use FMADD, we just use the
65 * flag to detect when FPU path is preferable in cases
66 * when current heuristics is unreliable. [it works
67 * out because FMADD-capable processors where FPU
68 * code path is undesirable are also VIS3-capable and
69 * VIS3 code path takes precedence.]
71 ( (OPENSSL_sparcv9cap_P[0] & SPARCV9_FMADD) ||
72 (OPENSSL_sparcv9cap_P[0] &
73 (SPARCV9_PREFER_FPU | SPARCV9_VIS1)) ==
74 (SPARCV9_PREFER_FPU | SPARCV9_VIS1) ))
75 return bn_mul_mont_fpu(rp, ap, bp, np, n0, num);
77 return bn_mul_mont_int(rp, ap, bp, np, n0, num);
80 unsigned long _sparcv9_rdtick(void);
81 void _sparcv9_vis1_probe(void);
82 unsigned long _sparcv9_vis1_instrument(void);
83 void _sparcv9_vis2_probe(void);
84 void _sparcv9_fmadd_probe(void);
85 unsigned long _sparcv9_rdcfr(void);
86 void _sparcv9_vis3_probe(void);
87 unsigned long _sparcv9_random(void);
88 size_t _sparcv9_vis1_instrument_bus(unsigned int *, size_t);
89 size_t _sparcv9_vis1_instrument_bus2(unsigned int *, size_t, size_t);
91 unsigned long OPENSSL_rdtsc(void)
93 if (OPENSSL_sparcv9cap_P[0] & SPARCV9_TICK_PRIVILEGED)
94 #if defined(__sun) && defined(__SVR4)
100 return _sparcv9_rdtick();
103 size_t OPENSSL_instrument_bus(unsigned int *out, size_t cnt)
105 if ((OPENSSL_sparcv9cap_P[0] & (SPARCV9_TICK_PRIVILEGED | SPARCV9_BLK)) ==
107 return _sparcv9_vis1_instrument_bus(out, cnt);
112 size_t OPENSSL_instrument_bus2(unsigned int *out, size_t cnt, size_t max)
114 if ((OPENSSL_sparcv9cap_P[0] & (SPARCV9_TICK_PRIVILEGED | SPARCV9_BLK)) ==
116 return _sparcv9_vis1_instrument_bus2(out, cnt, max);
121 static sigjmp_buf common_jmp;
122 static void common_handler(int sig)
124 siglongjmp(common_jmp, sig);
127 #if defined(__sun) && defined(__SVR4)
128 # if defined(__GNUC__) && __GNUC__>=2
129 extern unsigned int getisax(unsigned int vec[], unsigned int sz) __attribute__ ((weak));
130 # elif defined(__SUNPRO_C)
132 extern unsigned int getisax(unsigned int vec[], unsigned int sz);
134 static unsigned int (*getisax) (unsigned int vec[], unsigned int sz) = NULL;
138 void OPENSSL_cpuid_setup(void)
141 struct sigaction common_act, ill_oact, bus_oact;
142 sigset_t all_masked, oset;
143 static int trigger = 0;
149 if ((e = getenv("OPENSSL_sparcv9cap"))) {
150 OPENSSL_sparcv9cap_P[0] = strtoul(e, NULL, 0);
151 if ((e = strchr(e, ':')))
152 OPENSSL_sparcv9cap_P[1] = strtoul(e + 1, NULL, 0);
156 #if defined(__sun) && defined(__SVR4)
157 if (getisax != NULL) {
160 if (getisax (vec,1)) {
161 if (vec[0]&0x00020) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS1;
162 if (vec[0]&0x00040) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS2;
163 if (vec[0]&0x00080) OPENSSL_sparcv9cap_P[0] |= SPARCV9_BLK;
164 if (vec[0]&0x00100) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FMADD;
165 if (vec[0]&0x00400) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS3;
166 if (vec[0]&0x01000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJHPCACE;
167 if (vec[0]&0x02000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJDESX;
168 if (vec[0]&0x08000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_IMA;
169 if (vec[0]&0x10000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJAESX;
170 if (vec[1]&0x00008) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS4;
172 /* reconstruct %cfr copy */
173 OPENSSL_sparcv9cap_P[1] = (vec[0]>>17)&0x3ff;
174 OPENSSL_sparcv9cap_P[1] |= (OPENSSL_sparcv9cap_P[1]&CFR_MONTMUL)<<1;
175 if (vec[0]&0x20000000) OPENSSL_sparcv9cap_P[1] |= CFR_CRC32C;
176 if (vec[1]&0x00000020) OPENSSL_sparcv9cap_P[1] |= CFR_XMPMUL;
177 if (vec[1]&0x00000040)
178 OPENSSL_sparcv9cap_P[1] |= CFR_XMONTMUL|CFR_XMONTSQR;
180 /* Some heuristics */
181 /* all known VIS2-capable CPUs have unprivileged tick counter */
182 if (OPENSSL_sparcv9cap_P[0]&SPARCV9_VIS2)
183 OPENSSL_sparcv9cap_P[0] &= ~SPARCV9_TICK_PRIVILEGED;
185 OPENSSL_sparcv9cap_P[0] |= SPARCV9_PREFER_FPU;
187 /* detect UltraSPARC-Tx, see sparccpud.S for details... */
188 if ((OPENSSL_sparcv9cap_P[0]&SPARCV9_VIS1) &&
189 _sparcv9_vis1_instrument() >= 12)
190 OPENSSL_sparcv9cap_P[0] &= ~(SPARCV9_VIS1 | SPARCV9_PREFER_FPU);
193 if (sizeof(size_t) == 8)
194 OPENSSL_sparcv9cap_P[0] |= SPARCV9_64BIT_STACK;
200 /* Initial value, fits UltraSPARC-I&II... */
201 OPENSSL_sparcv9cap_P[0] = SPARCV9_PREFER_FPU | SPARCV9_TICK_PRIVILEGED;
203 sigfillset(&all_masked);
204 sigdelset(&all_masked, SIGILL);
205 sigdelset(&all_masked, SIGTRAP);
207 sigdelset(&all_masked, SIGEMT);
209 sigdelset(&all_masked, SIGFPE);
210 sigdelset(&all_masked, SIGBUS);
211 sigdelset(&all_masked, SIGSEGV);
212 sigprocmask(SIG_SETMASK, &all_masked, &oset);
214 memset(&common_act, 0, sizeof(common_act));
215 common_act.sa_handler = common_handler;
216 common_act.sa_mask = all_masked;
218 sigaction(SIGILL, &common_act, &ill_oact);
219 sigaction(SIGBUS, &common_act, &bus_oact); /* T1 fails 16-bit ldda [on
222 if (sigsetjmp(common_jmp, 1) == 0) {
224 OPENSSL_sparcv9cap_P[0] &= ~SPARCV9_TICK_PRIVILEGED;
227 if (sigsetjmp(common_jmp, 1) == 0) {
228 _sparcv9_vis1_probe();
229 OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS1 | SPARCV9_BLK;
230 /* detect UltraSPARC-Tx, see sparccpud.S for details... */
231 if (_sparcv9_vis1_instrument() >= 12)
232 OPENSSL_sparcv9cap_P[0] &= ~(SPARCV9_VIS1 | SPARCV9_PREFER_FPU);
234 _sparcv9_vis2_probe();
235 OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS2;
239 if (sigsetjmp(common_jmp, 1) == 0) {
240 _sparcv9_fmadd_probe();
241 OPENSSL_sparcv9cap_P[0] |= SPARCV9_FMADD;
245 * VIS3 flag is tested independently from VIS1, unlike VIS2 that is,
246 * because VIS3 defines even integer instructions.
248 if (sigsetjmp(common_jmp, 1) == 0) {
249 _sparcv9_vis3_probe();
250 OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS3;
253 if (sigsetjmp(common_jmp, 1) == 0) {
254 _sparcv9_fjaesx_probe();
255 OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJAESX;
259 * In wait for better solution _sparcv9_rdcfr is masked by
260 * VIS3 flag, because it goes to uninterruptable endless
261 * loop on UltraSPARC II running Solaris. Things might be
262 * different on Linux...
264 if ((OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3) &&
265 sigsetjmp(common_jmp, 1) == 0) {
266 OPENSSL_sparcv9cap_P[1] = (unsigned int)_sparcv9_rdcfr();
269 sigaction(SIGBUS, &bus_oact, NULL);
270 sigaction(SIGILL, &ill_oact, NULL);
272 sigprocmask(SIG_SETMASK, &oset, NULL);
274 if (sizeof(size_t) == 8)
275 OPENSSL_sparcv9cap_P[0] |= SPARCV9_64BIT_STACK;
278 int ret = syscall(340);
280 if (ret >= 0 && ret & 1)
281 OPENSSL_sparcv9cap_P[0] |= SPARCV9_64BIT_STACK;