ppccap.c 4.9 KB

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