]>
Commit | Line | Data |
---|---|---|
b4b48a10 AP |
1 | #include <stdio.h> |
2 | #include <stdlib.h> | |
3 | #include <string.h> | |
4 | #include <setjmp.h> | |
5 | #include <signal.h> | |
fd054957 | 6 | #include <unistd.h> |
d5630dd6 | 7 | #if defined(__linux) || defined(_AIX) |
78c3e205 AP |
8 | #include <sys/utsname.h> |
9 | #endif | |
9f7b2c76 | 10 | #include <crypto.h> |
b4b48a10 AP |
11 | #include <openssl/bn.h> |
12 | ||
13 | #define PPC_FPU64 (1<<0) | |
6415dd7b | 14 | #define PPC_ALTIVEC (1<<1) |
de51e830 | 15 | #define PPC_CRYPTO207 (1<<2) |
b4b48a10 | 16 | |
07f3e4f3 | 17 | unsigned int OPENSSL_ppccap_P = 0; |
b4b48a10 AP |
18 | |
19 | static sigset_t all_masked; | |
20 | ||
d741cf22 | 21 | #ifdef OPENSSL_BN_ASM_MONT |
b4b48a10 AP |
22 | 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) |
23 | { | |
24 | int bn_mul_mont_fpu64(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np, const BN_ULONG *n0, int num); | |
25 | 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); | |
26 | ||
27 | if (sizeof(size_t)==4) | |
28 | { | |
b9e87d07 | 29 | #if 1 || (defined(__APPLE__) && defined(__MACH__)) |
2e75ed33 | 30 | if (num>=8 && (num&3)==0 && (OPENSSL_ppccap_P&PPC_FPU64)) |
b4b48a10 AP |
31 | return bn_mul_mont_fpu64(rp,ap,bp,np,n0,num); |
32 | #else | |
33 | /* boundary of 32 was experimentally determined on | |
34 | Linux 2.6.22, might have to be adjusted on AIX... */ | |
70b76d39 | 35 | if (num>=32 && (num&3)==0 && (OPENSSL_ppccap_P&PPC_FPU64)) |
b4b48a10 AP |
36 | { |
37 | sigset_t oset; | |
38 | int ret; | |
39 | ||
40 | sigprocmask(SIG_SETMASK,&all_masked,&oset); | |
41 | ret=bn_mul_mont_fpu64(rp,ap,bp,np,n0,num); | |
42 | sigprocmask(SIG_SETMASK,&oset,NULL); | |
43 | ||
44 | return ret; | |
45 | } | |
46 | #endif | |
47 | } | |
48 | else if ((OPENSSL_ppccap_P&PPC_FPU64)) | |
6415dd7b | 49 | /* this is a "must" on POWER6, but run-time detection |
b4b48a10 AP |
50 | * is not implemented yet... */ |
51 | return bn_mul_mont_fpu64(rp,ap,bp,np,n0,num); | |
52 | ||
53 | return bn_mul_mont_int(rp,ap,bp,np,n0,num); | |
54 | } | |
d741cf22 | 55 | #endif |
b4b48a10 AP |
56 | |
57 | static sigjmp_buf ill_jmp; | |
58 | static void ill_handler (int sig) { siglongjmp(ill_jmp,sig); } | |
59 | ||
70b76d39 | 60 | void OPENSSL_ppc64_probe(void); |
fd054957 | 61 | void OPENSSL_altivec_probe(void); |
de51e830 | 62 | void OPENSSL_crypto207_probe(void); |
70b76d39 | 63 | |
b4b48a10 AP |
64 | void OPENSSL_cpuid_setup(void) |
65 | { | |
66 | char *e; | |
6415dd7b AP |
67 | struct sigaction ill_oact,ill_act; |
68 | sigset_t oset; | |
69 | static int trigger=0; | |
b4b48a10 | 70 | |
6415dd7b AP |
71 | if (trigger) return; |
72 | trigger=1; | |
73 | ||
b4b48a10 | 74 | sigfillset(&all_masked); |
b4b48a10 | 75 | sigdelset(&all_masked,SIGILL); |
78a533cb | 76 | sigdelset(&all_masked,SIGTRAP); |
80dfadfd | 77 | #ifdef SIGEMT |
78a533cb | 78 | sigdelset(&all_masked,SIGEMT); |
80dfadfd | 79 | #endif |
d741cf22 | 80 | sigdelset(&all_masked,SIGFPE); |
78a533cb AP |
81 | sigdelset(&all_masked,SIGBUS); |
82 | sigdelset(&all_masked,SIGSEGV); | |
b4b48a10 AP |
83 | |
84 | if ((e=getenv("OPENSSL_ppccap"))) | |
85 | { | |
86 | OPENSSL_ppccap_P=strtoul(e,NULL,0); | |
87 | return; | |
88 | } | |
89 | ||
6415dd7b AP |
90 | OPENSSL_ppccap_P = 0; |
91 | ||
fd054957 | 92 | #if defined(_AIX) |
d5630dd6 AP |
93 | if (sizeof(size_t)==4) |
94 | { | |
95 | struct utsname uts; | |
fd054957 | 96 | # if defined(_SC_AIX_KERNEL_BITMODE) |
d5630dd6 | 97 | if (sysconf(_SC_AIX_KERNEL_BITMODE)!=64) return; |
fd054957 | 98 | # endif |
f717abd7 | 99 | if (uname(&uts)!=0 || atoi(uts.version)<6) return; |
d5630dd6 | 100 | } |
fd054957 AP |
101 | #endif |
102 | ||
6415dd7b AP |
103 | memset(&ill_act,0,sizeof(ill_act)); |
104 | ill_act.sa_handler = ill_handler; | |
105 | ill_act.sa_mask = all_masked; | |
106 | ||
107 | sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset); | |
108 | sigaction(SIGILL,&ill_act,&ill_oact); | |
109 | ||
b4b48a10 AP |
110 | if (sizeof(size_t)==4) |
111 | { | |
78c3e205 AP |
112 | #ifdef __linux |
113 | struct utsname uts; | |
114 | if (uname(&uts)==0 && strcmp(uts.machine,"ppc64")==0) | |
115 | #endif | |
6415dd7b | 116 | if (sigsetjmp(ill_jmp,1) == 0) |
b4b48a10 AP |
117 | { |
118 | OPENSSL_ppc64_probe(); | |
119 | OPENSSL_ppccap_P |= PPC_FPU64; | |
120 | } | |
b4b48a10 | 121 | } |
6415dd7b AP |
122 | else |
123 | { | |
124 | /* | |
125 | * Wanted code detecting POWER6 CPU and setting PPC_FPU64 | |
126 | */ | |
127 | } | |
128 | ||
129 | if (sigsetjmp(ill_jmp,1) == 0) | |
130 | { | |
131 | OPENSSL_altivec_probe(); | |
132 | OPENSSL_ppccap_P |= PPC_ALTIVEC; | |
de51e830 AP |
133 | if (sigsetjmp(ill_jmp,1) == 0) |
134 | { | |
135 | OPENSSL_crypto207_probe(); | |
136 | OPENSSL_ppccap_P |= PPC_CRYPTO207; | |
137 | } | |
6415dd7b AP |
138 | } |
139 | ||
140 | sigaction (SIGILL,&ill_oact,NULL); | |
141 | sigprocmask(SIG_SETMASK,&oset,NULL); | |
b4b48a10 | 142 | } |