ppccap.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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. #define PPC_FPU64 (1<<0)
  9. #define PPC_ALTIVEC (1<<1)
  10. static int OPENSSL_ppccap_P = 0;
  11. static sigset_t all_masked;
  12. #ifdef OPENSSL_BN_ASM_MONT
  13. 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)
  14. {
  15. 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);
  16. 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);
  17. if (sizeof(size_t)==4)
  18. {
  19. #if (defined(__APPLE__) && defined(__MACH__))
  20. if (num>=8 && (num&3)==0 && (OPENSSL_ppccap_P&PPC_FPU64))
  21. return bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
  22. #else
  23. /* boundary of 32 was experimentally determined on
  24. Linux 2.6.22, might have to be adjusted on AIX... */
  25. if (num>=32 && (num&3)==0 && (OPENSSL_ppccap_P&PPC_FPU64))
  26. {
  27. sigset_t oset;
  28. int ret;
  29. sigprocmask(SIG_SETMASK,&all_masked,&oset);
  30. ret=bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
  31. sigprocmask(SIG_SETMASK,&oset,NULL);
  32. return ret;
  33. }
  34. #endif
  35. }
  36. else if ((OPENSSL_ppccap_P&PPC_FPU64))
  37. /* this is a "must" on POWER6, but run-time detection
  38. * is not implemented yet... */
  39. return bn_mul_mont_fpu64(rp,ap,bp,np,n0,num);
  40. return bn_mul_mont_int(rp,ap,bp,np,n0,num);
  41. }
  42. #endif
  43. static sigjmp_buf ill_jmp;
  44. static void ill_handler (int sig) { siglongjmp(ill_jmp,sig); }
  45. void OPENSSL_ppc64_probe(void);
  46. void OPENSSL_cpuid_setup(void)
  47. {
  48. char *e;
  49. struct sigaction ill_oact,ill_act;
  50. sigset_t oset;
  51. static int trigger=0;
  52. if (trigger) return;
  53. trigger=1;
  54. sigfillset(&all_masked);
  55. sigdelset(&all_masked,SIGILL);
  56. sigdelset(&all_masked,SIGTRAP);
  57. #ifdef SIGEMT
  58. sigdelset(&all_masked,SIGEMT);
  59. #endif
  60. sigdelset(&all_masked,SIGFPE);
  61. sigdelset(&all_masked,SIGBUS);
  62. sigdelset(&all_masked,SIGSEGV);
  63. if ((e=getenv("OPENSSL_ppccap")))
  64. {
  65. OPENSSL_ppccap_P=strtoul(e,NULL,0);
  66. return;
  67. }
  68. OPENSSL_ppccap_P = 0;
  69. memset(&ill_act,0,sizeof(ill_act));
  70. ill_act.sa_handler = ill_handler;
  71. ill_act.sa_mask = all_masked;
  72. sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset);
  73. sigaction(SIGILL,&ill_act,&ill_oact);
  74. if (sizeof(size_t)==4)
  75. {
  76. if (sigsetjmp(ill_jmp,1) == 0)
  77. {
  78. OPENSSL_ppc64_probe();
  79. OPENSSL_ppccap_P |= PPC_FPU64;
  80. }
  81. }
  82. else
  83. {
  84. /*
  85. * Wanted code detecting POWER6 CPU and setting PPC_FPU64
  86. */
  87. }
  88. if (sigsetjmp(ill_jmp,1) == 0)
  89. {
  90. OPENSSL_altivec_probe();
  91. OPENSSL_ppccap_P |= PPC_ALTIVEC;
  92. }
  93. sigaction (SIGILL,&ill_oact,NULL);
  94. sigprocmask(SIG_SETMASK,&oset,NULL);
  95. }