diff options
author | Andy Polyakov <appro@openssl.org> | 2012-09-23 20:29:03 +0000 |
---|---|---|
committer | Andy Polyakov <appro@openssl.org> | 2012-09-23 20:29:03 +0000 |
commit | 1fda639ae756eb87f585b7d5114490d4ffe649a1 (patch) | |
tree | 2a358c9ee53d8da2dc6cf8b7d9958645a21feaed /crypto/sparcv9cap.c | |
parent | 4d88fc8173573b089aac0e0e53572802fc7594cb (diff) |
sparcv9cap.c: add SPARC-T4 feature detection.
Submitted by: David Miller
Diffstat (limited to 'crypto/sparcv9cap.c')
-rw-r--r-- | crypto/sparcv9cap.c | 83 |
1 files changed, 57 insertions, 26 deletions
diff --git a/crypto/sparcv9cap.c b/crypto/sparcv9cap.c index b961cbe3fa..149eb5232d 100644 --- a/crypto/sparcv9cap.c +++ b/crypto/sparcv9cap.c @@ -6,14 +6,12 @@ #include <sys/time.h> #include <openssl/bn.h> -#define SPARCV9_TICK_PRIVILEGED (1<<0) -#define SPARCV9_PREFER_FPU (1<<1) -#define SPARCV9_VIS1 (1<<2) -#define SPARCV9_VIS2 (1<<3) /* reserved */ -#define SPARCV9_FMADD (1<<4) /* reserved for SPARC64 V */ -#define SPARCV9_BLK (1<<5) /* VIS1 block copy */ +#include "sparc_arch.h" -static int OPENSSL_sparcv9cap_P=SPARCV9_TICK_PRIVILEGED; +#if defined(__GNUC__) && defined(__linux) +__attribute__((visibility("hidden"))) +#endif +unsigned int OPENSSL_sparcv9cap_P[2]={SPARCV9_TICK_PRIVILEGED,0}; int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np,const BN_ULONG *n0, int num) { @@ -21,7 +19,7 @@ int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_U int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np,const BN_ULONG *n0, int num); if (num>=8 && !(num&1) && - (OPENSSL_sparcv9cap_P&(SPARCV9_PREFER_FPU|SPARCV9_VIS1)) == + (OPENSSL_sparcv9cap_P[0]&(SPARCV9_PREFER_FPU|SPARCV9_VIS1)) == (SPARCV9_PREFER_FPU|SPARCV9_VIS1)) return bn_mul_mont_fpu(rp,ap,bp,np,n0,num); else @@ -33,12 +31,15 @@ void _sparcv9_vis1_probe(void); unsigned long _sparcv9_vis1_instrument(void); void _sparcv9_vis2_probe(void); void _sparcv9_fmadd_probe(void); +unsigned long _sparcv9_rdcfr(void); +void _sparcv9_vis3_probe(void); +unsigned long _sparcv9_random(void); size_t _sparcv9_vis1_instrument_bus(unsigned int *,size_t); size_t _sparcv8_vis1_instrument_bus2(unsigned int *,size_t,size_t); unsigned long OPENSSL_rdtsc(void) { - if (OPENSSL_sparcv9cap_P&SPARCV9_TICK_PRIVILEGED) + if (OPENSSL_sparcv9cap_P[0]&SPARCV9_TICK_PRIVILEGED) #if defined(__sun) && defined(__SVR4) return gethrtime(); #else @@ -50,7 +51,7 @@ unsigned long OPENSSL_rdtsc(void) size_t OPENSSL_instrument_bus(unsigned int *out,size_t cnt) { - if (OPENSSL_sparcv9cap_P&(SPARCV9_TICK_PRIVILEGED|SPARCV9_BLK) == + if (OPENSSL_sparcv9cap_P[0]&(SPARCV9_TICK_PRIVILEGED|SPARCV9_BLK) == SPARCV9_BLK) return _sparcv9_vis1_instrument_bus(out,cnt); else @@ -59,7 +60,7 @@ size_t OPENSSL_instrument_bus(unsigned int *out,size_t cnt) size_t OPENSSL_instrument_bus2(unsigned int *out,size_t cnt,size_t max) { - if (OPENSSL_sparcv9cap_P&(SPARCV9_TICK_PRIVILEGED|SPARCV9_BLK) == + if (OPENSSL_sparcv9cap_P[0]&(SPARCV9_TICK_PRIVILEGED|SPARCV9_BLK) == SPARCV9_BLK) return _sparcv9_vis1_instrument_bus2(out,cnt,max); else @@ -90,18 +91,18 @@ static int walk_nodename(di_node_t node, di_node_name_t di_node_name) if (!strcmp (name,"SUNW,UltraSPARC") || !strncmp(name,"SUNW,UltraSPARC-I",17)) /* covers II,III,IV */ { - OPENSSL_sparcv9cap_P |= SPARCV9_PREFER_FPU|SPARCV9_VIS1; + OPENSSL_sparcv9cap_P[0] |= SPARCV9_PREFER_FPU|SPARCV9_VIS1; /* %tick is privileged only on UltraSPARC-I/II, but not IIe */ if (name[14]!='\0' && name[17]!='\0' && name[18]!='\0') - OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED; + OPENSSL_sparcv9cap_P[0] &= ~SPARCV9_TICK_PRIVILEGED; return DI_WALK_TERMINATE; } /* This is expected to catch remaining UltraSPARCs, such as T1 */ else if (!strncmp(name,"SUNW,UltraSPARC",15)) { - OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED; + OPENSSL_sparcv9cap_P[0] &= ~SPARCV9_TICK_PRIVILEGED; return DI_WALK_TERMINATE; } @@ -120,7 +121,7 @@ void OPENSSL_cpuid_setup(void) if ((e=getenv("OPENSSL_sparcv9cap"))) { - OPENSSL_sparcv9cap_P=strtoul(e,NULL,0); + OPENSSL_sparcv9cap_P[0]=strtoul(e,NULL,0); return; } @@ -128,17 +129,17 @@ void OPENSSL_cpuid_setup(void) { if (strcmp(si,"sun4v")) /* FPU is preferred for all CPUs, but US-T1/2 */ - OPENSSL_sparcv9cap_P |= SPARCV9_PREFER_FPU; + OPENSSL_sparcv9cap_P[0] |= SPARCV9_PREFER_FPU; } if (sysinfo(SI_ISALIST,si,sizeof(si))>0) { if (strstr(si,"+vis")) - OPENSSL_sparcv9cap_P |= SPARCV9_VIS1|SPARCV9_BLK; + OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS1|SPARCV9_BLK; if (strstr(si,"+vis2")) { - OPENSSL_sparcv9cap_P |= SPARCV9_VIS2; - OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED; + OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS2; + OPENSSL_sparcv9cap_P[0] &= ~SPARCV9_TICK_PRIVILEGED; return; } } @@ -198,12 +199,14 @@ void OPENSSL_cpuid_setup(void) if ((e=getenv("OPENSSL_sparcv9cap"))) { - OPENSSL_sparcv9cap_P=strtoul(e,NULL,0); + OPENSSL_sparcv9cap_P[0]=strtoul(e,NULL,0); + if ((e=strchr(e,':'))) + OPENSSL_sparcv9cap_P[1]=strtoul(e+1,NULL,0); return; } /* Initial value, fits UltraSPARC-I&II... */ - OPENSSL_sparcv9cap_P = SPARCV9_PREFER_FPU|SPARCV9_TICK_PRIVILEGED; + OPENSSL_sparcv9cap_P[0] = SPARCV9_PREFER_FPU|SPARCV9_TICK_PRIVILEGED; sigfillset(&all_masked); sigdelset(&all_masked,SIGILL); @@ -226,27 +229,55 @@ void OPENSSL_cpuid_setup(void) if (sigsetjmp(common_jmp,1) == 0) { _sparcv9_rdtick(); - OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED; + OPENSSL_sparcv9cap_P[0] &= ~SPARCV9_TICK_PRIVILEGED; } if (sigsetjmp(common_jmp,1) == 0) { _sparcv9_vis1_probe(); - OPENSSL_sparcv9cap_P |= SPARCV9_VIS1|SPARCV9_BLK; + OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS1|SPARCV9_BLK; /* detect UltraSPARC-Tx, see sparccpud.S for details... */ if (_sparcv9_vis1_instrument() >= 12) - OPENSSL_sparcv9cap_P &= ~(SPARCV9_VIS1|SPARCV9_PREFER_FPU); + OPENSSL_sparcv9cap_P[0] &= ~(SPARCV9_VIS1|SPARCV9_PREFER_FPU); else { _sparcv9_vis2_probe(); - OPENSSL_sparcv9cap_P |= SPARCV9_VIS2; + OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS2; } } if (sigsetjmp(common_jmp,1) == 0) { _sparcv9_fmadd_probe(); - OPENSSL_sparcv9cap_P |= SPARCV9_FMADD; + OPENSSL_sparcv9cap_P[0] |= SPARCV9_FMADD; + } + + /* + * VIS3 flag is tested independently from VIS1, unlike VIS2 that is, + * because VIS3 defines even integer instructions. + */ + if (sigsetjmp(common_jmp,1) == 0) + { + _sparcv9_vis3_probe(); + OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS3; + } + + if (sigsetjmp(common_jmp,1) == 0) + { + (void)_sparcv9_random(); + OPENSSL_sparcv9cap_P[0] |= SPARCV9_RANDOM; + } + + /* + * In wait for better solution _sparcv9_rdcfr is masked by + * VIS3 flag, because it goes to uninterruptable endless + * loop on UltraSPARC II running Solaris. Things might be + * different on Linux... + */ + if ((OPENSSL_sparcv9cap_P[0]&SPARCV9_VIS3) && + sigsetjmp(common_jmp,1) == 0) + { + OPENSSL_sparcv9cap_P[1] = (unsigned int)_sparcv9_rdcfr(); } sigaction(SIGBUS,&bus_oact,NULL); |