ppccap.c 4.4 KB

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