diff options
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/sparccpuid.S | 36 | ||||
-rw-r--r-- | crypto/sparcv9cap.c | 133 |
2 files changed, 150 insertions, 19 deletions
diff --git a/crypto/sparccpuid.S b/crypto/sparccpuid.S index c17350fc89..ac57472dd6 100644 --- a/crypto/sparccpuid.S +++ b/crypto/sparccpuid.S @@ -34,7 +34,8 @@ OPENSSL_wipe_cpu: nop call .PIC.zero.up mov .zero-(.-4),%o0 - ldd [%o0],%f0 + ld [%o0],%f0 + ld [%o0],%f1 subcc %g0,1,%o0 ! Following is V9 "rd %ccr,%o0" instruction. However! V8 @@ -166,6 +167,7 @@ walk_reg_wins: .global OPENSSL_atomic_add .type OPENSSL_atomic_add,#function +.align 32 OPENSSL_atomic_add: #ifndef ABI64 subcc %g0,1,%o2 @@ -213,27 +215,23 @@ OPENSSL_atomic_add: sra %o0,%g0,%o0 ! we return signed int, remember? .size OPENSSL_atomic_add,.-OPENSSL_atomic_add -.global OPENSSL_rdtsc +.global OPENSSL_rdtick +.align 32 +OPENSSL_rdtick: subcc %g0,1,%o0 .word 0x91408000 !rd %ccr,%o0 cmp %o0,0x99 - bne .notsc + bne .notick xor %o0,%o0,%o0 - save %sp,FRAME-16,%sp - mov 513,%o0 !SI_PLATFORM - add %sp,BIAS+16,%o1 - call sysinfo - mov 256,%o2 - - add %sp,BIAS-16,%o1 - ld [%o1],%l0 - ld [%o1+4],%l1 - ld [%o1+8],%l2 - mov %lo('SUNW'),%l3 - ret - restore -.notsc: + .word 0x91410000 !rd %tick,%o0 + retl + .word 0x93323020 !srlx %o2,32,%o1 +.notick: retl + xor %o1,%o1,%o1 +.type OPENSSL_rdtick,#function +.size OPENSSL_rdtick,.-OPENSSL_rdtick + +.section ".init",#alloc,#execinstr + call OPENSSL_cpuid_setup nop -.type OPENSSL_rdtsc,#function -.size OPENSSL_rdtsc,.-OPENSSL_atomic_add diff --git a/crypto/sparcv9cap.c b/crypto/sparcv9cap.c new file mode 100644 index 0000000000..7012f78604 --- /dev/null +++ b/crypto/sparcv9cap.c @@ -0,0 +1,133 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#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 */ +static int OPENSSL_sparcv9cap_P=SPARCV9_TICK_PRIVILEGED; + +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) + { + int bn_mul_mont_fpu(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np,const BN_ULONG *n0, int num); + 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 (OPENSSL_sparcv9cap_P&(SPARCV9_PREFER_FPU|SPARCV9_VIS1) == + (SPARCV9_PREFER_FPU|SPARCV9_VIS1)) + return bn_mul_mont_fpu(rp,ap,bp,np,n0,num); + else + return bn_mul_mont_int(rp,ap,bp,np,n0,num); + } + +unsigned long OPENSSL_rdtsc(void) + { + unsigned long OPENSSL_rdtick(void); + + if (OPENSSL_sparcv9cap_P&SPARCV9_TICK_PRIVILEGED) +#if defined(__sun) && defined(__SVR4) + return gethrtime(); +#else + return 0; +#endif + else + return OPENSSL_rdtick(); + } + +#if defined(__sun) && defined(__SVR4) + +#include <dlfcn.h> +#include <libdevinfo.h> + +typedef di_node_t (*di_init_t)(const char *,uint_t); +typedef void (*di_fini_t)(di_node_t); +typedef char * (*di_node_name_t)(di_node_t); +typedef int (*di_walk_node_t)(di_node_t,uint_t,di_node_name_t,int (*)(di_node_t,di_node_name_t)); + +#define DLLINK(h,name) (name=(name##_t)dlsym((h),#name)) + +static int walk_nodename(di_node_t node, di_node_name_t di_node_name) + { + char *name = (*di_node_name)(node); + + /* This is expected to catch all UltraSPARC flavors prior T1 */ + if (!strcmp (name,"SUNW,UltraSPARC") || + !strncmp(name,"SUNW,UltraSPARC-I",17)) + { + OPENSSL_sparcv9cap_P |= SPARCV9_PREFER_FPU|SPARCV9_VIS1; + + /* %tick is privileged only on UltraSPARC-I/II */ + if (name[14]!='\0' && name[17]!='\0' && name[18]!='\0') + OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED; + + return DI_WALK_TERMINATE; + } + /* This is expected to catch remaining UltraSPARC T1 */ + else if (!strncmp(name,"SUNW,UltraSPARC",15)) + { + OPENSSL_sparcv9cap_P |= SPARCV9_VIS1; + OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED; + } + + return DI_WALK_CONTINUE; + } + +void OPENSSL_cpuid_setup(void) + { + void *h; + char *e; + + if (e=getenv("OPENSSL_sparcv9cap")) + { + OPENSSL_sparcv9cap_P=strtoul(e,NULL,0); + return; + } + + if (h = dlopen("libdevinfo.so.1",RTLD_LAZY)) do + { + di_init_t di_init; + di_fini_t di_fini; + di_walk_node_t di_walk_node; + di_node_name_t di_node_name; + di_node_t root_node; + + if (!DLLINK(h,di_init)) break; + if (!DLLINK(h,di_fini)) break; + if (!DLLINK(h,di_walk_node)) break; + if (!DLLINK(h,di_node_name)) break; + + if ((root_node = (*di_init)("/",DINFOSUBTREE))!=DI_NODE_NIL) + { + (*di_walk_node)(root_node,DI_WALK_SIBFIRST, + di_node_name,walk_nodename); + (*di_fini)(root_node); + } + } while(0); + + if (h) dlclose(h); + } + +#elif defined(__linux) + +void OPENSSL_cpuid_setup(void) + { + char *e; + + if (e=getenv("OPENSSL_sparcv9cap")) + { + OPENSSL_sparcv9cap_P=strtoul(env,NULL,0); + return; + } + + /* Linux apparently supports UltraSPARC-I/II/III only */ + OPENSSL_sparcv9cap_P |= SPARCV9_PREFER_FPU|SPARCV9_VIS1; + } + +#else + +void OPENSSL_cpuid_setup(void) {} + +#endif |