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

randombit / botan / 14117568268

27 Mar 2025 10:05PM UTC coverage: 91.534% (+0.006%) from 91.528%
14117568268

push

github

web-flow
Merge pull request #4797 from randombit/jack/split-cpuid-impl

Split up CPUID implementation into submodules

95364 of 104184 relevant lines covered (91.53%)

11527621.82 hits per line

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

96.63
/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 <botan/internal/target_info.h>
15
#include <ostream>
16

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

21
namespace Botan {
22

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

27
   auto append_fn = [&](bool flag, const char* flag_name) {
399✔
28
      if(flag) {
380✔
29
         flags.push_back(flag_name);
442✔
30
      }
31
   };
380✔
32

33
   // NOLINTNEXTLINE(*-macro-usage)
34
#define CPUID_PRINT(flag) append_fn(has_##flag(), #flag)
35

36
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
37
   CPUID_PRINT(rdtsc);
19✔
38

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

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

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

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

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

61
   CPUID_PRINT(intel_sm3);
19✔
62
   CPUID_PRINT(intel_sm4);
19✔
63

64
#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
65
   CPUID_PRINT(altivec);
66
   CPUID_PRINT(power_crypto);
67
   CPUID_PRINT(darn_rng);
68
#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
69
   CPUID_PRINT(neon);
70
   CPUID_PRINT(arm_sve);
71

72
   CPUID_PRINT(arm_sha1);
73
   CPUID_PRINT(arm_sha2);
74
   CPUID_PRINT(arm_aes);
75
   CPUID_PRINT(arm_pmull);
76
   CPUID_PRINT(arm_sha2_512);
77
   CPUID_PRINT(arm_sha3);
78
   CPUID_PRINT(arm_sm3);
79
   CPUID_PRINT(arm_sm4);
80
#else
81
   BOTAN_UNUSED(append_fn);
82
#endif
83

84
#undef CPUID_PRINT
85

86
   return string_join(flags, ' ');
38✔
87
}
19✔
88

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

94
#if defined(BOTAN_HAS_CPUID_DETECTION)
95

96
namespace {
97

98
uint32_t cleared_cpuid_bits() {
13,017✔
99
   uint32_t cleared = 0;
13,017✔
100

101
   #if defined(BOTAN_HAS_OS_UTILS)
102
   std::string clear_cpuid_env;
13,017✔
103
   if(OS::read_env_variable(clear_cpuid_env, "BOTAN_CLEAR_CPUID")) {
13,017✔
104
      for(const auto& cpuid : split_on(clear_cpuid_env, ',')) {
336✔
105
         for(auto& bit : CPUID::bit_from_string(cpuid)) {
336✔
106
            cleared |= bit;
168✔
107
         }
168✔
108
      }
168✔
109
   }
110
   #endif
111

112
   return cleared;
13,017✔
113
}
13,017✔
114

115
}  // namespace
116

117
#endif
118

119
CPUID::CPUID_Data::CPUID_Data() {
13,017✔
120
   m_processor_features = 0;
13,017✔
121

122
#if defined(BOTAN_HAS_CPUID_DETECTION)
123
   m_processor_features = detect_cpu_features(~cleared_cpuid_bits());
13,017✔
124
#endif
125

126
   m_processor_features |= CPUID::CPUID_INITIALIZED_BIT;
13,017✔
127
}
13,017✔
128

129
std::vector<CPUID::CPUID_bits> CPUID::bit_from_string(std::string_view tok) {
213✔
130
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
131
   if(tok == "sse2" || tok == "simd") {
234✔
132
      return {CPUID::CPUID_SSE2_BIT};
7✔
133
   } else if(tok == "ssse3") {
206✔
134
      return {CPUID::CPUID_SSSE3_BIT};
6✔
135
   } else if(tok == "aesni" || tok == "aes_ni") {
210✔
136
      // aes_ni is the string printed on the console when running "botan cpuid"
137
      return {CPUID::CPUID_AESNI_BIT};
4✔
138
   } else if(tok == "clmul") {
196✔
139
      return {CPUID::CPUID_CLMUL_BIT};
3✔
140
   } else if(tok == "avx2") {
386✔
141
      return {CPUID::CPUID_AVX2_BIT};
6✔
142
   } else if(tok == "avx512") {
187✔
143
      return {CPUID::CPUID_AVX512_BIT};
2✔
144
   }
145
   // there were two if statements testing "sha" and "intel_sha" separately; combined
146
   // TODO(Botan4) remove "sha"
147
   else if(tok == "sha" || tok == "intel_sha") {
190✔
148
      return {CPUID::CPUID_SHA_BIT};
4✔
149
   } else if(tok == "intel_sha512") {
181✔
150
      return {CPUID::CPUID_SHA512_BIT};
1✔
151
   } else if(tok == "rdtsc") {
180✔
152
      return {CPUID::CPUID_RDTSC_BIT};
1✔
153
   } else if(tok == "bmi2") {
179✔
154
      return {CPUID::CPUID_BMI_BIT};
4✔
155
   } else if(tok == "adx") {
175✔
156
      return {CPUID::CPUID_ADX_BIT};
1✔
157
   } else if(tok == "gfni") {
174✔
158
      return {CPUID::CPUID_GFNI_BIT};
1✔
159
   } else if(tok == "rdrand") {
173✔
160
      return {CPUID::CPUID_RDRAND_BIT};
1✔
161
   } else if(tok == "rdseed") {
172✔
162
      return {CPUID::CPUID_RDSEED_BIT};
1✔
163
   } else if(tok == "avx512_aes") {
171✔
164
      return {CPUID::CPUID_AVX512_AES_BIT};
×
165
   } else if(tok == "avx512_clmul") {
171✔
166
      return {CPUID::CPUID_AVX512_CLMUL_BIT};
×
167
   } else if(tok == "avx2_vaes") {
171✔
168
      return {CPUID::CPUID_AVX2_AES_BIT};
2✔
169
   } else if(tok == "avx2_clmul") {
169✔
170
      return {CPUID::CPUID_AVX2_CLMUL_BIT};
156✔
171
   } else if(tok == "intel_sm3") {
13✔
172
      return {CPUID::CPUID_SM3_BIT};
×
173
   } else if(tok == "intel_sm4") {
13✔
174
      return {CPUID::CPUID_SM4_BIT};
1✔
175
   }
176

177
#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
178
   if(tok == "altivec" || tok == "simd") {
179
      return {CPUID::CPUID_ALTIVEC_BIT};
180
   } else if(tok == "power_crypto") {
181
      return {CPUID::CPUID_POWER_CRYPTO_BIT};
182
   } else if(tok == "darn_rng") {
183
      return {CPUID::CPUID_DARN_BIT};
184
   }
185

186
#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
187
   if(tok == "neon" || tok == "simd") {
188
      return {CPUID::CPUID_ARM_NEON_BIT};
189
   } else if(tok == "arm_sve") {
190
      return {CPUID::CPUID_ARM_SVE_BIT};
191
   } else if(tok == "armv8sha1" || tok == "arm_sha1") {
192
      return {CPUID::CPUID_ARM_SHA1_BIT};
193
   } else if(tok == "armv8sha2" || tok == "arm_sha2") {
194
      return {CPUID::CPUID_ARM_SHA2_BIT};
195
   } else if(tok == "armv8aes" || tok == "arm_aes") {
196
      return {CPUID::CPUID_ARM_AES_BIT};
197
   } else if(tok == "armv8pmull" || tok == "arm_pmull") {
198
      return {CPUID::CPUID_ARM_PMULL_BIT};
199
   } else if(tok == "armv8sha3" || tok == "arm_sha3") {
200
      return {CPUID::CPUID_ARM_SHA3_BIT};
201
   } else if(tok == "armv8sha2_512" || tok == "arm_sha2_512") {
202
      return {CPUID::CPUID_ARM_SHA2_512_BIT};
203
   } else if(tok == "armv8sm3" || tok == "arm_sm3") {
204
      return {CPUID::CPUID_ARM_SM3_BIT};
205
   } else if(tok == "armv8sm4" || tok == "arm_sm4") {
206
      return {CPUID::CPUID_ARM_SM4_BIT};
207
   }
208

209
#else
210
   BOTAN_UNUSED(tok);
211
#endif
212

213
   return {};
12✔
214
}
215

216
}  // 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