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