diff options
author | Jack Lloyd <[email protected]> | 2017-01-17 13:25:01 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2017-01-17 13:25:01 -0500 |
commit | 9dcf7c78c04c954cd1b49e80feb7478486c13531 (patch) | |
tree | b5e82237431ae5807db540645d60c3bfd5488aac /src/lib | |
parent | c3ae43c04ca4a8a3340b8549ab59c817c33f3011 (diff) |
Fixes for 32-bit ARM
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/utils/cpuid.cpp | 45 |
1 files changed, 38 insertions, 7 deletions
diff --git a/src/lib/utils/cpuid.cpp b/src/lib/utils/cpuid.cpp index bd96da987..d905eff9c 100644 --- a/src/lib/utils/cpuid.cpp +++ b/src/lib/utils/cpuid.cpp @@ -164,21 +164,52 @@ uint64_t arm_detect_cpu_features(size_t* cache_line_size) #if defined(BOTAN_TARGET_OS_HAS_GETAUXVAL) errno = 0; + /* + * On systems with getauxval these bits should normally be defined + * in bits/auxv.h but some buggy? glibc installs seem to miss them. + * These following values are all fixed, for the Linux ELF format, + * so we just hardcode them in ARM_hwcap_bit enum. + */ + + enum ARM_hwcap_bit { #if defined(BOTAN_TARGET_ARCH_IS_ARM32) - const unsigned long hwcap = ::getauxval(AT_HWCAP2); + NEON_bit = (1 << 12), + AES_bit = (1 << 0), + PMULL_bit = (1 << 1), + SHA1_bit = (1 << 2), + SHA2_bit = (1 << 3), + + ARCH_hwcap_neon = 16, // AT_HWCAP + ARCH_hwcap_crypto = 26, // AT_HWCAP2 #elif defined(BOTAN_TARGET_ARCH_IS_ARM64) - const unsigned long hwcap = ::getauxval(AT_HWCAP); + NEON_bit = (1 << 1), + AES_bit = (1 << 3), + PMULL_bit = (1 << 4), + SHA1_bit = (1 << 5), + SHA2_bit = (1 << 6), + + ARCH_hwcap_neon = 16, // AT_HWCAP + ARCH_hwcap_crypto = 16, // AT_HWCAP #endif + }; - if(hwcap & HWCAP_ASIMD) + const unsigned long hwcap_neon = ::getauxval(ARM_hwcap_bit::ARCH_hwcap_neon); + if(hwcap_neon & ARM_hwcap_bit::NEON_bit) detected_features |= CPUID::CPUID_ARM_NEON_BIT; - if(hwcap & HWCAP_AES) + + /* + On aarch64 this ends up calling getauxval twice with AT_HWCAP + This doesn't seem worth optimizing this out, since getauxval is + just reading a field in the ELF header. + */ + const unsigned long hwcap_crypto = ::getauxval(ARM_hwcap_bit::ARCH_hwcap_crypto); + if(hwcap_crypto & ARM_hwcap_bit::AES_bit) detected_features |= CPUID::CPUID_ARM_AES_BIT; - if(hwcap & HWCAP_PMULL) + if(hwcap_crypto & ARM_hwcap_bit::PMULL_bit) detected_features |= CPUID::CPUID_ARM_PMULL_BIT; - if(hwcap & HWCAP_SHA1) + if(hwcap_crypto & ARM_hwcap_bit::SHA1_bit) detected_features |= CPUID::CPUID_ARM_SHA1_BIT; - if(hwcap & HWCAP_SHA2) + if(hwcap_crypto & ARM_hwcap_bit::SHA2_bit) detected_features |= CPUID::CPUID_ARM_SHA2_BIT; const unsigned long dcache_line = ::getauxval(AT_DCACHEBSIZE); |