From 2688d99989902dea884632a8658f3abad0c26d16 Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Sat, 14 Nov 2015 00:10:19 +0100 Subject: crypto/ppccap.c: add SIGILL-free processor capability detection code. Reviewed-by: Kurt Roeckx --- crypto/ppc_arch.h | 6 +++ crypto/ppccap.c | 134 +++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 119 insertions(+), 21 deletions(-) diff --git a/crypto/ppc_arch.h b/crypto/ppc_arch.h index b50ec996a5..c0b4f1846b 100644 --- a/crypto/ppc_arch.h +++ b/crypto/ppc_arch.h @@ -3,8 +3,14 @@ extern unsigned int OPENSSL_ppccap_P; +/* + * Flags' usage can appear ambiguous, because they are set rather + * to reflect OpenSSL performance preferences than actual processor + * capabilities. + */ # define PPC_FPU64 (1<<0) # define PPC_ALTIVEC (1<<1) # define PPC_CRYPTO207 (1<<2) +# define PPC_FPU (1<<3) #endif diff --git a/crypto/ppccap.c b/crypto/ppccap.c index 74af4732b5..c8d012ea5a 100644 --- a/crypto/ppccap.c +++ b/crypto/ppccap.c @@ -7,6 +7,12 @@ #if defined(__linux) || defined(_AIX) # include #endif +#if defined(_AIX53) /* defined even on post-5.3 */ +# include +# if !defined(__power_set) +# define __power_set(a) (_system_configuration.implementation & (a)) +# endif +#endif #include #include @@ -79,10 +85,37 @@ static void ill_handler(int sig) siglongjmp(ill_jmp, sig); } +void OPENSSL_fpu_probe(void); void OPENSSL_ppc64_probe(void); void OPENSSL_altivec_probe(void); void OPENSSL_crypto207_probe(void); +/* + * Use a weak reference to getauxval() so we can use it if it is available + * but don't break the build if it is not. Note that this is *link-time* + * feature detection, not *run-time*. In other words if we link with + * symbol present, it's expected to be present even at run-time. + */ +#if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) +extern unsigned long getauxval(unsigned long type) __attribute__ ((weak)); +#else +static unsigned long (*getauxval) (unsigned long) = NULL; +#endif + +/* I wish was universally available */ +#define HWCAP 16 /* AT_HWCAP */ +#define HWCAP_PPC64 (1U << 30) +#define HWCAP_ALTIVEC (1U << 28) +#define HWCAP_FPU (1U << 27) +#define HWCAP_POWER6_EXT (1U << 9) +#define HWCAP_VSX (1U << 7) + +#define HWCAP2 26 /* AT_HWCAP2 */ +#define HWCAP_VEC_CRYPTO (1U << 25) + +# if defined(__GNUC__) && __GNUC__>=2 +__attribute__ ((constructor)) +# endif void OPENSSL_cpuid_setup(void) { char *e; @@ -94,16 +127,6 @@ void OPENSSL_cpuid_setup(void) return; trigger = 1; - sigfillset(&all_masked); - sigdelset(&all_masked, SIGILL); - sigdelset(&all_masked, SIGTRAP); -#ifdef SIGEMT - sigdelset(&all_masked, SIGEMT); -#endif - sigdelset(&all_masked, SIGFPE); - sigdelset(&all_masked, SIGBUS); - sigdelset(&all_masked, SIGSEGV); - if ((e = getenv("OPENSSL_ppccap"))) { OPENSSL_ppccap_P = strtoul(e, NULL, 0); return; @@ -112,6 +135,8 @@ void OPENSSL_cpuid_setup(void) OPENSSL_ppccap_P = 0; #if defined(_AIX) + OPENSSL_ppccap_P |= PPC_FPU; + if (sizeof(size_t) == 4) { struct utsname uts; # if defined(_SC_AIX_KERNEL_BITMODE) @@ -121,7 +146,69 @@ void OPENSSL_cpuid_setup(void) if (uname(&uts) != 0 || atoi(uts.version) < 6) return; } + +# if defined(__power_set) + /* + * Value used in __power_set is a single-bit 1<