8#include <botan/internal/cpuid.h>
10#if defined(BOTAN_TARGET_ARCH_IS_ARM64)
12 #include <botan/internal/os_utils.h>
14 #if defined(BOTAN_TARGET_OS_HAS_SYSCTLBYNAME)
15 #include <sys/sysctl.h>
16 #include <sys/types.h>
23#if defined(BOTAN_TARGET_ARCH_IS_ARM64)
25uint32_t CPUID::CPUID_Data::detect_cpu_features() {
26 uint32_t detected_features = 0;
28 #if defined(BOTAN_TARGET_OS_HAS_GETAUXVAL) || defined(BOTAN_TARGET_OS_HAS_ELF_AUX_INFO)
45 SHA2_512_bit = (1 << 21),
51 const unsigned long hwcap =
OS::get_auxval(ARM_hwcap_bit::ARCH_hwcap);
52 if(hwcap & ARM_hwcap_bit::NEON_bit) {
53 detected_features |= CPUID::CPUID_ARM_NEON_BIT;
54 if(hwcap & ARM_hwcap_bit::AES_bit)
55 detected_features |= CPUID::CPUID_ARM_AES_BIT;
56 if(hwcap & ARM_hwcap_bit::PMULL_bit)
57 detected_features |= CPUID::CPUID_ARM_PMULL_BIT;
58 if(hwcap & ARM_hwcap_bit::SHA1_bit)
59 detected_features |= CPUID::CPUID_ARM_SHA1_BIT;
60 if(hwcap & ARM_hwcap_bit::SHA2_bit)
61 detected_features |= CPUID::CPUID_ARM_SHA2_BIT;
62 if(hwcap & ARM_hwcap_bit::SHA3_bit)
63 detected_features |= CPUID::CPUID_ARM_SHA3_BIT;
64 if(hwcap & ARM_hwcap_bit::SM3_bit)
65 detected_features |= CPUID::CPUID_ARM_SM3_BIT;
66 if(hwcap & ARM_hwcap_bit::SM4_bit)
67 detected_features |= CPUID::CPUID_ARM_SM4_BIT;
68 if(hwcap & ARM_hwcap_bit::SHA2_512_bit)
69 detected_features |= CPUID::CPUID_ARM_SHA2_512_BIT;
70 if(hwcap & ARM_hwcap_bit::SVE_bit)
71 detected_features |= CPUID::CPUID_ARM_SVE_BIT;
74 #elif defined(BOTAN_TARGET_OS_IS_IOS) || defined(BOTAN_TARGET_OS_IS_MACOS)
77 detected_features |= CPUID::CPUID_ARM_NEON_BIT;
78 detected_features |= CPUID::CPUID_ARM_AES_BIT;
79 detected_features |= CPUID::CPUID_ARM_PMULL_BIT;
80 detected_features |= CPUID::CPUID_ARM_SHA1_BIT;
81 detected_features |= CPUID::CPUID_ARM_SHA2_BIT;
83 auto sysctlbyname_has_feature = [](
const char* feature_name) ->
bool {
85 size_t size =
sizeof(feature);
86 ::sysctlbyname(feature_name, &feature, &size,
nullptr, 0);
87 return (feature == 1);
90 if(sysctlbyname_has_feature(
"hw.optional.armv8_2_sha3"))
91 detected_features |= CPUID::CPUID_ARM_SHA3_BIT;
92 if(sysctlbyname_has_feature(
"hw.optional.armv8_2_sha512"))
93 detected_features |= CPUID::CPUID_ARM_SHA2_512_BIT;
95 #elif defined(BOTAN_USE_GCC_INLINE_ASM)
106 auto neon_probe = []()
noexcept ->
int {
107 asm(
"and v0.16b, v0.16b, v0.16b");
110 auto aes_probe = []()
noexcept ->
int {
111 asm(
".word 0x4e284800");
114 auto pmull_probe = []()
noexcept ->
int {
115 asm(
".word 0x0ee0e000");
118 auto sha1_probe = []()
noexcept ->
int {
119 asm(
".word 0x5e280800");
122 auto sha2_probe = []()
noexcept ->
int {
123 asm(
".word 0x5e282800");
126 auto sha512_probe = []()
noexcept ->
int {
127 asm(
".long 0xcec08000");
134 detected_features |= CPUID::CPUID_ARM_NEON_BIT;
137 detected_features |= CPUID::CPUID_ARM_AES_BIT;
139 detected_features |= CPUID::CPUID_ARM_PMULL_BIT;
141 detected_features |= CPUID::CPUID_ARM_SHA1_BIT;
143 detected_features |= CPUID::CPUID_ARM_SHA2_BIT;
145 detected_features |= CPUID::CPUID_ARM_SHA2_512_BIT;
150 return detected_features;
int BOTAN_TEST_API run_cpu_instruction_probe(const std::function< int()> &probe_fn)
unsigned long get_auxval(unsigned long id)