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