8#include <botan/internal/cpuid.h>
10#if defined(BOTAN_TARGET_ARCH_IS_ARM64)
11 #include <botan/internal/os_utils.h>
14#if defined(BOTAN_TARGET_OS_HAS_SYSCTLBYNAME)
15 #include <sys/sysctl.h>
16 #include <sys/types.h>
21#if defined(BOTAN_TARGET_ARCH_IS_ARM64)
23uint32_t CPUID::CPUID_Data::detect_cpu_features(uint32_t allowed) {
33 enum class ARM_hwcap_bit : uint64_t {
42 SHA2_512_bit = (1 << 21),
48 feat |= if_set(hwcap, ARM_hwcap_bit::NEON_bit, CPUID::CPUID_ARM_NEON_BIT, allowed);
50 if(feat & CPUID::CPUID_ARM_NEON_BIT) {
51 feat |= if_set(hwcap, ARM_hwcap_bit::AES_bit, CPUID::CPUID_ARM_AES_BIT, allowed);
52 feat |= if_set(hwcap, ARM_hwcap_bit::PMULL_bit, CPUID::CPUID_ARM_PMULL_BIT, allowed);
53 feat |= if_set(hwcap, ARM_hwcap_bit::SHA1_bit, CPUID::CPUID_ARM_SHA1_BIT, allowed);
54 feat |= if_set(hwcap, ARM_hwcap_bit::SHA2_bit, CPUID::CPUID_ARM_SHA2_BIT, allowed);
55 feat |= if_set(hwcap, ARM_hwcap_bit::SHA3_bit, CPUID::CPUID_ARM_SHA3_BIT, allowed);
56 feat |= if_set(hwcap, ARM_hwcap_bit::SM3_bit, CPUID::CPUID_ARM_SM3_BIT, allowed);
57 feat |= if_set(hwcap, ARM_hwcap_bit::SM4_bit, CPUID::CPUID_ARM_SM4_BIT, allowed);
58 feat |= if_set(hwcap, ARM_hwcap_bit::SHA2_512_bit, CPUID::CPUID_ARM_SHA2_512_BIT, allowed);
59 feat |= if_set(hwcap, ARM_hwcap_bit::SVE_bit, CPUID::CPUID_ARM_SVE_BIT, allowed);
67 #if defined(BOTAN_TARGET_OS_IS_IOS) || defined(BOTAN_TARGET_OS_IS_MACOS)
69 auto sysctlbyname_has_feature = [](
const char* feature_name) ->
bool {
71 size_t size =
sizeof(feature);
72 ::sysctlbyname(feature_name, &feature, &size,
nullptr, 0);
73 return (feature == 1);
77 feat |= CPUID::CPUID_ARM_NEON_BIT & allowed;
78 if(feat & CPUID::CPUID_ARM_NEON_BIT) {
79 feat |= CPUID::CPUID_ARM_AES_BIT & allowed;
80 feat |= CPUID::CPUID_ARM_PMULL_BIT & allowed;
81 feat |= CPUID::CPUID_ARM_SHA1_BIT & allowed;
82 feat |= CPUID::CPUID_ARM_SHA2_BIT & allowed;
84 if(sysctlbyname_has_feature(
"hw.optional.armv8_2_sha3")) {
85 feat |= CPUID::CPUID_ARM_SHA3_BIT & allowed;
87 if(sysctlbyname_has_feature(
"hw.optional.armv8_2_sha512")) {
88 feat |= CPUID::CPUID_ARM_SHA2_512_BIT & allowed;
92 #elif defined(BOTAN_USE_GCC_INLINE_ASM)
99 auto neon_probe = []()
noexcept ->
int {
100 asm(
"and v0.16b, v0.16b, v0.16b");
103 auto aes_probe = []()
noexcept ->
int {
104 asm(
".word 0x4e284800");
107 auto pmull_probe = []()
noexcept ->
int {
108 asm(
".word 0x0ee0e000");
111 auto sha1_probe = []()
noexcept ->
int {
112 asm(
".word 0x5e280800");
115 auto sha2_probe = []()
noexcept ->
int {
116 asm(
".word 0x5e282800");
119 auto sha512_probe = []()
noexcept ->
int {
120 asm(
".long 0xcec08000");
124 if(allowed & CPUID::CPUID_ARM_NEON_BIT) {
126 feat |= CPUID::CPUID_ARM_NEON_BIT;
129 if(feat & CPUID::CPUID_ARM_NEON_BIT) {
131 feat |= CPUID::CPUID_ARM_AES_BIT & allowed;
134 feat |= CPUID::CPUID_ARM_PMULL_BIT & allowed;
137 feat |= CPUID::CPUID_ARM_SHA1_BIT & allowed;
140 feat |= CPUID::CPUID_ARM_SHA2_BIT & allowed;
143 feat |= CPUID::CPUID_ARM_SHA2_512_BIT & allowed;
unsigned long auxval_hwcap()
int BOTAN_TEST_API run_cpu_instruction_probe(const std::function< int()> &probe_fn)
unsigned long get_auxval(unsigned long id)