• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 12976993364

26 Jan 2025 05:51PM UTC coverage: 91.251% (-0.005%) from 91.256%
12976993364

push

github

web-flow
Merge pull request #4599 from randombit/jack/split-api-and-compiler-headers

Split compiler.h into two headers

93963 of 102972 relevant lines covered (91.25%)

11437005.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.83
/src/lib/utils/cpuid/cpuid.cpp
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
#include <botan/internal/cpuid.h>
9

10
#include <botan/assert.h>
11
#include <botan/exceptn.h>
12
#include <botan/types.h>
13
#include <botan/internal/parsing.h>
14
#include <ostream>
15

16
#if defined(BOTAN_HAS_OS_UTILS)
17
   #include <botan/internal/os_utils.h>
18
#endif
19

20
namespace Botan {
21

22
//static
23
std::string CPUID::to_string() {
19✔
24
   std::vector<std::string> flags;
19✔
25

26
   auto append_fn = [&](bool flag, const char* flag_name) {
399✔
27
      if(flag) {
380✔
28
         flags.push_back(flag_name);
442✔
29
      }
30
   };
380✔
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);
19✔
37

38
   CPUID_PRINT(sse2);
19✔
39
   CPUID_PRINT(ssse3);
19✔
40
   CPUID_PRINT(avx2);
19✔
41

42
   CPUID_PRINT(bmi2);
19✔
43
   CPUID_PRINT(adx);
19✔
44
   CPUID_PRINT(gfni);
19✔
45

46
   CPUID_PRINT(aes_ni);
19✔
47
   CPUID_PRINT(clmul);
19✔
48
   CPUID_PRINT(rdrand);
19✔
49
   CPUID_PRINT(rdseed);
19✔
50
   CPUID_PRINT(intel_sha);
19✔
51
   CPUID_PRINT(intel_sha512);
19✔
52

53
   CPUID_PRINT(avx2_vaes);
19✔
54
   CPUID_PRINT(avx2_clmul);
19✔
55

56
   CPUID_PRINT(avx512);
19✔
57
   CPUID_PRINT(avx512_aes);
19✔
58
   CPUID_PRINT(avx512_clmul);
19✔
59

60
   CPUID_PRINT(intel_sm3);
19✔
61
   CPUID_PRINT(intel_sm4);
19✔
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, ' ');
38✔
86
}
19✔
87

88
//static
89
void CPUID::initialize() {
5,626✔
90
   state() = CPUID_Data();
5,626✔
91
}
5,626✔
92

93
namespace {
94

95
// Returns true if big-endian
96
bool runtime_check_if_big_endian() {
13,015✔
97
   // Check runtime endian
98
   const uint32_t endian32 = 0x01234567;
13,015✔
99
   const uint8_t* e8 = reinterpret_cast<const uint8_t*>(&endian32);
13,015✔
100

101
   bool is_big_endian = false;
13,015✔
102

103
   if(e8[0] == 0x01 && e8[1] == 0x23 && e8[2] == 0x45 && e8[3] == 0x67) {
13,015✔
104
      is_big_endian = true;
105
   } else if(e8[0] == 0x67 && e8[1] == 0x45 && e8[2] == 0x23 && e8[3] == 0x01) {
13,015✔
106
      is_big_endian = false;
107
   } else {
108
      throw Internal_Error("Unexpected endian at runtime, neither big nor little");
109
   }
110

111
   // If we were compiled with a known endian, verify it matches at runtime
112
#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
113
   BOTAN_ASSERT(!is_big_endian, "Build and runtime endian match");
13,015✔
114
#elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
115
   BOTAN_ASSERT(is_big_endian, "Build and runtime endian match");
116
#endif
117

118
   return is_big_endian;
13,015✔
119
}
120

121
#if defined(BOTAN_CPUID_HAS_DETECTION)
122
uint32_t cleared_cpuid_bits() {
13,015✔
123
   uint32_t cleared = 0;
13,015✔
124

125
   #if defined(BOTAN_HAS_OS_UTILS)
126
   std::string clear_cpuid_env;
13,015✔
127
   if(OS::read_env_variable(clear_cpuid_env, "BOTAN_CLEAR_CPUID")) {
13,015✔
128
      for(const auto& cpuid : split_on(clear_cpuid_env, ',')) {
336✔
129
         for(auto& bit : CPUID::bit_from_string(cpuid)) {
336✔
130
            cleared |= bit;
168✔
131
         }
168✔
132
      }
168✔
133
   }
134
   #endif
135

136
   return cleared;
13,015✔
137
}
13,015✔
138
#endif
139

140
}  // namespace
141

142
CPUID::CPUID_Data::CPUID_Data() {
13,015✔
143
   m_processor_features = 0;
13,015✔
144

145
#if defined(BOTAN_CPUID_HAS_DETECTION)
146
   m_processor_features = detect_cpu_features(~cleared_cpuid_bits());
13,015✔
147
#endif
148

149
   m_processor_features |= CPUID::CPUID_INITIALIZED_BIT;
13,015✔
150

151
   if(runtime_check_if_big_endian()) {
13,015✔
152
      m_processor_features |= CPUID::CPUID_IS_BIG_ENDIAN_BIT;
153
   }
154
}
13,015✔
155

156
std::vector<CPUID::CPUID_bits> CPUID::bit_from_string(std::string_view tok) {
211✔
157
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
158
   if(tok == "sse2" || tok == "simd") {
232✔
159
      return {CPUID::CPUID_SSE2_BIT};
7✔
160
   } else if(tok == "ssse3") {
204✔
161
      return {CPUID::CPUID_SSSE3_BIT};
6✔
162
   } else if(tok == "aesni" || tok == "aes_ni") {
208✔
163
      // aes_ni is the string printed on the console when running "botan cpuid"
164
      return {CPUID::CPUID_AESNI_BIT};
4✔
165
   } else if(tok == "clmul") {
194✔
166
      return {CPUID::CPUID_CLMUL_BIT};
3✔
167
   } else if(tok == "avx2") {
191✔
168
      return {CPUID::CPUID_AVX2_BIT};
6✔
169
   } else if(tok == "avx512") {
185✔
170
      return {CPUID::CPUID_AVX512_BIT};
2✔
171
   }
172
   // there were two if statements testing "sha" and "intel_sha" separately; combined
173
   else if(tok == "sha" || tok == "intel_sha") {
188✔
174
      return {CPUID::CPUID_SHA_BIT};
4✔
175
   } else if(tok == "rdtsc") {
179✔
176
      return {CPUID::CPUID_RDTSC_BIT};
1✔
177
   } else if(tok == "bmi2") {
178✔
178
      return {CPUID::CPUID_BMI_BIT};
4✔
179
   } else if(tok == "adx") {
174✔
180
      return {CPUID::CPUID_ADX_BIT};
1✔
181
   } else if(tok == "gfni") {
173✔
182
      return {CPUID::CPUID_GFNI_BIT};
1✔
183
   } else if(tok == "rdrand") {
172✔
184
      return {CPUID::CPUID_RDRAND_BIT};
1✔
185
   } else if(tok == "rdseed") {
171✔
186
      return {CPUID::CPUID_RDSEED_BIT};
1✔
187
   } else if(tok == "avx512_aes") {
170✔
188
      return {CPUID::CPUID_AVX512_AES_BIT};
×
189
   } else if(tok == "avx512_clmul") {
170✔
190
      return {CPUID::CPUID_AVX512_CLMUL_BIT};
×
191
   } else if(tok == "avx2_vaes") {
170✔
192
      return {CPUID::CPUID_AVX2_AES_BIT};
2✔
193
   } else if(tok == "avx2_clmul") {
168✔
194
      return {CPUID::CPUID_AVX2_CLMUL_BIT};
156✔
195
   } else if(tok == "intel_sm3") {
12✔
196
      return {CPUID::CPUID_SM3_BIT};
×
197
   } else if(tok == "intel_sm4") {
12✔
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 {};
12✔
238
}
239

240
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc