armcap.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  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 "arm_arch.h"
  8. unsigned int OPENSSL_armcap_P;
  9. static sigset_t all_masked;
  10. static sigjmp_buf ill_jmp;
  11. static void ill_handler(int sig)
  12. {
  13. siglongjmp(ill_jmp, sig);
  14. }
  15. /*
  16. * Following subroutines could have been inlined, but it's not all
  17. * ARM compilers support inline assembler...
  18. */
  19. void _armv7_neon_probe(void);
  20. unsigned int _armv7_tick(void);
  21. unsigned int OPENSSL_rdtsc(void)
  22. {
  23. if (OPENSSL_armcap_P & ARMV7_TICK)
  24. return _armv7_tick();
  25. else
  26. return 0;
  27. }
  28. #if defined(__GNUC__) && __GNUC__>=2
  29. void OPENSSL_cpuid_setup(void) __attribute__ ((constructor));
  30. #endif
  31. void OPENSSL_cpuid_setup(void)
  32. {
  33. char *e;
  34. struct sigaction ill_oact, ill_act;
  35. sigset_t oset;
  36. static int trigger = 0;
  37. if (trigger)
  38. return;
  39. trigger = 1;
  40. if ((e = getenv("OPENSSL_armcap"))) {
  41. OPENSSL_armcap_P = strtoul(e, NULL, 0);
  42. return;
  43. }
  44. sigfillset(&all_masked);
  45. sigdelset(&all_masked, SIGILL);
  46. sigdelset(&all_masked, SIGTRAP);
  47. sigdelset(&all_masked, SIGFPE);
  48. sigdelset(&all_masked, SIGBUS);
  49. sigdelset(&all_masked, SIGSEGV);
  50. OPENSSL_armcap_P = 0;
  51. memset(&ill_act, 0, sizeof(ill_act));
  52. ill_act.sa_handler = ill_handler;
  53. ill_act.sa_mask = all_masked;
  54. sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
  55. sigaction(SIGILL, &ill_act, &ill_oact);
  56. if (sigsetjmp(ill_jmp, 1) == 0) {
  57. _armv7_neon_probe();
  58. OPENSSL_armcap_P |= ARMV7_NEON;
  59. }
  60. if (sigsetjmp(ill_jmp, 1) == 0) {
  61. _armv7_tick();
  62. OPENSSL_armcap_P |= ARMV7_TICK;
  63. }
  64. sigaction(SIGILL, &ill_oact, NULL);
  65. sigprocmask(SIG_SETMASK, &oset, NULL);
  66. }