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