1 #include <nil/crypto3/utilities/cpuid/cpuid.hpp>
3 #if defined(BOOST_ARCH_ARM)
5 #if defined(CRYPTO3_TARGET_OS_HAS_GETAUXVAL)
8 #elif defined(CRYPTO3_TARGET_OS_IS_IOS)
10 #include <sys/sysctl.h>
13 #include <nil/crypto3/utilities/os_utils.h>
22 #if defined(BOOST_ARCH_ARM)
24 #if defined(CRYPTO3_TARGET_OS_IS_IOS)
28 uint64_t flags_by_ios_machine_type(
const std::string &machine) {
37 size_t min_version_neon;
38 size_t min_version_armv8;
41 static const version_info min_versions[] = {
48 if (machine.size() < 3)
51 auto comma = machine.find(
',');
54 if (comma == std::string::npos)
57 std::string product = machine.substr(0, comma);
61 while (product.size() > 1 && ::isdigit(product.back())) {
62 const size_t digit = product.back() -
'0';
63 version += digit * place;
71 for (
const version_info &info : min_versions) {
72 if (info.name != product)
75 if (version >= info.min_version_armv8) {
76 return cpuid::CPUID_ARM_RIJNDAEL_BIT | cpuid::CPUID_ARM_PMULL_BIT | cpuid::CPUID_ARM_SHA1_BIT |
77 cpuid::CPUID_ARM_SHA2_BIT | cpuid::CPUID_ARM_NEON_BIT;
80 if (version >= info.min_version_neon)
81 return cpuid::CPUID_ARM_NEON_BIT;
92 uint64_t cpuid::detect_cpu_features(
size_t *cache_line_size) {
93 uint64_t detected_features = 0;
95 #if defined(CRYPTO3_TARGET_OS_HAS_GETAUXVAL)
104 #if defined(CRYPTO3_TARGET_ARCHITECTURE_IS_ARM32)
105 NEON_bit = (1 << 12),
107 PMULL_bit = (1 << 1),
111 ARCH_hwcap_neon = 16,
112 ARCH_hwcap_crypto = 26,
113 #elif defined(CRYPTO3_TARGET_ARCHITECTURE_IS_ARM64)
116 PMULL_bit = (1 << 4),
120 ARCH_hwcap_neon = 16,
121 ARCH_hwcap_crypto = 16,
125 #if defined(AT_DCACHEBSIZE)
126 const unsigned long dcache_line = ::getauxval(AT_DCACHEBSIZE);
129 if (dcache_line == 32 || dcache_line == 64 || dcache_line == 128)
133 const unsigned long hwcap_neon = ::getauxval(ARM_hwcap_bit::ARCH_hwcap_neon);
134 if (hwcap_neon & ARM_hwcap_bit::NEON_bit)
135 detected_features |= cpuid::CPUID_ARM_NEON_BIT;
142 const unsigned long hwcap_crypto = ::getauxval(ARM_hwcap_bit::ARCH_hwcap_crypto);
143 if (hwcap_crypto & ARM_hwcap_bit::AES_bit)
144 detected_features |= cpuid::CPUID_ARM_RIJNDAEL_BIT;
145 if (hwcap_crypto & ARM_hwcap_bit::PMULL_bit)
146 detected_features |= cpuid::CPUID_ARM_PMULL_BIT;
147 if (hwcap_crypto & ARM_hwcap_bit::SHA1_bit)
148 detected_features |= cpuid::CPUID_ARM_SHA1_BIT;
149 if (hwcap_crypto & ARM_hwcap_bit::SHA2_bit)
150 detected_features |= cpuid::CPUID_ARM_SHA2_BIT;
152 #elif defined(CRYPTO3_TARGET_OS_IS_IOS)
154 char machine[64] = {0};
155 size_t size =
sizeof(machine) - 1;
156 ::sysctlbyname(
"hw.machine", machine, &size,
nullptr, 0);
158 detected_features = flags_by_ios_machine_type(machine);
160 #elif defined(CRYPTO3_USE_GCC_INLINE_ASM) && defined(CRYPTO3_TARGET_ARCHITECTURE_IS_ARM64)
171 auto neon_probe = []() ->
int {
172 asm(
"and v0.16b, v0.16b, v0.16b");
175 auto aes_probe = []() ->
int {
176 asm(
".word 0x4e284800");
179 auto pmull_probe = []() ->
int {
180 asm(
".word 0x0ee0e000");
183 auto sha1_probe = []() ->
int {
184 asm(
".word 0x5e280800");
187 auto sha2_probe = []() ->
int {
188 asm(
".word 0x5e282800");
194 if (run_cpu_instruction_probe(neon_probe) == 1) {
195 detected_features |= cpuid::CPUID_ARM_NEON_BIT;
197 if (run_cpu_instruction_probe(aes_probe) == 1)
198 detected_features |= cpuid::CPUID_ARM_RIJNDAEL_BIT;
199 if (run_cpu_instruction_probe(pmull_probe) == 1)
200 detected_features |= cpuid::CPUID_ARM_PMULL_BIT;
201 if (run_cpu_instruction_probe(sha1_probe) == 1)
202 detected_features |= cpuid::CPUID_ARM_SHA1_BIT;
203 if (run_cpu_instruction_probe(sha2_probe) == 1)
204 detected_features |= cpuid::CPUID_ARM_SHA2_BIT;
209 return detected_features;
static size_t cache_line_size()
Definition: cpuid.hpp:134