Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

cpuid.h
Go to the documentation of this file.
1 /*
2 * Runtime CPU detection
3 * (C) 2009,2010,2013,2017 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 <string>
13 #include <iosfwd>
14
15 namespace Botan {
16
17 /**
18 * A class handling runtime CPU feature detection. It is limited to
19 * just the features necessary to implement CPU specific code in Botan,
20 * rather than being a general purpose utility.
21 *
22 * This class supports:
23 *
24 * - x86 features using CPUID. x86 is also the only processor with
25 * accurate cache line detection currently.
26 *
27 * - PowerPC AltiVec detection on Linux, NetBSD, OpenBSD, and Darwin
28 *
29 * - ARM NEON and crypto extensions detection. On Linux and Android
30 * systems which support getauxval, that is used to access CPU
31 * feature information. Otherwise a relatively portable but
32 * thread-unsafe mechanism involving executing probe functions which
33 * catching SIGILL signal is used.
34 */
35 class BOTAN_DLL CPUID
36 {
37 public:
38 /**
39 * Probe the CPU and see what extensions are supported
40 */
41 static void initialize();
42
43 static bool has_simd_32();
44
45 /**
46 * Deprecated equivalent to
47 * o << "CPUID flags: " << CPUID::to_string() << "\n";
48 */
49 BOTAN_DEPRECATED("Use CPUID::to_string")
50 static void print(std::ostream& o);
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 * Return a best guess of the cache line size
64 */
65 static size_t cache_line_size()
66 {
67 if(g_processor_features == 0)
68 {
69 initialize();
70 }
71 return g_cache_line_size;
72 }
73
74 static bool is_little_endian()
75 {
76 if(g_processor_features == 0)
77 {
78 initialize();
79 }
80 return g_little_endian;
81 }
82
83 static bool is_big_endian()
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 }
91
92 enum CPUID_bits : 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 };
131
132 #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
133 /**
134 * Check if the processor supports AltiVec/VMX
135 */
136 static bool has_altivec()
137 { return has_cpuid_bit(CPUID_ALTIVEC_BIT); }
138 #endif
139
140 #if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
141 /**
142 * Check if the processor supports NEON SIMD
143 */
144 static bool has_neon()
145 { return has_cpuid_bit(CPUID_ARM_NEON_BIT); }
146
147 /**
148 * Check if the processor supports ARMv8 SHA1
149 */
150 static bool has_arm_sha1()
151 { return has_cpuid_bit(CPUID_ARM_SHA1_BIT); }
152
153 /**
154 * Check if the processor supports ARMv8 SHA2
155 */
156 static bool has_arm_sha2()
157 { return has_cpuid_bit(CPUID_ARM_SHA2_BIT); }
158
159 /**
160 * Check if the processor supports ARMv8 AES
161 */
162 static bool has_arm_aes()
163 { return has_cpuid_bit(CPUID_ARM_AES_BIT); }
164
165 /**
166 * Check if the processor supports ARMv8 PMULL
167 */
168 static bool has_arm_pmull()
169 { return has_cpuid_bit(CPUID_ARM_PMULL_BIT); }
170 #endif
171
172 #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
173
174 /**
175 * Check if the processor supports RDTSC
176 */
177 static bool has_rdtsc()
178 { return has_cpuid_bit(CPUID_RDTSC_BIT); }
179
180 /**
181 * Check if the processor supports SSE2
182 */
183 static bool has_sse2()
184 { return has_cpuid_bit(CPUID_SSE2_BIT); }
185
186 /**
187 * Check if the processor supports SSSE3
188 */
189 static bool has_ssse3()
190 { return has_cpuid_bit(CPUID_SSSE3_BIT); }
191
192 /**
193 * Check if the processor supports SSE4.1
194 */
195 static bool has_sse41()
196 { return has_cpuid_bit(CPUID_SSE41_BIT); }
197
198 /**
199 * Check if the processor supports SSE4.2
200 */
201 static bool has_sse42()
202 { return has_cpuid_bit(CPUID_SSE42_BIT); }
203
204 /**
205 * Check if the processor supports AVX2
206 */
207 static bool has_avx2()
208 { return has_cpuid_bit(CPUID_AVX2_BIT); }
209
210 /**
211 * Check if the processor supports AVX-512F
212 */
213 static bool has_avx512f()
214 { return has_cpuid_bit(CPUID_AVX512F_BIT); }
215
216 /**
217 * Check if the processor supports BMI2
218 */
219 static bool has_bmi2()
220 { return has_cpuid_bit(CPUID_BMI2_BIT); }
221
222 /**
223 * Check if the processor supports AES-NI
224 */
225 static bool has_aes_ni()
226 { return has_cpuid_bit(CPUID_AESNI_BIT); }
227
228 /**
229 * Check if the processor supports CLMUL
230 */
231 static bool has_clmul()
232 { return has_cpuid_bit(CPUID_CLMUL_BIT); }
233
234 /**
235 * Check if the processor supports Intel SHA extension
236 */
237 static bool has_intel_sha()
238 { return has_cpuid_bit(CPUID_SHA_BIT); }
239
240 /**
241 * Check if the processor supports ADX extension
242 */
243 static bool has_adx()
244 { return has_cpuid_bit(CPUID_ADX_BIT); }
245
246 /**
247 * Check if the processor supports RDRAND
248 */
249 static bool has_rdrand()
250 { return has_cpuid_bit(CPUID_RDRAND_BIT); }
251
252 /**
253 * Check if the processor supports RDSEED
254 */
255 static bool has_rdseed()
256 { return has_cpuid_bit(CPUID_RDSEED_BIT); }
257 #endif
258
259 /*
260 * Clear a CPUID bit
261 * Call CPUID::initialize to reset
262 *
263 * This is only exposed for testing, don't use unless you know
264 * what you are doing.
265 */
266 static void clear_cpuid_bit(CPUID_bits bit)
267 {
268 const uint64_t mask = ~(static_cast<uint64_t>(bit));
269 g_processor_features &= mask;
270 }
271
272 /*
273 * Don't call this function, use CPUID::has_xxx above
274 * It is only exposed for the tests.
275 */
276 static bool has_cpuid_bit(CPUID_bits elem)
277 {
278 if(g_processor_features == 0)
279 initialize();
280 return ((g_processor_features & static_cast<uint64_t>(elem)) != 0);
281 }
282
283 private:
284 static bool g_little_endian;
285 static size_t g_cache_line_size;
286 static uint64_t g_processor_features;
287 };
288
289 }
290
291 #endif
Botan::CPUID
Definition: cpuid.h:35
Botan::CPUID::cache_line_size
static size_t cache_line_size()
Definition: cpuid.h:65
Botan::BOTAN_DEPRECATED
class BOTAN_DLL BOTAN_DEPRECATED("LibraryInitializer is no longer required") LibraryInitializer
Definition: init.h:22
Botan::CPUID::is_little_endian
static bool is_little_endian()
Definition: cpuid.h:74
Botan
Definition: alg_id.cpp:13
Botan::CPUID::CPUID_bits
CPUID_bits
Definition: cpuid.h:92
Botan::to_string
std::string to_string(const secure_vector< uint8_t > &bytes)
Definition: stl_util.h:25
Botan::CPUID::clear_cpuid_bit
static void clear_cpuid_bit(CPUID_bits bit)
Definition: cpuid.h:266
Botan::CPUID::has_cpuid_bit
static bool has_cpuid_bit(CPUID_bits elem)
Definition: cpuid.h:276
Botan::CPUID::is_big_endian
static bool is_big_endian()
Definition: cpuid.h:83