aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-01-17 13:25:01 -0500
committerJack Lloyd <[email protected]>2017-01-17 13:25:01 -0500
commit9dcf7c78c04c954cd1b49e80feb7478486c13531 (patch)
treeb5e82237431ae5807db540645d60c3bfd5488aac /src/lib
parentc3ae43c04ca4a8a3340b8549ab59c817c33f3011 (diff)
Fixes for 32-bit ARM
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/utils/cpuid.cpp45
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);