Some ARM environments don't support |getauxval| or signals and need to configure the capabilities of the chip at compile time. This change adds defines that allow them to do so. Change-Id: I4e6987f69dd13444029bc7ac7ed4dbf8fb1faa76 Reviewed-on: https://boringssl-review.googlesource.com/6280 Reviewed-by: Adam Langley <agl@google.com>kris/onging/CECPQ3_patch15
@@ -91,6 +91,30 @@ binaries. | |||
don't have steps for assembling the assembly language source files, so they | |||
currently cannot be used to build BoringSSL. | |||
## Embedded ARM | |||
ARM, unlike Intel, does not have an instruction that allows applications to | |||
discover the capabilities of the processor. Instead, the capability information | |||
has to be provided by the operating system somehow. | |||
BoringSSL will try to use `getauxval` to discover the capabilities and, failing | |||
that, will probe for NEON support by executing a NEON instruction and handling | |||
any illegal-instruction signal. But some environments don't support that sort | |||
of thing and, for them, it's possible to configure the CPU capabilities | |||
at compile time. | |||
If you define `OPENSSL_STATIC_ARMCAP` then you can define any of the following | |||
to enabling the corresponding ARM feature. | |||
* `OPENSSL_STATIC_ARMCAP_NEON` or `__ARM_NEON__` (note that the latter is set by compilers when NEON support is enabled). | |||
* `OPENSSL_STATIC_ARMCAP_AES` | |||
* `OPENSSL_STATIC_ARMCAP_SHA1` | |||
* `OPENSSL_STATIC_ARMCAP_SHA256` | |||
* `OPENSSL_STATIC_ARMCAP_PMULL` | |||
Note that if a feature is enabled in this way, but not actually supported at | |||
run-time, BoringSSL will likely crash. | |||
# Running tests | |||
There are two sets of tests: the C/C++ tests and the blackbox tests. For former | |||
@@ -51,6 +51,8 @@ | |||
#include <assert.h> | |||
#include <stdlib.h> | |||
#include <openssl/cpu.h> | |||
#include "internal.h" | |||
@@ -1059,10 +1061,9 @@ void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { | |||
#else | |||
#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) | |||
#include <openssl/arm_arch.h> | |||
static int hwaes_capable(void) { | |||
return (OPENSSL_armcap_P & ARMV8_AES) != 0; | |||
return CRYPTO_is_ARMv8_AES_capable(); | |||
} | |||
int aes_v8_set_encrypt_key(const uint8_t *user_key, const int bits, | |||
@@ -121,7 +121,7 @@ static char bsaes_capable(void) { | |||
#define HWAES | |||
static int hwaes_capable(void) { | |||
return (OPENSSL_armcap_P & ARMV8_AES) != 0; | |||
return CRYPTO_is_ARMv8_AES_capable(); | |||
} | |||
int aes_v8_set_encrypt_key(const uint8_t *user_key, const int bits, | |||
@@ -1756,7 +1756,7 @@ int EVP_has_aes_hardware(void) { | |||
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) | |||
return aesni_capable() && crypto_gcm_clmul_enabled(); | |||
#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) | |||
return hwaes_capable() && (OPENSSL_armcap_P & ARMV8_PMULL); | |||
return hwaes_capable() && CRYPTO_is_ARMv8_PMULL_capable(); | |||
#else | |||
return 0; | |||
#endif | |||
@@ -14,15 +14,14 @@ | |||
#include <openssl/cpu.h> | |||
#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) | |||
#if (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) && \ | |||
!defined(OPENSSL_STATIC_ARMCAP) | |||
#include <inttypes.h> | |||
#include <string.h> | |||
#if !defined(OPENSSL_TRUSTY) | |||
#include <setjmp.h> | |||
#include <signal.h> | |||
#endif | |||
#include <openssl/arm_arch.h> | |||
@@ -33,6 +32,8 @@ | |||
unsigned long getauxval(unsigned long type) __attribute__((weak)); | |||
extern uint32_t OPENSSL_armcap_P; | |||
char CRYPTO_is_NEON_capable(void) { | |||
return (OPENSSL_armcap_P & ARMV7_NEON) != 0; | |||
} | |||
@@ -62,7 +63,15 @@ void CRYPTO_set_NEON_functional(char neon_functional) { | |||
} | |||
} | |||
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_ARM) && !defined(OPENSSL_TRUSTY) | |||
int CRYPTO_is_ARMv8_AES_capable(void) { | |||
return (OPENSSL_armcap_P & ARMV8_AES) != 0; | |||
} | |||
int CRYPTO_is_ARMv8_PMULL_capable(void) { | |||
return (OPENSSL_armcap_P & ARMV8_PMULL) != 0; | |||
} | |||
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_ARM) | |||
static sigjmp_buf sigill_jmp; | |||
@@ -120,7 +129,7 @@ static int probe_for_NEON(void) { | |||
return 0; | |||
} | |||
#endif /* !OPENSSL_NO_ASM && OPENSSL_ARM && !OPENSSL_TRUSTY */ | |||
#endif /* !OPENSSL_NO_ASM && OPENSSL_ARM */ | |||
void OPENSSL_cpuid_setup(void) { | |||
if (getauxval == NULL) { | |||
@@ -186,4 +195,5 @@ void OPENSSL_cpuid_setup(void) { | |||
} | |||
} | |||
#endif /* defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) */ | |||
#endif /* (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) && | |||
!defined(OPENSSL_STATIC_ARMCAP) */ |
@@ -17,7 +17,7 @@ | |||
#include "internal.h" | |||
#if !defined(OPENSSL_NO_ASM) && \ | |||
#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_STATIC_ARMCAP) && \ | |||
(defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ | |||
defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) | |||
/* x86, x86_64 and the ARMs need to record the result of a cpuid call for the | |||
@@ -57,7 +57,27 @@ uint32_t OPENSSL_ia32cap_P[4] = {0}; | |||
#include <openssl/arm_arch.h> | |||
#if defined(__ARM_NEON__) | |||
#if defined(OPENSSL_STATIC_ARMCAP) | |||
uint32_t OPENSSL_armcap_P = | |||
#if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__) | |||
ARMV7_NEON | ARMV7_NEON_FUNCTIONAL | | |||
#endif | |||
#if defined(OPENSSL_STATIC_ARMCAP_AES) | |||
ARMV8_AES | | |||
#endif | |||
#if defined(OPENSSL_STATIC_ARMCAP_SHA1) | |||
ARMV8_SHA1 | | |||
#endif | |||
#if defined(OPENSSL_STATIC_ARMCAP_SHA256) | |||
ARMV8_SHA256 | | |||
#endif | |||
#if defined(OPENSSL_STATIC_ARMCAP_PMULL) | |||
ARMV8_PMULL | | |||
#endif | |||
0; | |||
#elif defined(__ARM_NEON__) | |||
uint32_t OPENSSL_armcap_P = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL; | |||
#else | |||
uint32_t OPENSSL_armcap_P = ARMV7_NEON_FUNCTIONAL; | |||
@@ -355,7 +355,7 @@ void gcm_ghash_4bit_x86(uint64_t Xi[2], const u128 Htable[16], const uint8_t *in | |||
#define GCM_FUNCREF_4BIT | |||
static int pmull_capable(void) { | |||
return (OPENSSL_armcap_P & ARMV8_PMULL) != 0; | |||
return CRYPTO_is_ARMv8_PMULL_capable(); | |||
} | |||
void gcm_init_v8(u128 Htable[16], const uint64_t Xi[2]); | |||
@@ -102,15 +102,6 @@ | |||
* will be included. */ | |||
#define __ARM_MAX_ARCH__ 8 | |||
#if !__ASSEMBLER__ | |||
/* OPENSSL_armcap_P contains flags describing the capabilities of the CPU and | |||
* is easy for assembly code to acesss. For C code, see the functions in | |||
* |cpu.h|. */ | |||
extern uint32_t OPENSSL_armcap_P; | |||
#endif /* !__ASSEMBLER__ */ | |||
/* ARMV7_NEON is true when a NEON unit is present in the current CPU. */ | |||
#define ARMV7_NEON (1 << 0) | |||
@@ -94,6 +94,9 @@ extern uint32_t OPENSSL_ia32cap_P[4]; | |||
#endif | |||
#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) | |||
#if !defined(OPENSSL_STATIC_ARMCAP) | |||
/* CRYPTO_is_NEON_capable returns true if the current CPU has a NEON unit. Note | |||
* that |OPENSSL_armcap_P| also exists and contains the same information in a | |||
* form that's easier for assembly to use. */ | |||
@@ -116,6 +119,46 @@ OPENSSL_EXPORT char CRYPTO_is_NEON_functional(void); | |||
* compiled with |-mfpu=neon| or if |CRYPTO_set_NEON_capable| has been called | |||
* with a non-zero argument. */ | |||
OPENSSL_EXPORT void CRYPTO_set_NEON_functional(char neon_functional); | |||
/* CRYPTO_is_ARMv8_AES_capable returns true if the current CPU supports the | |||
* ARMv8 AES instruction. */ | |||
int CRYPTO_is_ARMv8_AES_capable(void); | |||
/* CRYPTO_is_ARMv8_PMULL_capable returns true if the current CPU supports the | |||
* ARMv8 PMULL instruction. */ | |||
int CRYPTO_is_ARMv8_PMULL_capable(void); | |||
#else | |||
static inline int CRYPTO_is_NEON_capable(void) { | |||
#if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__) | |||
return 1; | |||
#else | |||
return 0; | |||
#endif | |||
} | |||
static inline int CRYPTO_is_NEON_functional(void) { | |||
return CRYPTO_is_NEON_capable(); | |||
} | |||
static inline int CRYPTO_is_ARMv8_AES_capable(void) { | |||
#if defined(OPENSSL_STATIC_ARMCAP_AES) | |||
return 1; | |||
#else | |||
return 0; | |||
#endif | |||
} | |||
static inline int CRYPTO_is_ARMv8_PMULL_capable(void) { | |||
#if defined(OPENSSL_STATIC_ARMCAP_PMULL) | |||
return 1; | |||
#else | |||
return 0; | |||
#endif | |||
} | |||
#endif /* OPENSSL_STATIC_ARMCAP */ | |||
#endif /* OPENSSL_ARM */ | |||