armcap.c 1.6 KB

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