Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

cpuid.cpp
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 #include <botan/cpuid.h>
9 #include <botan/types.h>
10 #include <botan/exceptn.h>
11 #include <botan/parsing.h>
12 #include <ostream>
13
14 namespace Botan {
15
16 bool CPUID::has_simd_32()
17 {
18 #if defined(BOTAN_TARGET_SUPPORTS_SSE2)
19 return CPUID::has_sse2();
20 #elif defined(BOTAN_TARGET_SUPPORTS_ALTIVEC)
21 return CPUID::has_altivec();
22 #elif defined(BOTAN_TARGET_SUPPORTS_NEON)
23 return CPUID::has_neon();
24 #else
25 return true;
26 #endif
27 }
28
29 //static
30 std::string CPUID::to_string()
31 {
32 std::vector<std::string> flags;
33
34 #define CPUID_PRINT(flag) do { if(has_##flag()) { flags.push_back(#flag); } } while(0)
35
36 #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
37 CPUID_PRINT(sse2);
38 CPUID_PRINT(ssse3);
39 CPUID_PRINT(sse41);
40 CPUID_PRINT(sse42);
41 CPUID_PRINT(avx2);
42 CPUID_PRINT(avx512f);
43
44 CPUID_PRINT(rdtsc);
45 CPUID_PRINT(bmi1);
46 CPUID_PRINT(bmi2);
47 CPUID_PRINT(adx);
48
49 CPUID_PRINT(aes_ni);
50 CPUID_PRINT(clmul);
51 CPUID_PRINT(rdrand);
52 CPUID_PRINT(rdseed);
53 CPUID_PRINT(intel_sha);
54 #endif
55
56 #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
57 CPUID_PRINT(altivec);
58 CPUID_PRINT(power_crypto);
59 CPUID_PRINT(darn_rng);
60 #endif
61
62 #if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
63 CPUID_PRINT(neon);
64 CPUID_PRINT(arm_sve);
65
66 CPUID_PRINT(arm_sha1);
67 CPUID_PRINT(arm_sha2);
68 CPUID_PRINT(arm_aes);
69 CPUID_PRINT(arm_pmull);
70 CPUID_PRINT(arm_sha2_512);
71 CPUID_PRINT(arm_sha3);
72 CPUID_PRINT(arm_sm3);
73 CPUID_PRINT(arm_sm4);
74 #endif
75
76 #undef CPUID_PRINT
77
78 return string_join(flags, ' ');
79 }
80
81 //static
82 void CPUID::print(std::ostream& o)
83 {
84 o << "CPUID flags: " << CPUID::to_string() << "\n";
85 }
86
87 //static
88 void CPUID::initialize()
89 {
90 state() = CPUID_Data();
91 }
92
93 CPUID::CPUID_Data::CPUID_Data()
94 {
95 #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) || \
96 defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY) || \
97 defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
98
99 m_cache_line_size = 0;
100 m_processor_features = detect_cpu_features(&m_cache_line_size);
101
102 #endif
103
104 m_processor_features |= CPUID::CPUID_INITIALIZED_BIT;
105
106 if(m_cache_line_size == 0)
107 m_cache_line_size = BOTAN_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE;
108
109 m_endian_status = runtime_check_endian();
110 }
111
112 //static
113 CPUID::Endian_Status CPUID::CPUID_Data::runtime_check_endian()
114 {
115 // Check runtime endian
116 const uint32_t endian32 = 0x01234567;
117 const uint8_t* e8 = reinterpret_cast<const uint8_t*>(&endian32);
118
119 CPUID::Endian_Status endian = CPUID::Endian_Status::Unknown;
120
121 if(e8[0] == 0x01 && e8[1] == 0x23 && e8[2] == 0x45 && e8[3] == 0x67)
122 {
123 endian = CPUID::Endian_Status::Big;
124 }
125 else if(e8[0] == 0x67 && e8[1] == 0x45 && e8[2] == 0x23 && e8[3] == 0x01)
126 {
127 endian = CPUID::Endian_Status::Little;
128 }
129 else
130 {
131 throw Internal_Error("Unexpected endian at runtime, neither big nor little");
132 }
133
134 // If we were compiled with a known endian, verify it matches at runtime
135 #if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
136 BOTAN_ASSERT(endian == CPUID::Endian_Status::Little, "Build and runtime endian match");
137 #elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
138 BOTAN_ASSERT(endian == CPUID::Endian_Status::Big, "Build and runtime endian match");
139 #endif
140
141 return endian;
142 }
143
144 std::vector<Botan::CPUID::CPUID_bits>
145 CPUID::bit_from_string(const std::string& tok)
146 {
147 #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
148 if(tok == "sse2" || tok == "simd")
149 return {Botan::CPUID::CPUID_SSE2_BIT};
150 if(tok == "ssse3")
151 return {Botan::CPUID::CPUID_SSSE3_BIT};
152 if(tok == "aesni")
153 return {Botan::CPUID::CPUID_AESNI_BIT};
154 if(tok == "clmul")
155 return {Botan::CPUID::CPUID_CLMUL_BIT};
156 if(tok == "avx2")
157 return {Botan::CPUID::CPUID_AVX2_BIT};
158 if(tok == "sha")
159 return {Botan::CPUID::CPUID_SHA_BIT};
160 if(tok == "bmi2")
161 return {Botan::CPUID::CPUID_BMI2_BIT};
162 if(tok == "adx")
163 return {Botan::CPUID::CPUID_ADX_BIT};
164 if(tok == "intel_sha")
165 return {Botan::CPUID::CPUID_SHA_BIT};
166
167 #elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
168 if(tok == "altivec" || tok == "simd")
169 return {Botan::CPUID::CPUID_ALTIVEC_BIT};
170 if(tok == "power_crypto")
171 return {Botan::CPUID::CPUID_POWER_CRYPTO_BIT};
172
173 #elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
174 if(tok == "neon" || tok == "simd")
175 return {Botan::CPUID::CPUID_ARM_NEON_BIT};
176 if(tok == "armv8sha1")
177 return {Botan::CPUID::CPUID_ARM_SHA1_BIT};
178 if(tok == "armv8sha2")
179 return {Botan::CPUID::CPUID_ARM_SHA2_BIT};
180 if(tok == "armv8aes")
181 return {Botan::CPUID::CPUID_ARM_AES_BIT};
182 if(tok == "armv8pmull")
183 return {Botan::CPUID::CPUID_ARM_PMULL_BIT};
184 if(tok == "armv8sha3")
185 return {Botan::CPUID::CPUID_ARM_SHA3_BIT};
186 if(tok == "armv8sha2_512")
187 return {Botan::CPUID::CPUID_ARM_SHA2_512_BIT};
188 if(tok == "armv8sm3")
189 return {Botan::CPUID::CPUID_ARM_SM3_BIT};
190 if(tok == "armv8sm4")
191 return {Botan::CPUID::CPUID_ARM_SM4_BIT};
192
193 #else
194 BOTAN_UNUSED(tok);
195 #endif
196
197 return {};
198 }
199
200 }
Botan::CPUID::Endian_Status::Big
Botan::CPUID::Endian_Status::Unknown
Botan::PKCS11::flags
Flags flags(Flag flags)
Definition: p11.h:858
Botan::CPUID::CPUID_INITIALIZED_BIT
Definition: cpuid.h:140
Botan::CPUID::has_simd_32
static bool has_simd_32()
Definition: cpuid.cpp:16
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
Botan::CPUID::to_string
static std::string to_string()
Definition: cpuid.cpp:30
Botan::CPUID::bit_from_string
static std::vector< CPUID::CPUID_bits > bit_from_string(const std::string &tok)
Definition: cpuid.cpp:145
Botan
Definition: alg_id.cpp:13
BOTAN_UNUSED
#define BOTAN_UNUSED(...)
Definition: assert.h:142
Botan::CPUID::print
static void print(std::ostream &o)
Definition: cpuid.cpp:82
Botan::CPUID::initialize
static void initialize()
Definition: cpuid.cpp:88
Botan::OCSP::Response_Status_Code::Internal_Error
CPUID_PRINT
#define CPUID_PRINT(flag)
Botan::CPUID::Endian_Status::Little
Botan::string_join
std::string string_join(const std::vector< std::string > &strs, char delim)
Definition: parsing.cpp:182