Botan  2.1.0
Crypto and TLS for C++11
Public Types | Static Public Member Functions | List of all members
Botan::CPUID Class Reference

#include <cpuid.h>

Public Types

enum  CPUID_bits : uint64_t { CPUID_INITIALIZED_BIT = (1ULL << 63) }
 

Static Public Member Functions

static size_t cache_line_size ()
 
static void clear_cpuid_bit (CPUID_bits bit)
 
static bool has_cpuid_bit (CPUID_bits elem)
 
static bool has_simd_32 ()
 
static void initialize ()
 
static bool is_big_endian ()
 
static bool is_little_endian ()
 
static void print (std::ostream &o)
 
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:

Definition at line 35 of file cpuid.h.

Member Enumeration Documentation

enum Botan::CPUID::CPUID_bits : uint64_t
Enumerator
CPUID_INITIALIZED_BIT 

Definition at line 92 of file cpuid.h.

92  : uint64_t {
93 #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
94  // These values have no relation to cpuid bitfields
95 
96  // SIMD instruction sets
97  CPUID_SSE2_BIT = (1ULL << 0),
98  CPUID_SSSE3_BIT = (1ULL << 1),
99  CPUID_SSE41_BIT = (1ULL << 2),
100  CPUID_SSE42_BIT = (1ULL << 3),
101  CPUID_AVX2_BIT = (1ULL << 4),
102  CPUID_AVX512F_BIT = (1ULL << 5),
103 
104  // Misc useful instructions
105  CPUID_RDTSC_BIT = (1ULL << 10),
106  CPUID_BMI2_BIT = (1ULL << 11),
107  CPUID_ADX_BIT = (1ULL << 12),
108 
109  // Crypto-specific ISAs
110  CPUID_AESNI_BIT = (1ULL << 16),
111  CPUID_CLMUL_BIT = (1ULL << 17),
112  CPUID_RDRAND_BIT = (1ULL << 18),
113  CPUID_RDSEED_BIT = (1ULL << 19),
114  CPUID_SHA_BIT = (1ULL << 20),
115 #endif
116 
117 #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
118  CPUID_ALTIVEC_BIT = (1ULL << 0),
119 #endif
120 
121 #if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
122  CPUID_ARM_NEON_BIT = (1ULL << 0),
123  CPUID_ARM_AES_BIT = (1ULL << 16),
124  CPUID_ARM_PMULL_BIT = (1ULL << 17),
125  CPUID_ARM_SHA1_BIT = (1ULL << 18),
126  CPUID_ARM_SHA2_BIT = (1ULL << 19),
127 #endif
128 
129  CPUID_INITIALIZED_BIT = (1ULL << 63)
130  };

Member Function Documentation

static size_t Botan::CPUID::cache_line_size ( )
inlinestatic

Return a best guess of the cache line size

Definition at line 65 of file cpuid.h.

Referenced by Botan::prefetch_readonly(), and Botan::prefetch_readwrite().

66  {
67  if(g_processor_features == 0)
68  {
69  initialize();
70  }
71  return g_cache_line_size;
72  }
static void initialize()
Definition: cpuid.cpp:413
static void Botan::CPUID::clear_cpuid_bit ( CPUID_bits  bit)
inlinestatic

Definition at line 266 of file cpuid.h.

267  {
268  const uint64_t mask = ~(static_cast<uint64_t>(bit));
269  g_processor_features &= mask;
270  }
static bool Botan::CPUID::has_cpuid_bit ( CPUID_bits  elem)
inlinestatic

Definition at line 276 of file cpuid.h.

277  {
278  if(g_processor_features == 0)
279  initialize();
280  return ((g_processor_features & static_cast<uint64_t>(elem)) != 0);
281  }
static void initialize()
Definition: cpuid.cpp:413
bool Botan::CPUID::has_simd_32 ( )
static

Definition at line 351 of file cpuid.cpp.

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

352  {
353 #if defined(BOTAN_TARGET_SUPPORTS_SSE2)
354  return CPUID::has_sse2();
355 #elif defined(BOTAN_TARGET_SUPPORTS_ALTIVEC)
356  return CPUID::has_altivec();
357 #elif defined(BOTAN_TARGET_SUPPORTS_NEON)
358  return CPUID::has_neon();
359 #else
360  return true;
361 #endif
362  }
void Botan::CPUID::initialize ( )
static

Probe the CPU and see what extensions are supported

Definition at line 413 of file cpuid.cpp.

References BOTAN_ASSERT, and CPUID_INITIALIZED_BIT.

414  {
415  g_processor_features = 0;
416 
417 #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
418  g_processor_features = powerpc_detect_cpu_featutures();
419 #elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
420  g_processor_features = arm_detect_cpu_features(&g_cache_line_size);
421 #elif defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
422  g_processor_features = x86_detect_cpu_features(&g_cache_line_size);
423 #endif
424 
425  g_processor_features |= CPUID::CPUID_INITIALIZED_BIT;
426 
427  // Check runtime endian
428  const uint32_t endian32 = 0x01234567;
429  const uint8_t* e8 = reinterpret_cast<const uint8_t*>(&endian32);
430 
431  if(e8[0] == 0x01 && e8[1] == 0x23 && e8[2] == 0x45 && e8[3] == 0x67)
432  {
433  g_little_endian = false;
434  }
435  else if(e8[0] == 0x67 && e8[1] == 0x45 && e8[2] == 0x23 && e8[3] == 0x01)
436  {
437  g_little_endian = true;
438  }
439  else
440  {
441  throw Internal_Error("Unexpected endian at runtime, neither big nor little");
442  }
443 
444  // If we were compiled with a known endian, verify it matches at runtime
445 #if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
446  BOTAN_ASSERT(g_little_endian == true, "Build and runtime endian match");
447 #elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
448  BOTAN_ASSERT(g_little_endian == false, "Build and runtime endian match");
449 #endif
450 
451  }
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:27
static bool Botan::CPUID::is_big_endian ( )
inlinestatic

Definition at line 83 of file cpuid.h.

Referenced by Botan::SIMD_4x32::load_le(), and Botan::SIMD_4x32::store_le().

84  {
85  /*
86  * We do not support PDP endian, so the endian is
87  * always either big or little.
88  */
89  return is_little_endian() == false;
90  }
static bool is_little_endian()
Definition: cpuid.h:74
static bool Botan::CPUID::is_little_endian ( )
inlinestatic

Definition at line 74 of file cpuid.h.

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

75  {
76  if(g_processor_features == 0)
77  {
78  initialize();
79  }
80  return g_little_endian;
81  }
static void initialize()
Definition: cpuid.cpp:413
void Botan::CPUID::print ( std::ostream &  o)
static

Deprecated equivalent to o << "CPUID flags: " << CPUID::to_string() << "\n";

Definition at line 408 of file cpuid.cpp.

References to_string().

409  {
410  o << "CPUID flags: " << CPUID::to_string() << "\n";
411  }
static std::string to_string()
Definition: cpuid.cpp:365
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 365 of file cpuid.cpp.

References CPUID_PRINT, Botan::PKCS11::flags(), and Botan::string_join().

Referenced by print().

366  {
367  std::vector<std::string> flags;
368 
369 #define CPUID_PRINT(flag) do { if(has_##flag()) { flags.push_back(#flag); } } while(0)
370 
371 #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
372  CPUID_PRINT(sse2);
373  CPUID_PRINT(ssse3);
374  CPUID_PRINT(sse41);
375  CPUID_PRINT(sse42);
376  CPUID_PRINT(avx2);
377  CPUID_PRINT(avx512f);
378 
379  CPUID_PRINT(rdtsc);
380  CPUID_PRINT(bmi2);
381  CPUID_PRINT(adx);
382 
383  CPUID_PRINT(aes_ni);
384  CPUID_PRINT(clmul);
385  CPUID_PRINT(rdrand);
386  CPUID_PRINT(rdseed);
387  CPUID_PRINT(intel_sha);
388 #endif
389 
390 #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
391  CPUID_PRINT(altivec);
392 #endif
393 
394 #if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
395  CPUID_PRINT(neon);
396  CPUID_PRINT(arm_sha1);
397  CPUID_PRINT(arm_sha2);
398  CPUID_PRINT(arm_aes);
399  CPUID_PRINT(arm_pmull);
400 #endif
401 
402 #undef CPUID_PRINT
403 
404  return string_join(flags, ' ');
405  }
std::string string_join(const std::vector< std::string > &strs, char delim)
Definition: parsing.cpp:172
Flags flags(Flag flags)
Definition: p11.h:858
#define CPUID_PRINT(flag)

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