diff --git a/crypto/cpu-arm-linux.c b/crypto/cpu-arm-linux.c index ab4648ce..73c38ecc 100644 --- a/crypto/cpu-arm-linux.c +++ b/crypto/cpu-arm-linux.c @@ -288,6 +288,8 @@ static int has_broken_neon(const STRING_PIECE *cpuinfo) { extern uint32_t OPENSSL_armcap_P; +static int g_has_broken_neon; + void OPENSSL_cpuid_setup(void) { char *cpuinfo_data; size_t cpuinfo_len; @@ -317,7 +319,8 @@ void OPENSSL_cpuid_setup(void) { } /* Clear NEON support if known broken. */ - if (has_broken_neon(&cpuinfo)) { + g_has_broken_neon = has_broken_neon(&cpuinfo); + if (g_has_broken_neon) { hwcap &= ~HWCAP_NEON; } @@ -352,4 +355,6 @@ void OPENSSL_cpuid_setup(void) { OPENSSL_free(cpuinfo_data); } +int CRYPTO_has_broken_NEON(void) { return g_has_broken_neon; } + #endif /* OPENSSL_ARM && !OPENSSL_STATIC_ARMCAP */ diff --git a/include/openssl/cpu.h b/include/openssl/cpu.h index dad544e7..55be4c1f 100644 --- a/include/openssl/cpu.h +++ b/include/openssl/cpu.h @@ -110,13 +110,24 @@ OPENSSL_EXPORT char CRYPTO_is_NEON_capable_at_runtime(void); /* CRYPTO_is_NEON_capable returns true if the current CPU has a NEON unit. If * this is known statically then it returns one immediately. */ static inline int CRYPTO_is_NEON_capable(void) { -#if defined(__ARM_NEON__) + /* Only statically skip the runtime lookup on aarch64. On arm, one CPU is + * known to have a broken NEON unit which is known to fail with on some + * hand-written NEON assembly. For now, continue to apply the workaround even + * when the compiler is instructed to freely emit NEON code. See + * https://crbug.com/341598 and https://crbug.com/606629. */ +#if defined(__ARM_NEON__) && !defined(OPENSSL_ARM) return 1; #else return CRYPTO_is_NEON_capable_at_runtime(); #endif } +#if defined(OPENSSL_ARM) +/* CRYPTO_has_broken_NEON returns one if the current CPU is known to have a + * broken NEON unit. See https://crbug.com/341598. */ +OPENSSL_EXPORT int CRYPTO_has_broken_NEON(void); +#endif + /* CRYPTO_is_ARMv8_AES_capable returns true if the current CPU supports the * ARMv8 AES instruction. */ int CRYPTO_is_ARMv8_AES_capable(void); @@ -152,7 +163,7 @@ static inline int CRYPTO_is_ARMv8_PMULL_capable(void) { } #endif /* OPENSSL_STATIC_ARMCAP */ -#endif /* OPENSSL_ARM */ +#endif /* OPENSSL_ARM || OPENSSL_AARCH64 */ #if defined(__cplusplus)