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 (num>=8 && !(num&1) &&
     23 	    (OPENSSL_sparcv9cap_P&(SPARCV9_PREFER_FPU|SPARCV9_VIS1)) ==
     24 		(SPARCV9_PREFER_FPU|SPARCV9_VIS1))
     25 		return bn_mul_mont_fpu(rp,ap,bp,np,n0,num);
     26 	else
     27 		return bn_mul_mont_int(rp,ap,bp,np,n0,num);
     28 	}
     29 
     30 unsigned long	_sparcv9_rdtick(void);
     31 void		_sparcv9_vis1_probe(void);
     32 unsigned long	_sparcv9_vis1_instrument(void);
     33 void		_sparcv9_vis2_probe(void);
     34 void		_sparcv9_fmadd_probe(void);
     35 
     36 unsigned long OPENSSL_rdtsc(void)
     37 	{
     38 	if (OPENSSL_sparcv9cap_P&SPARCV9_TICK_PRIVILEGED)
     39 #if defined(__sun) && defined(__SVR4)
     40 		return gethrtime();
     41 #else
     42 		return 0;
     43 #endif
     44 	else
     45 		return _sparcv9_rdtick();
     46 	}
     47 
     48 #if 0 && defined(__sun) && defined(__SVR4)
     49 /* This code path is disabled, because of incompatibility of
     50  * libdevinfo.so.1 and libmalloc.so.1 (see below for details)
     51  */
     52 #include <malloc.h>
     53 #include <dlfcn.h>
     54 #include <libdevinfo.h>
     55 #include <sys/systeminfo.h>
     56 
     57 typedef di_node_t (*di_init_t)(const char *,uint_t);
     58 typedef void      (*di_fini_t)(di_node_t);
     59 typedef char *    (*di_node_name_t)(di_node_t);
     60 typedef int       (*di_walk_node_t)(di_node_t,uint_t,di_node_name_t,int (*)(di_node_t,di_node_name_t));
     61 
     62 #define DLLINK(h,name) (name=(name##_t)dlsym((h),#name))
     63 
     64 static int walk_nodename(di_node_t node, di_node_name_t di_node_name)
     65 	{
     66 	char *name = (*di_node_name)(node);
     67 
     68 	/* This is expected to catch all UltraSPARC flavors prior T1 */
     69 	if (!strcmp (name,"SUNW,UltraSPARC") ||
     70 	    !strncmp(name,"SUNW,UltraSPARC-I",17))  /* covers II,III,IV */
     71 		{
     72 		OPENSSL_sparcv9cap_P |= SPARCV9_PREFER_FPU|SPARCV9_VIS1;
     73 
     74 		/* %tick is privileged only on UltraSPARC-I/II, but not IIe */
     75 		if (name[14]!='\0' && name[17]!='\0' && name[18]!='\0')
     76 			OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED;
     77 
     78 		return DI_WALK_TERMINATE;
     79 		}
     80 	/* This is expected to catch remaining UltraSPARCs, such as T1 */
     81 	else if (!strncmp(name,"SUNW,UltraSPARC",15))
     82 		{
     83 		OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED;
     84 
     85 		return DI_WALK_TERMINATE;
     86 		}
     87 
     88 	return DI_WALK_CONTINUE;
     89 	}
     90 
     91 void OPENSSL_cpuid_setup(void)
     92 	{
     93 	void *h;
     94 	char *e,si[256];
     95 	static int trigger=0;
     96 
     97 	if (trigger) return;
     98 	trigger=1;
     99 
    100 	if ((e=getenv("OPENSSL_sparcv9cap")))
    101 		{
    102 		OPENSSL_sparcv9cap_P=strtoul(e,NULL,0);
    103 		return;
    104 		}
    105 
    106 	if (sysinfo(SI_MACHINE,si,sizeof(si))>0)
    107 		{
    108 		if (strcmp(si,"sun4v"))
    109 			/* FPU is preferred for all CPUs, but US-T1/2 */
    110 			OPENSSL_sparcv9cap_P |= SPARCV9_PREFER_FPU;
    111 		}
    112 
    113 	if (sysinfo(SI_ISALIST,si,sizeof(si))>0)
    114 		{
    115 		if (strstr(si,"+vis"))
    116 			OPENSSL_sparcv9cap_P |= SPARCV9_VIS1;
    117 		if (strstr(si,"+vis2"))
    118 			{
    119 			OPENSSL_sparcv9cap_P |= SPARCV9_VIS2;
    120 			OPENSSL_sparcv9cap_P &= ~SPARCV9_TICK_PRIVILEGED;
    121 			return;
    122 			}
    123 		}
    124 #ifdef M_KEEP
    125 	/*
    126 	 * Solaris libdevinfo.so.1 is effectively incomatible with
    127 	 * libmalloc.so.1. Specifically, if application is linked with
    128 	 * -lmalloc, it crashes upon startup with SIGSEGV in
    129 	 * free(3LIBMALLOC) called by di_fini. Prior call to
    130 	 * mallopt(M_KEEP,0) somehow helps... But not always...
    131 	 */
    132 	if ((h = dlopen(NULL,RTLD_LAZY)))
    133 		{
    134 		union { void *p; int (*f)(int,int); } sym;
    135 		if ((sym.p = dlsym(h,"mallopt"))) (*sym.f)(M_KEEP,0);
    136 		dlclose(h);
    137 		}
    138 #endif
    139 	if ((h = dlopen("libdevinfo.so.1",RTLD_LAZY))) do
    140 		{
    141 		di_init_t	di_init;
    142 		di_fini_t	di_fini;
    143 		di_walk_node_t	di_walk_node;
    144 		di_node_name_t	di_node_name;
    145 		di_node_t	root_node;
    146 
    147 		if (!DLLINK(h,di_init))		break;
    148 		if (!DLLINK(h,di_fini))		break;
    149 		if (!DLLINK(h,di_walk_node))	break;
    150 		if (!DLLINK(h,di_node_name))	break;
    151 
    152 		if ((root_node = (*di_init)("/",DINFOSUBTREE))!=DI_NODE_NIL)
    153 			{
    154 			(*di_walk_node)(root_node,DI_WALK_SIBFIRST,
    155 					di_node_name,walk_nodename);
    156 			(*di_fini)(root_node);
    157 			}
    158 		} while(0);
    159 
    160 	if (h) dlclose(h);
    161 	}
    162 
    163 #else
    164 
    165 static sigjmp_buf common_jmp;
    166 static void common_handler(int sig) { siglongjmp(common_jmp,sig); }
    167 
    168 void OPENSSL_cpuid_setup(void)
    169 	{
    170 	char *e;
    171 	struct sigaction	common_act,ill_oact,bus_oact;
    172 	sigset_t		all_masked,oset;
    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