8 #include <botan/cpuid.h>
10 #if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
12 #if defined(BOTAN_TARGET_OS_IS_IOS)
13 #include <sys/types.h>
14 #include <sys/sysctl.h>
17 #include <botan/internal/os_utils.h>
25 #if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
27 #if defined(BOTAN_TARGET_OS_IS_IOS)
31 uint64_t flags_by_ios_machine_type(
const std::string& machine)
41 size_t min_version_neon;
42 size_t min_version_armv8;
45 static const version_info min_versions[] = {
52 if(machine.size() < 3)
55 auto comma = machine.find(
',');
58 if(comma == std::string::npos)
61 std::string product = machine.substr(0, comma);
65 while(product.size() > 1 && ::isdigit(product.back()))
67 const size_t digit = product.back() -
'0';
68 version += digit * place;
76 for(
const version_info& info : min_versions)
78 if(info.name != product)
81 if(version >= info.min_version_armv8)
83 return CPUID::CPUID_ARM_AES_BIT |
84 CPUID::CPUID_ARM_PMULL_BIT |
85 CPUID::CPUID_ARM_SHA1_BIT |
86 CPUID::CPUID_ARM_SHA2_BIT |
87 CPUID::CPUID_ARM_NEON_BIT;
90 if(version >= info.min_version_neon)
91 return CPUID::CPUID_ARM_NEON_BIT;
102 uint64_t CPUID::CPUID_Data::detect_cpu_features(
size_t* cache_line_size)
104 uint64_t detected_features = 0;
106 #if defined(BOTAN_TARGET_OS_HAS_GETAUXVAL) || defined(BOTAN_TARGET_OS_HAS_ELF_AUX_INFO)
115 #if defined(BOTAN_TARGET_ARCH_IS_ARM32)
116 NEON_bit = (1 << 12),
118 PMULL_bit = (1 << 1),
122 ARCH_hwcap_neon = 16,
123 ARCH_hwcap_crypto = 26,
124 #elif defined(BOTAN_TARGET_ARCH_IS_ARM64)
127 PMULL_bit = (1 << 4),
130 SHA3_bit = (1 << 17),
133 SHA2_512_bit = (1 << 21),
136 ARCH_hwcap_neon = 16,
137 ARCH_hwcap_crypto = 16,
141 #if defined(AT_DCACHEBSIZE)
143 const unsigned long dcache_line = ::getauxval(AT_DCACHEBSIZE);
146 if(dcache_line == 32 || dcache_line == 64 || dcache_line == 128)
147 *cache_line_size =
static_cast<size_t>(dcache_line);
152 const unsigned long hwcap_neon =
OS::get_auxval(ARM_hwcap_bit::ARCH_hwcap_neon);
153 if(hwcap_neon & ARM_hwcap_bit::NEON_bit)
154 detected_features |= CPUID::CPUID_ARM_NEON_BIT;
161 const unsigned long hwcap_crypto =
OS::get_auxval(ARM_hwcap_bit::ARCH_hwcap_crypto);
162 if(hwcap_crypto & ARM_hwcap_bit::AES_bit)
163 detected_features |= CPUID::CPUID_ARM_AES_BIT;
164 if(hwcap_crypto & ARM_hwcap_bit::PMULL_bit)
165 detected_features |= CPUID::CPUID_ARM_PMULL_BIT;
166 if(hwcap_crypto & ARM_hwcap_bit::SHA1_bit)
167 detected_features |= CPUID::CPUID_ARM_SHA1_BIT;
168 if(hwcap_crypto & ARM_hwcap_bit::SHA2_bit)
169 detected_features |= CPUID::CPUID_ARM_SHA2_BIT;
171 #if defined(BOTAN_TARGET_ARCH_IS_ARM64)
172 if(hwcap_crypto & ARM_hwcap_bit::SHA3_bit)
173 detected_features |= CPUID::CPUID_ARM_SHA3_BIT;
174 if(hwcap_crypto & ARM_hwcap_bit::SM3_bit)
175 detected_features |= CPUID::CPUID_ARM_SM3_BIT;
176 if(hwcap_crypto & ARM_hwcap_bit::SM4_bit)
177 detected_features |= CPUID::CPUID_ARM_SM4_BIT;
178 if(hwcap_crypto & ARM_hwcap_bit::SHA2_512_bit)
179 detected_features |= CPUID::CPUID_ARM_SHA2_512_BIT;
180 if(hwcap_crypto & ARM_hwcap_bit::SVE_bit)
181 detected_features |= CPUID::CPUID_ARM_SVE_BIT;
184 #elif defined(BOTAN_TARGET_OS_IS_IOS)
186 char machine[64] = { 0 };
187 size_t size =
sizeof(machine) - 1;
188 ::sysctlbyname(
"hw.machine", machine, &size,
nullptr, 0);
190 detected_features = flags_by_ios_machine_type(machine);
192 #elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_ARM64)
203 auto neon_probe = []() noexcept ->
int {
asm(
"and v0.16b, v0.16b, v0.16b");
return 1; };
204 auto aes_probe = []() noexcept ->
int {
asm(
".word 0x4e284800");
return 1; };
205 auto pmull_probe = []() noexcept ->
int {
asm(
".word 0x0ee0e000");
return 1; };
206 auto sha1_probe = []() noexcept ->
int {
asm(
".word 0x5e280800");
return 1; };
207 auto sha2_probe = []() noexcept ->
int {
asm(
".word 0x5e282800");
return 1; };
213 detected_features |= CPUID::CPUID_ARM_NEON_BIT;
216 detected_features |= CPUID::CPUID_ARM_AES_BIT;
218 detected_features |= CPUID::CPUID_ARM_PMULL_BIT;
220 detected_features |= CPUID::CPUID_ARM_SHA1_BIT;
222 detected_features |= CPUID::CPUID_ARM_SHA2_BIT;
227 return detected_features;
int BOTAN_TEST_API run_cpu_instruction_probe(std::function< int()> probe_fn)
#define BOTAN_UNUSED(...)
unsigned long get_auxval(unsigned long id)