| 
									
										
										
										
											2011-07-18 01:40:29 +08:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <setjmp.h>
 | 
					
						
							|  |  |  | #include <signal.h>
 | 
					
						
							|  |  |  | #include <crypto.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "arm_arch.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | unsigned int OPENSSL_armcap_P; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static sigset_t all_masked; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static sigjmp_buf ill_jmp; | 
					
						
							|  |  |  | static void ill_handler (int sig) { siglongjmp(ill_jmp,sig); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Following subroutines could have been inlined, but it's not all | 
					
						
							|  |  |  |  * ARM compilers support inline assembler... | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void _armv7_neon_probe(void); | 
					
						
							|  |  |  | unsigned int _armv7_tick(void); | 
					
						
							| 
									
										
										
										
											2015-05-11 17:34:56 +08:00
										 |  |  | void _armv8_aes_probe(void); | 
					
						
							|  |  |  | void _armv8_sha1_probe(void); | 
					
						
							|  |  |  | void _armv8_sha256_probe(void); | 
					
						
							|  |  |  | void _armv8_pmull_probe(void); | 
					
						
							| 
									
										
										
										
											2011-07-18 01:40:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | unsigned int OPENSSL_rdtsc(void) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	if (OPENSSL_armcap_P|ARMV7_TICK) | 
					
						
							|  |  |  | 		return _armv7_tick(); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-21 04:52:26 +08:00
										 |  |  | #if defined(__GNUC__) && __GNUC__>=2
 | 
					
						
							| 
									
										
										
										
											2011-10-24 21:24:28 +08:00
										 |  |  | void OPENSSL_cpuid_setup(void) __attribute__((constructor)); | 
					
						
							| 
									
										
										
										
											2011-10-21 04:52:26 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-07-18 01:40:29 +08:00
										 |  |  | void OPENSSL_cpuid_setup(void) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	char *e; | 
					
						
							|  |  |  | 	struct sigaction	ill_oact,ill_act; | 
					
						
							|  |  |  | 	sigset_t		oset; | 
					
						
							|  |  |  | 	static int trigger=0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (trigger) return; | 
					
						
							|  |  |  | 	trigger=1; | 
					
						
							|  |  |  |   | 
					
						
							|  |  |  | 	if ((e=getenv("OPENSSL_armcap"))) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		OPENSSL_armcap_P=strtoul(e,NULL,0); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sigfillset(&all_masked); | 
					
						
							|  |  |  | 	sigdelset(&all_masked,SIGILL); | 
					
						
							|  |  |  | 	sigdelset(&all_masked,SIGTRAP); | 
					
						
							|  |  |  | 	sigdelset(&all_masked,SIGFPE); | 
					
						
							|  |  |  | 	sigdelset(&all_masked,SIGBUS); | 
					
						
							|  |  |  | 	sigdelset(&all_masked,SIGSEGV); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	OPENSSL_armcap_P = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memset(&ill_act,0,sizeof(ill_act)); | 
					
						
							|  |  |  | 	ill_act.sa_handler = ill_handler; | 
					
						
							|  |  |  | 	ill_act.sa_mask    = all_masked; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset); | 
					
						
							|  |  |  | 	sigaction(SIGILL,&ill_act,&ill_oact); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (sigsetjmp(ill_jmp,1) == 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		_armv7_neon_probe(); | 
					
						
							|  |  |  | 		OPENSSL_armcap_P |= ARMV7_NEON; | 
					
						
							| 
									
										
										
										
											2015-05-11 17:34:56 +08:00
										 |  |  | #ifdef __aarch64__
 | 
					
						
							|  |  |  | 		if (sigsetjmp(ill_jmp,1) == 0) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			_armv8_pmull_probe(); | 
					
						
							|  |  |  | 			OPENSSL_armcap_P |= ARMV8_PMULL|ARMV8_AES; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		else if (sigsetjmp(ill_jmp,1) == 0) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			_armv8_aes_probe(); | 
					
						
							|  |  |  | 			OPENSSL_armcap_P |= ARMV8_AES; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		if (sigsetjmp(ill_jmp,1) == 0) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			_armv8_sha1_probe(); | 
					
						
							|  |  |  | 			OPENSSL_armcap_P |= ARMV8_SHA1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		if (sigsetjmp(ill_jmp,1) == 0) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			_armv8_sha256_probe(); | 
					
						
							|  |  |  | 			OPENSSL_armcap_P |= ARMV8_SHA256; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-07-18 01:40:29 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	if (sigsetjmp(ill_jmp,1) == 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		_armv7_tick(); | 
					
						
							|  |  |  | 		OPENSSL_armcap_P |= ARMV7_TICK; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sigaction (SIGILL,&ill_oact,NULL); | 
					
						
							|  |  |  | 	sigprocmask(SIG_SETMASK,&oset,NULL); | 
					
						
							|  |  |  | 	} |