Home | History | Annotate | Download | only in crypto
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <setjmp.h>
      5 #include <signal.h>
      6 #include <sys/time.h>
      7 #include <openssl/bn.h>
      8 
      9 #define SPARCV9_TICK_PRIVILEGED	(1<<0)
     10 #define SPARCV9_PREFER_FPU	(1<<1)
     11 #define SPARCV9_VIS1		(1<<2)
     12 #define SPARCV9_VIS2		(1<<3)	/* reserved */
     13 #define SPARCV9_FMADD		(1<<4)	/* reserved for SPARC64 V */
     14 
     15 static int OPENSSL_sparcv9cap_P=SPARCV9_TICK_PRIVILEGED;
     16 
     17 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)
     18 	{
     19 	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);
     20 	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);
     21 
     22 	if ((OPENSSL_sparcv9cap_P&(SPARCV9_PREFER_FPU|SPARCV9_VIS1)) ==
     23 		(SPARCV9_PREFER_FPU|SPARCV9_VIS1))
     24 		return bn_mul_mont_fpu(rp,ap,bp,np,n0,num);
     25 	else
     26 		return bn_mul_mont_int(rp,ap,bp,np,n0,num);
     27 	}
     28 
     29 unsigned long	_sparcv9_rdtick(void);
     30 void		_sparcv9_vis1_probe(void);
     31 unsigned long	_sparcv9_vis1_instrument(void);
     32 void		_sparcv9_vis2_probe(void);
     33 void		_sparcv9_fmadd_probe(void);
     34 
     35 unsigned long OPENSSL_rdtsc(void)
     36 	{
     37 	if (OPENSSL_sparcv9cap_P&SPARCV9_TICK_PRIVILEGED)
     38 #if defined(__sun) && defined(__SVR4)
     39 		return gethrtime();
     40 #else
     41 		return 0;
     42 #endif
     43 	else
     44 		return _sparcv9_rdtick();
     45 	}
     46 
     47 #if 0 && defined(__sun) && defined(__SVR4)
     48 /* This code path is disabled, because of incompatibility of
     49  * libdevinfo.so.1 and libmalloc.so.1 (see below for details)
     50  */
     51 #include <malloc.h>
     52 #include <dlfcn.h>
     53 #include <libdevinfo.h>
     54 #include <sys/systeminfo.h>
     55 
     56 typedef di_node_t (*di_init_t)(const char *,uint_t);
     57 typedef void      (*di_fini_t)(di_node_t);
     58 typedef char *    (*di_node_name_t)(di_node_t);
     59 typedef int       (*di_walk_node_t)(di_node_t,uint_t,di_node_name_t,int (*)(di_node_t,di_node_name_t));
     60 
     61 #define DLLINK(h,name) (name=(name##_t)dlsym((h),#name))
     62 
     63 static int walk_nodename(di_node_t node, di_node_name_t di_node_name)
     64 	{
     65 	char *name = (*di_node_name)(node);
     66 
     67 	/* This is expected to catch all UltraSPARC flavors prior T1 */
     68 	if (!strcmp (name,"SUNW,UltraSPARC") ||
     69 	    !strncmp(name,"SUNW,UltraSPARC-I",17))  /* covers II,III,IV */
     70 		{
     71 		OPENSSL_sparcv9cap_P |= SPARCV9_PREFER_FPU|SPARCV9_VIS1;
     72 
     73 		/* %tick is privileged only on UltraSPARC-I/II, but not IIe */
     74 		if (name[14]!='\0' && name[17]!='\0' && name[18]!='\0')
     75 			OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED;
     76 
     77 		return DI_WALK_TERMINATE;
     78 		}
     79 	/* This is expected to catch remaining UltraSPARCs, such as T1 */
     80 	else if (!strncmp(name,"SUNW,UltraSPARC",15))
     81 		{
     82 		OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED;
     83 
     84 		return DI_WALK_TERMINATE;
     85 		}
     86 
     87 	return DI_WALK_CONTINUE;
     88 	}
     89 
     90 void OPENSSL_cpuid_setup(void)
     91 	{
     92 	void *h;
     93 	char *e,si[256];
     94 	static int trigger=0;
     95 
     96 	if (trigger) return;
     97 	trigger=1;
     98 
     99 	if ((e=getenv("OPENSSL_sparcv9cap")))
    100 		{
    101 		OPENSSL_sparcv9cap_P=strtoul(e,NULL,0);
    102 		return;
    103 		}
    104 
    105 	if (sysinfo(SI_MACHINE,si,sizeof(si))>0)
    106 		{
    107 		if (strcmp(si,"sun4v"))
    108 			/* FPU is preferred for all CPUs, but US-T1/2 */
    109 			OPENSSL_sparcv9cap_P |= SPARCV9_PREFER_FPU;
    110 		}
    111 
    112 	if (sysinfo(SI_ISALIST,si,sizeof(si))>0)
    113 		{
    114 		if (strstr(si,"+vis"))
    115 			OPENSSL_sparcv9cap_P |= SPARCV9_VIS1;
    116 		if (strstr(si,"+vis2"))
    117 			{
    118 			OPENSSL_sparcv9cap_P |= SPARCV9_VIS2;
    119 			OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED;
    120 			return;
    121 			}
    122 		}
    123 #ifdef M_KEEP
    124 	/*
    125 	 * Solaris libdevinfo.so.1 is effectively incomatible with
    126 	 * libmalloc.so.1. Specifically, if application is linked with
    127 	 * -lmalloc, it crashes upon startup with SIGSEGV in
    128 	 * free(3LIBMALLOC) called by di_fini. Prior call to
    129 	 * mallopt(M_KEEP,0) somehow helps... But not always...
    130 	 */
    131 	if ((h = dlopen(NULL,RTLD_LAZY)))
    132 		{
    133 		union { void *p; int (*f)(int,int); } sym;
    134 		if ((sym.p = dlsym(h,"mallopt"))) (*sym.f)(M_KEEP,0);
    135 		dlclose(h);
    136 		}
    137 #endif
    138 	if ((h = dlopen("libdevinfo.so.1",RTLD_LAZY))) do
    139 		{
    140 		di_init_t	di_init;
    141 		di_fini_t	di_fini;
    142 		di_walk_node_t	di_walk_node;
    143 		di_node_name_t	di_node_name;
    144 		di_node_t	root_node;
    145 
    146 		if (!DLLINK(h,di_init))		break;
    147 		if (!DLLINK(h,di_fini))		break;
    148 		if (!DLLINK(h,di_walk_node))	break;
    149 		if (!DLLINK(h,di_node_name))	break;
    150 
    151 		if ((root_node = (*di_init)("/",DINFOSUBTREE))!=DI_NODE_NIL)
    152 			{
    153 			(*di_walk_node)(root_node,DI_WALK_SIBFIRST,
    154 					di_node_name,walk_nodename);
    155 			(*di_fini)(root_node);
    156 			}
    157 		} while(0);
    158 
    159 	if (h) dlclose(h);
    160 	}
    161 
    162 #else
    163 
    164 static sigjmp_buf common_jmp;
    165 static void common_handler(int sig) { siglongjmp(common_jmp,sig); }
    166 
    167 void OPENSSL_cpuid_setup(void)
    168 	{
    169 	char *e;
    170 	struct sigaction	common_act,ill_oact,bus_oact;
    171 	sigset_t		all_masked,oset;
    172 	int			sig;
    173 	static int trigger=0;
    174 
    175 	if (trigger) return;
    176 	trigger=1;
    177 
    178 	if ((e=getenv("OPENSSL_sparcv9cap")))
    179 		{
    180 		OPENSSL_sparcv9cap_P=strtoul(e,NULL,0);
    181 		return;
    182 		}
    183 
    184 	/* Initial value, fits UltraSPARC-I&II... */
    185 	OPENSSL_sparcv9cap_P = SPARCV9_PREFER_FPU|SPARCV9_TICK_PRIVILEGED;
    186 
    187 	sigfillset(&all_masked);
    188 	sigdelset(&all_masked,SIGILL);
    189 	sigdelset(&all_masked,SIGTRAP);
    190 #ifdef SIGEMT
    191 	sigdelset(&all_masked,SIGEMT);
    192 #endif
    193 	sigdelset(&all_masked,SIGFPE);
    194 	sigdelset(&all_masked,SIGBUS);
    195 	sigdelset(&all_masked,SIGSEGV);
    196 	sigprocmask(SIG_SETMASK,&all_masked,&oset);
    197 
    198 	memset(&common_act,0,sizeof(common_act));
    199 	common_act.sa_handler = common_handler;
    200 	common_act.sa_mask    = all_masked;
    201 
    202 	sigaction(SIGILL,&common_act,&ill_oact);
    203 	sigaction(SIGBUS,&common_act,&bus_oact);/* T1 fails 16-bit ldda [on Linux] */
    204 
    205 	if (sigsetjmp(common_jmp,1) == 0)
    206 		{
    207 		_sparcv9_rdtick();
    208 		OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED;
    209 		}
    210 
    211 	if (sigsetjmp(common_jmp,1) == 0)
    212 		{
    213 		_sparcv9_vis1_probe();
    214 		OPENSSL_sparcv9cap_P |= SPARCV9_VIS1;
    215 		/* detect UltraSPARC-Tx, see sparccpud.S for details... */
    216 		if (_sparcv9_vis1_instrument() >= 12)
    217 			OPENSSL_sparcv9cap_P &= ~(SPARCV9_VIS1|SPARCV9_PREFER_FPU);
    218 		else
    219 			{
    220 			_sparcv9_vis2_probe();
    221 			OPENSSL_sparcv9cap_P |= SPARCV9_VIS2;
    222 			}
    223 		}
    224 
    225 	if (sigsetjmp(common_jmp,1) == 0)
    226 		{
    227 		_sparcv9_fmadd_probe();
    228 		OPENSSL_sparcv9cap_P |= SPARCV9_FMADD;
    229 		}
    230 
    231 	sigaction(SIGBUS,&bus_oact,NULL);
    232 	sigaction(SIGILL,&ill_oact,NULL);
    233 
    234 	sigprocmask(SIG_SETMASK,&oset,NULL);
    235 	}
    236 
    237 #endif
    238