Commit c06b0f3d authored by Andy Polyakov's avatar Andy Polyakov
Browse files

sparccpuid module update.

parent 68ea6068
Loading
Loading
Loading
Loading
+17 −19
Original line number Diff line number Diff line
@@ -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

crypto/sparcv9cap.c

0 → 100644
+133 −0
Original line number Diff line number Diff line
#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