1238384Sjkim#include <stdio.h>
2238384Sjkim#include <stdlib.h>
3238384Sjkim#include <string.h>
4238384Sjkim#include <setjmp.h>
5238384Sjkim#include <signal.h>
6238384Sjkim#include <crypto.h>
7238384Sjkim
8238384Sjkim#include "arm_arch.h"
9238384Sjkim
10238384Sjkimunsigned int OPENSSL_armcap_P;
11238384Sjkim
12238384Sjkimstatic sigset_t all_masked;
13238384Sjkim
14238384Sjkimstatic sigjmp_buf ill_jmp;
15238384Sjkimstatic void ill_handler (int sig) { siglongjmp(ill_jmp,sig); }
16238384Sjkim
17238384Sjkim/*
18238384Sjkim * Following subroutines could have been inlined, but it's not all
19238384Sjkim * ARM compilers support inline assembler...
20238384Sjkim */
21238384Sjkimvoid _armv7_neon_probe(void);
22238384Sjkimunsigned int _armv7_tick(void);
23238384Sjkim
24238384Sjkimunsigned int OPENSSL_rdtsc(void)
25238384Sjkim	{
26279264Sdelphij	if (OPENSSL_armcap_P & ARMV7_TICK)
27238384Sjkim		return _armv7_tick();
28238384Sjkim	else
29238384Sjkim		return 0;
30238384Sjkim	}
31238384Sjkim
32238384Sjkim#if defined(__GNUC__) && __GNUC__>=2
33238384Sjkimvoid OPENSSL_cpuid_setup(void) __attribute__((constructor));
34238384Sjkim#endif
35238384Sjkimvoid OPENSSL_cpuid_setup(void)
36238384Sjkim	{
37238384Sjkim	char *e;
38238384Sjkim	struct sigaction	ill_oact,ill_act;
39238384Sjkim	sigset_t		oset;
40238384Sjkim	static int trigger=0;
41238384Sjkim
42238384Sjkim	if (trigger) return;
43238384Sjkim	trigger=1;
44238384Sjkim
45238384Sjkim	if ((e=getenv("OPENSSL_armcap")))
46238384Sjkim		{
47238384Sjkim		OPENSSL_armcap_P=strtoul(e,NULL,0);
48238384Sjkim		return;
49238384Sjkim		}
50238384Sjkim
51238384Sjkim	sigfillset(&all_masked);
52238384Sjkim	sigdelset(&all_masked,SIGILL);
53238384Sjkim	sigdelset(&all_masked,SIGTRAP);
54238384Sjkim	sigdelset(&all_masked,SIGFPE);
55238384Sjkim	sigdelset(&all_masked,SIGBUS);
56238384Sjkim	sigdelset(&all_masked,SIGSEGV);
57238384Sjkim
58238384Sjkim	OPENSSL_armcap_P = 0;
59238384Sjkim
60238384Sjkim	memset(&ill_act,0,sizeof(ill_act));
61238384Sjkim	ill_act.sa_handler = ill_handler;
62238384Sjkim	ill_act.sa_mask    = all_masked;
63238384Sjkim
64238384Sjkim	sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset);
65238384Sjkim	sigaction(SIGILL,&ill_act,&ill_oact);
66238384Sjkim
67238384Sjkim	if (sigsetjmp(ill_jmp,1) == 0)
68238384Sjkim		{
69238384Sjkim		_armv7_neon_probe();
70238384Sjkim		OPENSSL_armcap_P |= ARMV7_NEON;
71238384Sjkim		}
72238384Sjkim	if (sigsetjmp(ill_jmp,1) == 0)
73238384Sjkim		{
74238384Sjkim		_armv7_tick();
75238384Sjkim		OPENSSL_armcap_P |= ARMV7_TICK;
76238384Sjkim		}
77238384Sjkim
78238384Sjkim	sigaction (SIGILL,&ill_oact,NULL);
79238384Sjkim	sigprocmask(SIG_SETMASK,&oset,NULL);
80238384Sjkim	}
81