OLD | NEW |
| (Empty) |
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_U
LONG *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_n
ode_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 Linu
x] */ | |
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_FP
U); | |
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 | |
OLD | NEW |