ppccap.c 2.8 KB

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