Botan 3.8.1
Crypto and TLS for C&
cpuid.h
Go to the documentation of this file.
1/*
2* Runtime CPU detection
3* (C) 2009,2010,2013,2017,2023 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#ifndef BOTAN_CPUID_H_
9#define BOTAN_CPUID_H_
10
11#include <botan/types.h>
12#include <botan/internal/target_info.h>
13#include <optional>
14#include <string>
15
16#if defined(BOTAN_HAS_CPUID_DETECTION)
17 #include <botan/internal/cpuid_features.h>
18#endif
19
20namespace Botan {
21
22#if !defined(BOTAN_HAS_CPUID_DETECTION)
23// A no-op CPUFeature
25 public:
26 enum Bit : uint32_t {};
27
28 uint32_t as_u32() const;
29
31
32 static std::optional<CPUFeature> from_string(std::string_view);
33
34 std::string to_string() const;
35};
36#endif
37
38/**
39* A class handling runtime CPU feature detection. It is limited to
40* just the features necessary to implement CPU specific code in Botan,
41* rather than being a general purpose utility.
42*/
43class BOTAN_TEST_API CPUID final {
44 public:
46
47 /**
48 * Probe the CPU and see what extensions are supported
49 */
50 static void initialize();
51
52 /**
53 * Return a possibly empty string containing list of known CPU
54 * extensions. Each name will be seperated by a space, and the ordering
55 * will be arbitrary. This list only contains values that are useful to
56 * Botan (for example FMA instructions are not checked).
57 *
58 * Example outputs "sse2 ssse3 rdtsc", "neon arm_aes", "altivec"
59 */
60 static std::string to_string();
61
62 /**
63 * Check if a feature is supported returning the associated string if so
64 *
65 * This is a helper function used to implement provider()
66 */
67 static std::optional<std::string> check(CPUID::Feature feat) {
68 if(state().has_bit(feat.as_u32())) {
69 return feat.to_string();
70 } else {
71 return {};
72 }
73 }
74
75 /**
76 * Check if a feature is supported returning the associated string if so
77 *
78 * This is a helper function used to implement provider()
79 */
80 static std::optional<std::string> check(CPUID::Feature feat1, CPUID::Feature feat2) {
81 if(state().has_bit((feat1.as_u32() | feat2.as_u32()))) {
82 // Typically feat2 is a secondary feature that is almost but not
83 // completely implied by feat1 (ex: AVX2 + BMI2) which we have to
84 // check for completness, but don't reflect into the provider name.
85 return feat1.to_string();
86 } else {
87 return {};
88 }
89 }
90
91 /**
92 * Check if a feature is supported
93 */
94 static bool has(CPUID::Feature feat) { return state().has_bit(feat.as_u32()); }
95
96 /**
97 * Check if two features are both supported
98 */
99 static bool has(CPUID::Feature feat1, CPUID::Feature feat2) {
100 return state().has_bit(feat1.as_u32() | feat2.as_u32());
101 }
102
103 /*
104 * Clear a CPUID bit
105 * Call CPUID::initialize to reset
106 *
107 * This is only exposed for testing and should never be called within the library
108 */
109 static void clear_cpuid_bit(CPUID::Feature bit) { state().clear_cpuid_bit(bit.as_u32()); }
110
111 static std::optional<CPUID::Feature> bit_from_string(std::string_view tok);
112
113 /**
114 * A common helper for the various CPUID implementations
115 */
116 template <typename T>
117 static inline uint32_t if_set(uint64_t cpuid, T flag, CPUID::Feature bit, uint32_t allowed) {
118 const uint64_t flag64 = static_cast<uint64_t>(flag);
119 if((cpuid & flag64) == flag64) {
120 return (bit.as_u32() & allowed);
121 } else {
122 return 0;
123 }
124 }
125
126 private:
127 struct CPUID_Data {
128 public:
129 CPUID_Data();
130
131 CPUID_Data(const CPUID_Data& other) = default;
132 CPUID_Data& operator=(const CPUID_Data& other) = default;
133
134 void clear_cpuid_bit(uint32_t bit) { m_processor_features &= ~bit; }
135
136 bool has_bit(uint32_t bit) const { return (m_processor_features & bit) == bit; }
137
138 uint32_t bitset() const { return m_processor_features; }
139
140 private:
141#if defined(BOTAN_HAS_CPUID_DETECTION)
142 static uint32_t detect_cpu_features(uint32_t allowed_bits);
143#endif
144
145 uint32_t m_processor_features;
146 };
147
148 static CPUID_Data& state() {
149 static CPUID::CPUID_Data g_cpuid;
150 return g_cpuid;
151 }
152};
153
154} // namespace Botan
155
156#endif
#define BOTAN_TEST_API
Definition api.h:39
uint32_t as_u32() const
Definition cpuid.cpp:20
CPUFeature(Bit)
Definition cpuid.h:30
std::string to_string() const
Definition cpuid.cpp:28
static std::optional< std::string > check(CPUID::Feature feat)
Definition cpuid.h:67
static bool has(CPUID::Feature feat1, CPUID::Feature feat2)
Definition cpuid.h:99
static uint32_t if_set(uint64_t cpuid, T flag, CPUID::Feature bit, uint32_t allowed)
Definition cpuid.h:117
CPUFeature Feature
Definition cpuid.h:45
static void clear_cpuid_bit(CPUID::Feature bit)
Definition cpuid.h:109
static std::string to_string()
Definition cpuid.cpp:34
static void initialize()
Definition cpuid.cpp:50
static std::optional< std::string > check(CPUID::Feature feat1, CPUID::Feature feat2)
Definition cpuid.h:80
static bool has(CPUID::Feature feat)
Definition cpuid.h:94
std::string to_string(ErrorType type)
Convert an ErrorType to string.
Definition exceptn.cpp:13