Botan 3.7.1
Crypto and TLS for C&
Botan::CPUID Class Referencefinal

#include <cpuid.h>

Public Types

enum  CPUID_bits : uint32_t { CPUID_IS_BIG_ENDIAN_BIT = (1U << 30) , CPUID_INITIALIZED_BIT = (1U << 31) }
 

Static Public Member Functions

static std::vector< CPUID::CPUID_bitsbit_from_string (std::string_view tok)
 
static void clear_cpuid_bit (CPUID_bits bit)
 
static bool has_carryless_multiply ()
 
static bool has_cpuid_bit (CPUID_bits elem)
 
static bool has_hw_aes ()
 
static bool has_simd_32 ()
 
static bool has_vperm ()
 
template<typename T >
static uint32_t if_set (uint64_t cpuid, T flag, CPUID::CPUID_bits bit, uint32_t allowed)
 
static void initialize ()
 
static bool is_big_endian ()
 
static bool is_little_endian ()
 
static std::string to_string ()
 

Detailed Description

A class handling runtime CPU feature detection. It is limited to just the features necessary to implement CPU specific code in Botan, rather than being a general purpose utility.

This class supports:

  • x86 features using CPUID. x86 is also the only processor with accurate cache line detection currently.
  • PowerPC AltiVec detection on Linux, NetBSD, OpenBSD, and macOS
  • ARM NEON and crypto extensions detection. On Linux and Android systems which support getauxval, that is used to access CPU feature information. Otherwise a relatively portable but thread-unsafe mechanism involving executing probe functions which catching SIGILL signal is used.

Definition at line 43 of file cpuid.h.

Member Enumeration Documentation

◆ CPUID_bits

enum Botan::CPUID::CPUID_bits : uint32_t
Enumerator
CPUID_IS_BIG_ENDIAN_BIT 
CPUID_INITIALIZED_BIT 

Definition at line 96 of file cpuid.h.

96 : uint32_t {
97#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
98 // These values have no relation to cpuid bitfields
99
100 // SIMD instruction sets
101 CPUID_SSE2_BIT = (1U << 0),
102 CPUID_SSSE3_BIT = (1U << 1),
103 CPUID_AVX2_BIT = (1U << 2),
104 CPUID_AVX512_BIT = (1U << 3),
105
106 // Misc useful instructions
107 CPUID_RDTSC_BIT = (1U << 10),
108 CPUID_ADX_BIT = (1U << 11),
109 CPUID_BMI_BIT = (1U << 12),
110 CPUID_GFNI_BIT = (1U << 13),
111
112 // Crypto-specific ISAs
113 CPUID_AESNI_BIT = (1U << 16),
114 CPUID_CLMUL_BIT = (1U << 17),
115 CPUID_RDRAND_BIT = (1U << 18),
116 CPUID_RDSEED_BIT = (1U << 19),
117 CPUID_SHA_BIT = (1U << 20),
118 CPUID_AVX512_AES_BIT = (1U << 21),
119 CPUID_AVX512_CLMUL_BIT = (1U << 22),
120 CPUID_AVX2_AES_BIT = (1U << 23),
121 CPUID_AVX2_CLMUL_BIT = (1U << 24),
122 CPUID_SHA512_BIT = (1U << 25),
123 CPUID_SM3_BIT = (1U << 26),
124 CPUID_SM4_BIT = (1U << 27),
125#endif
126
127#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
128 CPUID_ALTIVEC_BIT = (1U << 0),
129 CPUID_POWER_CRYPTO_BIT = (1U << 1),
130 CPUID_DARN_BIT = (1U << 2),
131#endif
132
133#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
134 CPUID_ARM_NEON_BIT = (1U << 0),
135 CPUID_ARM_SVE_BIT = (1U << 1),
136 CPUID_ARM_AES_BIT = (1U << 16),
137 CPUID_ARM_PMULL_BIT = (1U << 17),
138 CPUID_ARM_SHA1_BIT = (1U << 18),
139 CPUID_ARM_SHA2_BIT = (1U << 19),
140 CPUID_ARM_SHA3_BIT = (1U << 20),
141 CPUID_ARM_SHA2_512_BIT = (1U << 21),
142 CPUID_ARM_SM3_BIT = (1U << 22),
143 CPUID_ARM_SM4_BIT = (1U << 23),
144#endif
145
146 CPUID_IS_BIG_ENDIAN_BIT = (1U << 30),
147 CPUID_INITIALIZED_BIT = (1U << 31)
148 };
@ CPUID_INITIALIZED_BIT
Definition cpuid.h:147
@ CPUID_IS_BIG_ENDIAN_BIT
Definition cpuid.h:146

Member Function Documentation

◆ bit_from_string()

std::vector< CPUID::CPUID_bits > Botan::CPUID::bit_from_string ( std::string_view tok)
static

Definition at line 156 of file cpuid.cpp.

156 {
157#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
158 if(tok == "sse2" || tok == "simd") {
159 return {CPUID::CPUID_SSE2_BIT};
160 } else if(tok == "ssse3") {
161 return {CPUID::CPUID_SSSE3_BIT};
162 } else if(tok == "aesni" || tok == "aes_ni") {
163 // aes_ni is the string printed on the console when running "botan cpuid"
164 return {CPUID::CPUID_AESNI_BIT};
165 } else if(tok == "clmul") {
166 return {CPUID::CPUID_CLMUL_BIT};
167 } else if(tok == "avx2") {
168 return {CPUID::CPUID_AVX2_BIT};
169 } else if(tok == "avx512") {
170 return {CPUID::CPUID_AVX512_BIT};
171 }
172 // there were two if statements testing "sha" and "intel_sha" separately; combined
173 else if(tok == "sha" || tok == "intel_sha") {
174 return {CPUID::CPUID_SHA_BIT};
175 } else if(tok == "rdtsc") {
176 return {CPUID::CPUID_RDTSC_BIT};
177 } else if(tok == "bmi2") {
178 return {CPUID::CPUID_BMI_BIT};
179 } else if(tok == "adx") {
180 return {CPUID::CPUID_ADX_BIT};
181 } else if(tok == "gfni") {
182 return {CPUID::CPUID_GFNI_BIT};
183 } else if(tok == "rdrand") {
184 return {CPUID::CPUID_RDRAND_BIT};
185 } else if(tok == "rdseed") {
186 return {CPUID::CPUID_RDSEED_BIT};
187 } else if(tok == "avx512_aes") {
188 return {CPUID::CPUID_AVX512_AES_BIT};
189 } else if(tok == "avx512_clmul") {
190 return {CPUID::CPUID_AVX512_CLMUL_BIT};
191 } else if(tok == "avx2_vaes") {
192 return {CPUID::CPUID_AVX2_AES_BIT};
193 } else if(tok == "avx2_clmul") {
194 return {CPUID::CPUID_AVX2_CLMUL_BIT};
195 } else if(tok == "intel_sm3") {
196 return {CPUID::CPUID_SM3_BIT};
197 } else if(tok == "intel_sm4") {
198 return {CPUID::CPUID_SM4_BIT};
199 }
200
201#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
202 if(tok == "altivec" || tok == "simd") {
203 return {CPUID::CPUID_ALTIVEC_BIT};
204 } else if(tok == "power_crypto") {
205 return {CPUID::CPUID_POWER_CRYPTO_BIT};
206 } else if(tok == "darn_rng") {
207 return {CPUID::CPUID_DARN_BIT};
208 }
209
210#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
211 if(tok == "neon" || tok == "simd") {
212 return {CPUID::CPUID_ARM_NEON_BIT};
213 } else if(tok == "arm_sve") {
214 return {CPUID::CPUID_ARM_SVE_BIT};
215 } else if(tok == "armv8sha1" || tok == "arm_sha1") {
216 return {CPUID::CPUID_ARM_SHA1_BIT};
217 } else if(tok == "armv8sha2" || tok == "arm_sha2") {
218 return {CPUID::CPUID_ARM_SHA2_BIT};
219 } else if(tok == "armv8aes" || tok == "arm_aes") {
220 return {CPUID::CPUID_ARM_AES_BIT};
221 } else if(tok == "armv8pmull" || tok == "arm_pmull") {
222 return {CPUID::CPUID_ARM_PMULL_BIT};
223 } else if(tok == "armv8sha3" || tok == "arm_sha3") {
224 return {CPUID::CPUID_ARM_SHA3_BIT};
225 } else if(tok == "armv8sha2_512" || tok == "arm_sha2_512") {
226 return {CPUID::CPUID_ARM_SHA2_512_BIT};
227 } else if(tok == "armv8sm3" || tok == "arm_sm3") {
228 return {CPUID::CPUID_ARM_SM3_BIT};
229 } else if(tok == "armv8sm4" || tok == "arm_sm4") {
230 return {CPUID::CPUID_ARM_SM4_BIT};
231 }
232
233#else
234 BOTAN_UNUSED(tok);
235#endif
236
237 return {};
238}
#define BOTAN_UNUSED
Definition assert.h:118

References BOTAN_UNUSED.

◆ clear_cpuid_bit()

static void Botan::CPUID::clear_cpuid_bit ( CPUID_bits bit)
inlinestatic

Definition at line 385 of file cpuid.h.

385{ state().clear_cpuid_bit(static_cast<uint32_t>(bit)); }

◆ has_carryless_multiply()

static bool Botan::CPUID::has_carryless_multiply ( )
inlinestatic

Check if the processor supports carryless multiply (CLMUL, PMULL)

Definition at line 366 of file cpuid.h.

366 {
367#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
368 return has_clmul();
369#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
370 return has_arm_pmull();
371#elif defined(BOTAN_TARGET_ARCH_IS_PPC64)
372 return has_power_crypto();
373#else
374 return false;
375#endif
376 }

Referenced by Botan::GHASH::provider().

◆ has_cpuid_bit()

static bool Botan::CPUID::has_cpuid_bit ( CPUID_bits elem)
inlinestatic

Definition at line 391 of file cpuid.h.

391 {
392 const uint32_t elem32 = static_cast<uint32_t>(elem);
393 return state().has_bit(elem32);
394 }

◆ has_hw_aes()

static bool Botan::CPUID::has_hw_aes ( )
inlinestatic

Check if the processor supports hardware AES instructions

Definition at line 350 of file cpuid.h.

350 {
351#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
352 return has_aes_ni();
353#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
354 return has_arm_aes();
355#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
356 return has_power_crypto();
357#else
358 return false;
359#endif
360 }

Referenced by Botan::AES_128::decrypt_n(), Botan::AES_192::decrypt_n(), Botan::AES_256::decrypt_n(), Botan::AES_128::encrypt_n(), Botan::AES_192::encrypt_n(), and Botan::AES_256::encrypt_n().

◆ has_simd_32()

static bool Botan::CPUID::has_simd_32 ( )
inlinestatic

Return true if a 4x32 SIMD instruction set is available (SSE2, NEON, or Altivec/VMX)

Definition at line 84 of file cpuid.h.

84 {
85#if defined(BOTAN_TARGET_SUPPORTS_SSE2)
86 return CPUID::has_sse2();
87#elif defined(BOTAN_TARGET_SUPPORTS_ALTIVEC)
88 return CPUID::has_altivec();
89#elif defined(BOTAN_TARGET_SUPPORTS_NEON)
90 return CPUID::has_neon();
91#else
92 return false;
93#endif
94 }

Referenced by Botan::Noekeon::decrypt_n(), Botan::Serpent::decrypt_n(), Botan::SHACAL2::decrypt_n(), Botan::Noekeon::encrypt_n(), Botan::Serpent::encrypt_n(), Botan::SHACAL2::encrypt_n(), Botan::Noekeon::parallelism(), Botan::SHACAL2::parallelism(), Botan::ChaCha::provider(), Botan::Noekeon::provider(), Botan::Serpent::provider(), and Botan::SHACAL2::provider().

◆ has_vperm()

static bool Botan::CPUID::has_vperm ( )
inlinestatic

Check if the processor supports byte-level vector permutes (SSSE3, NEON, Altivec)

Definition at line 335 of file cpuid.h.

335 {
336#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
337 return has_ssse3();
338#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
339 return has_neon();
340#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
341 return has_altivec();
342#else
343 return false;
344#endif
345 }

Referenced by Botan::AES_128::decrypt_n(), Botan::AES_192::decrypt_n(), Botan::AES_256::decrypt_n(), Botan::AES_128::encrypt_n(), Botan::AES_192::encrypt_n(), Botan::AES_256::encrypt_n(), Botan::GHASH::provider(), and Botan::ZFEC::provider().

◆ if_set()

template<typename T >
static uint32_t Botan::CPUID::if_set ( uint64_t cpuid,
T flag,
CPUID::CPUID_bits bit,
uint32_t allowed )
inlinestatic

A common helper for the various CPUID implementations

Definition at line 402 of file cpuid.h.

402 {
403 const uint64_t flag64 = static_cast<uint64_t>(flag);
404 if((cpuid & flag64) == flag64) {
405 return (bit & allowed);
406 } else {
407 return 0;
408 }
409 }

◆ initialize()

void Botan::CPUID::initialize ( )
static

Probe the CPU and see what extensions are supported

Definition at line 89 of file cpuid.cpp.

89 {
90 state() = CPUID_Data();
91}

◆ is_big_endian()

static bool Botan::CPUID::is_big_endian ( )
inlinestatic

Definition at line 70 of file cpuid.h.

70 {
71#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
72 return true;
73#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
74 return false;
75#else
77#endif
78 }
static bool has_cpuid_bit(CPUID_bits elem)
Definition cpuid.h:391

Referenced by Botan::SIMD_4x32::load_le().

◆ is_little_endian()

static bool Botan::CPUID::is_little_endian ( )
inlinestatic

Definition at line 60 of file cpuid.h.

60 {
61#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
62 return true;
63#elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
64 return false;
65#else
67#endif
68 }

Referenced by Botan::XMSS_Tools::concat(), Botan::XMSS_Tools::concat(), Botan::SIMD_4x32::load_be(), Botan::SIMD_4x32::store_be(), and Botan::SIMD_4x32::store_le().

◆ to_string()

std::string Botan::CPUID::to_string ( )
static

Return a possibly empty string containing list of known CPU extensions. Each name will be seperated by a space, and the ordering will be arbitrary. This list only contains values that are useful to Botan (for example FMA instructions are not checked).

Example outputs "sse2 ssse3 rdtsc", "neon arm_aes", "altivec"

Definition at line 23 of file cpuid.cpp.

23 {
24 std::vector<std::string> flags;
25
26 auto append_fn = [&](bool flag, const char* flag_name) {
27 if(flag) {
28 flags.push_back(flag_name);
29 }
30 };
31
32 // NOLINTNEXTLINE(*-macro-usage)
33#define CPUID_PRINT(flag) append_fn(has_##flag(), #flag)
34
35#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
36 CPUID_PRINT(rdtsc);
37
38 CPUID_PRINT(sse2);
39 CPUID_PRINT(ssse3);
40 CPUID_PRINT(avx2);
41
42 CPUID_PRINT(bmi2);
43 CPUID_PRINT(adx);
44 CPUID_PRINT(gfni);
45
46 CPUID_PRINT(aes_ni);
47 CPUID_PRINT(clmul);
48 CPUID_PRINT(rdrand);
49 CPUID_PRINT(rdseed);
50 CPUID_PRINT(intel_sha);
51 CPUID_PRINT(intel_sha512);
52
53 CPUID_PRINT(avx2_vaes);
54 CPUID_PRINT(avx2_clmul);
55
56 CPUID_PRINT(avx512);
57 CPUID_PRINT(avx512_aes);
58 CPUID_PRINT(avx512_clmul);
59
60 CPUID_PRINT(intel_sm3);
61 CPUID_PRINT(intel_sm4);
62
63#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
64 CPUID_PRINT(altivec);
65 CPUID_PRINT(power_crypto);
66 CPUID_PRINT(darn_rng);
67#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
68 CPUID_PRINT(neon);
69 CPUID_PRINT(arm_sve);
70
71 CPUID_PRINT(arm_sha1);
72 CPUID_PRINT(arm_sha2);
73 CPUID_PRINT(arm_aes);
74 CPUID_PRINT(arm_pmull);
75 CPUID_PRINT(arm_sha2_512);
76 CPUID_PRINT(arm_sha3);
77 CPUID_PRINT(arm_sm3);
78 CPUID_PRINT(arm_sm4);
79#else
80 BOTAN_UNUSED(append_fn);
81#endif
82
83#undef CPUID_PRINT
84
85 return string_join(flags, ' ');
86}
#define CPUID_PRINT(flag)
Flags flags(Flag flags)
Definition p11.h:838
std::string string_join(const std::vector< std::string > &strs, char delim)
Definition parsing.cpp:140

References BOTAN_UNUSED, CPUID_PRINT, and Botan::string_join().


The documentation for this class was generated from the following files: