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