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_IS_IOS) || defined(BOTAN_TARGET_OS_IS_MACOS)
15 #include <sys/sysctl.h>
16 #include <sys/types.h>
21 #if defined(BOTAN_TARGET_OS_IS_MACOS)
24bool sysctlbyname_has_feature(
const char* feature_name) {
26 size_t size =
sizeof(feature);
27 ::sysctlbyname(feature_name, &feature, &size,
nullptr, 0);
28 return (feature == 1);
34uint32_t CPUID::CPUID_Data::detect_cpu_features() {
35 uint32_t detected_features = 0;
37 #if defined(BOTAN_TARGET_OS_HAS_GETAUXVAL) || defined(BOTAN_TARGET_OS_HAS_ELF_AUX_INFO)
54 SHA2_512_bit = (1 << 21),
60 const unsigned long hwcap =
OS::get_auxval(ARM_hwcap_bit::ARCH_hwcap);
61 if(hwcap & ARM_hwcap_bit::NEON_bit) {
62 detected_features |= CPUID::CPUID_ARM_NEON_BIT;
63 if(hwcap & ARM_hwcap_bit::AES_bit)
64 detected_features |= CPUID::CPUID_ARM_AES_BIT;
65 if(hwcap & ARM_hwcap_bit::PMULL_bit)
66 detected_features |= CPUID::CPUID_ARM_PMULL_BIT;
67 if(hwcap & ARM_hwcap_bit::SHA1_bit)
68 detected_features |= CPUID::CPUID_ARM_SHA1_BIT;
69 if(hwcap & ARM_hwcap_bit::SHA2_bit)
70 detected_features |= CPUID::CPUID_ARM_SHA2_BIT;
71 if(hwcap & ARM_hwcap_bit::SHA3_bit)
72 detected_features |= CPUID::CPUID_ARM_SHA3_BIT;
73 if(hwcap & ARM_hwcap_bit::SM3_bit)
74 detected_features |= CPUID::CPUID_ARM_SM3_BIT;
75 if(hwcap & ARM_hwcap_bit::SM4_bit)
76 detected_features |= CPUID::CPUID_ARM_SM4_BIT;
77 if(hwcap & ARM_hwcap_bit::SHA2_512_bit)
78 detected_features |= CPUID::CPUID_ARM_SHA2_512_BIT;
79 if(hwcap & ARM_hwcap_bit::SVE_bit)
80 detected_features |= CPUID::CPUID_ARM_SVE_BIT;
83 #elif defined(BOTAN_TARGET_OS_IS_IOS) || defined(BOTAN_TARGET_OS_IS_MACOS)
86 detected_features |= CPUID::CPUID_ARM_NEON_BIT;
87 detected_features |= CPUID::CPUID_ARM_AES_BIT;
88 detected_features |= CPUID::CPUID_ARM_PMULL_BIT;
89 detected_features |= CPUID::CPUID_ARM_SHA1_BIT;
90 detected_features |= CPUID::CPUID_ARM_SHA2_BIT;
92 #if defined(BOTAN_TARGET_OS_IS_MACOS)
93 if(sysctlbyname_has_feature(
"hw.optional.armv8_2_sha3"))
94 detected_features |= CPUID::CPUID_ARM_SHA3_BIT;
95 if(sysctlbyname_has_feature(
"hw.optional.armv8_2_sha512"))
96 detected_features |= CPUID::CPUID_ARM_SHA2_512_BIT;
99 #elif defined(BOTAN_USE_GCC_INLINE_ASM)
110 auto neon_probe = []()
noexcept ->
int {
111 asm(
"and v0.16b, v0.16b, v0.16b");
114 auto aes_probe = []()
noexcept ->
int {
115 asm(
".word 0x4e284800");
118 auto pmull_probe = []()
noexcept ->
int {
119 asm(
".word 0x0ee0e000");
122 auto sha1_probe = []()
noexcept ->
int {
123 asm(
".word 0x5e280800");
126 auto sha2_probe = []()
noexcept ->
int {
127 asm(
".word 0x5e282800");
130 auto sha512_probe = []()
noexcept ->
int {
131 asm(
".long 0xcec08000");
138 detected_features |= CPUID::CPUID_ARM_NEON_BIT;
141 detected_features |= CPUID::CPUID_ARM_AES_BIT;
143 detected_features |= CPUID::CPUID_ARM_PMULL_BIT;
145 detected_features |= CPUID::CPUID_ARM_SHA1_BIT;
147 detected_features |= CPUID::CPUID_ARM_SHA2_BIT;
149 detected_features |= CPUID::CPUID_ARM_SHA2_512_BIT;
154 return detected_features;
int BOTAN_TEST_API run_cpu_instruction_probe(const std::function< int()> &probe_fn)
unsigned long get_auxval(unsigned long id)