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