OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
ppccap.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <setjmp.h>
5 #include <signal.h>
6 #include <crypto.h>
7 #include <openssl/bn.h>
8 
9 #define PPC_FPU64 (1<<0)
10 #define PPC_ALTIVEC (1<<1)
11 
12 static int OPENSSL_ppccap_P = 0;
13 
14 static sigset_t all_masked;
15 
16 #ifdef OPENSSL_BN_ASM_MONT
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_fpu64(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 (sizeof(size_t)==4)
23  {
24 #if (defined(__APPLE__) && defined(__MACH__))
25  if (num>=8 && (num&3)==0 && (OPENSSL_ppccap_P&PPC_FPU64))
26  return bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
27 #else
28  /* boundary of 32 was experimentally determined on
29  Linux 2.6.22, might have to be adjusted on AIX... */
30  if (num>=32 && (num&3)==0 && (OPENSSL_ppccap_P&PPC_FPU64))
31  {
32  sigset_t oset;
33  int ret;
34 
35  sigprocmask(SIG_SETMASK,&all_masked,&oset);
36  ret=bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
37  sigprocmask(SIG_SETMASK,&oset,NULL);
38 
39  return ret;
40  }
41 #endif
42  }
43  else if ((OPENSSL_ppccap_P&PPC_FPU64))
44  /* this is a "must" on POWER6, but run-time detection
45  * is not implemented yet... */
46  return bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
47 
48  return bn_mul_mont_int(rp,ap,bp,np,n0,num);
49  }
50 #endif
51 
52 static sigjmp_buf ill_jmp;
53 static void ill_handler (int sig) { siglongjmp(ill_jmp,sig); }
54 
55 void OPENSSL_ppc64_probe(void);
56 
58  {
59  char *e;
60  struct sigaction ill_oact,ill_act;
61  sigset_t oset;
62  static int trigger=0;
63 
64  if (trigger) return;
65  trigger=1;
66 
67  sigfillset(&all_masked);
68  sigdelset(&all_masked,SIGILL);
69  sigdelset(&all_masked,SIGTRAP);
70 #ifdef SIGEMT
71  sigdelset(&all_masked,SIGEMT);
72 #endif
73  sigdelset(&all_masked,SIGFPE);
74  sigdelset(&all_masked,SIGBUS);
75  sigdelset(&all_masked,SIGSEGV);
76 
77  if ((e=getenv("OPENSSL_ppccap")))
78  {
79  OPENSSL_ppccap_P=strtoul(e,NULL,0);
80  return;
81  }
82 
83  OPENSSL_ppccap_P = 0;
84 
85  memset(&ill_act,0,sizeof(ill_act));
86  ill_act.sa_handler = ill_handler;
87  ill_act.sa_mask = all_masked;
88 
89  sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset);
90  sigaction(SIGILL,&ill_act,&ill_oact);
91 
92  if (sizeof(size_t)==4)
93  {
94  if (sigsetjmp(ill_jmp,1) == 0)
95  {
97  OPENSSL_ppccap_P |= PPC_FPU64;
98  }
99  }
100  else
101  {
102  /*
103  * Wanted code detecting POWER6 CPU and setting PPC_FPU64
104  */
105  }
106 
107  if (sigsetjmp(ill_jmp,1) == 0)
108  {
109  OPENSSL_altivec_probe();
110  OPENSSL_ppccap_P |= PPC_ALTIVEC;
111  }
112 
113  sigaction (SIGILL,&ill_oact,NULL);
114  sigprocmask(SIG_SETMASK,&oset,NULL);
115  }