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

randombit / botan / 4855062618

01 May 2023 10:04PM UTC coverage: 92.147% (+0.004%) from 92.143%
4855062618

push

github

77604 of 84218 relevant lines covered (92.15%)

11834916.63 hits per line

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

96.2
/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/types.h>
11
#include <botan/exceptn.h>
12
#include <botan/internal/parsing.h>
13
#include <botan/internal/os_utils.h>
14
#include <ostream>
15

16
namespace Botan {
17

18
bool CPUID::has_simd_32()
299,271✔
19
   {
20
#if defined(BOTAN_TARGET_SUPPORTS_SSE2)
21
   return CPUID::has_sse2();
299,271✔
22
#elif defined(BOTAN_TARGET_SUPPORTS_ALTIVEC)
23
   return CPUID::has_altivec();
24
#elif defined(BOTAN_TARGET_SUPPORTS_NEON)
25
   return CPUID::has_neon();
26
#else
27
   return true;
28
#endif
29
   }
30

31
//static
32
std::string CPUID::to_string()
16✔
33
   {
34
   std::vector<std::string> flags;
16✔
35

36
   auto append_fn = [&](bool flag, const char* flag_name)
240✔
37
      {
38
      if(flag)
224✔
39
         flags.push_back(flag_name);
288✔
40
      };
224✔
41

42
   // NOLINTNEXTLINE(*-macro-usage)
43
#define CPUID_PRINT(flag) append_fn(has_##flag(), #flag)
44

45
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
46
   CPUID_PRINT(rdtsc);
16✔
47

48
   CPUID_PRINT(sse2);
16✔
49
   CPUID_PRINT(ssse3);
16✔
50
   CPUID_PRINT(avx2);
16✔
51

52
   CPUID_PRINT(bmi2);
16✔
53
   CPUID_PRINT(adx);
16✔
54

55
   CPUID_PRINT(aes_ni);
16✔
56
   CPUID_PRINT(clmul);
16✔
57
   CPUID_PRINT(rdrand);
16✔
58
   CPUID_PRINT(rdseed);
16✔
59
   CPUID_PRINT(intel_sha);
16✔
60

61
   CPUID_PRINT(avx512);
16✔
62
   CPUID_PRINT(avx512_aes);
16✔
63
   CPUID_PRINT(avx512_clmul);
16✔
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, ' ');
32✔
87
   }
16✔
88

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

95
namespace {
96

97
// Returns true if big-endian
98
bool runtime_check_if_big_endian()
12,838✔
99
   {
100
   // Check runtime endian
101
   const uint32_t endian32 = 0x01234567;
12,838✔
102
   const uint8_t* e8 = reinterpret_cast<const uint8_t*>(&endian32);
12,838✔
103

104
   bool is_big_endian = false;
12,838✔
105

106
   if(e8[0] == 0x01 && e8[1] == 0x23 && e8[2] == 0x45 && e8[3] == 0x67)
12,838✔
107
      {
108
      is_big_endian = true;
109
      }
110
   else if(e8[0] == 0x67 && e8[1] == 0x45 && e8[2] == 0x23 && e8[3] == 0x01)
12,838✔
111
      {
112
      is_big_endian = false;
113
      }
114
   else
115
      {
116
      throw Internal_Error("Unexpected endian at runtime, neither big nor little");
117
      }
118

119
   // If we were compiled with a known endian, verify it matches at runtime
120
#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
121
   BOTAN_ASSERT(!is_big_endian, "Build and runtime endian match");
12,838✔
122
#elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
123
   BOTAN_ASSERT(is_big_endian, "Build and runtime endian match");
124
#endif
125

126
   return is_big_endian;
12,838✔
127
   }
128

129
}
130

131
CPUID::CPUID_Data::CPUID_Data()
12,838✔
132
   {
133
   m_processor_features = 0;
12,838✔
134

135
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) || \
136
    defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY) || \
137
    defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
138

139
   m_processor_features = detect_cpu_features();
12,838✔
140

141
#endif
142

143
   m_processor_features |= CPUID::CPUID_INITIALIZED_BIT;
12,838✔
144

145
   if(runtime_check_if_big_endian())
12,838✔
146
      m_processor_features |= CPUID::CPUID_IS_BIG_ENDIAN_BIT;
147

148
   std::string clear_cpuid_env;
12,838✔
149
   if(OS::read_env_variable(clear_cpuid_env, "BOTAN_CLEAR_CPUID"))
12,838✔
150
      {
151
      for(const auto& cpuid : split_on(clear_cpuid_env, ','))
282✔
152
         {
153
         for(auto& bit: CPUID::bit_from_string(cpuid))
282✔
154
            {
155
            const uint32_t cleared = ~static_cast<uint32_t>(bit);
141✔
156
            m_processor_features &= cleared;
141✔
157
            }
141✔
158
         }
141✔
159
      }
160
   }
12,838✔
161

162
std::vector<CPUID::CPUID_bits>
163
CPUID::bit_from_string(std::string_view tok)
179✔
164
   {
165
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
166
   if(tok == "sse2" || tok == "simd")
211✔
167
      return {CPUID::CPUID_SSE2_BIT};
7✔
168
   if(tok == "ssse3")
181✔
169
      return {CPUID::CPUID_SSSE3_BIT};
6✔
170
   // aes_ni is the string printed on the console when running "botan cpuid"
171
   if(tok == "aesni" || tok == "aes_ni")
310✔
172
      return {CPUID::CPUID_AESNI_BIT};
4✔
173
   if(tok == "clmul")
165✔
174
      return {CPUID::CPUID_CLMUL_BIT};
3✔
175
   if(tok == "avx2")
165✔
176
      return {CPUID::CPUID_AVX2_BIT};
6✔
177
   if(tok == "avx512")
287✔
178
      return {CPUID::CPUID_AVX512_BIT};
×
179
   // there were two if statements testing "sha" and "intel_sha" separately; combined
180
   if(tok == "sha" || tok == "intel_sha")
159✔
181
      return {CPUID::CPUID_SHA_BIT};
3✔
182
   if(tok == "rdtsc")
152✔
183
      return {CPUID::CPUID_RDTSC_BIT};
1✔
184
   if(tok == "bmi2")
151✔
185
      return {CPUID::CPUID_BMI_BIT};
4✔
186
   if(tok == "adx")
145✔
187
      return {CPUID::CPUID_ADX_BIT};
1✔
188
   if(tok == "rdrand")
277✔
189
      return {CPUID::CPUID_RDRAND_BIT};
1✔
190
   if(tok == "rdseed")
144✔
191
      return {CPUID::CPUID_RDSEED_BIT};
132✔
192
   if(tok == "avx512_aes")
11✔
193
      return {CPUID::CPUID_AVX512_AES_BIT};
×
194
   if(tok == "avx512_clmul")
12✔
195
      return {CPUID::CPUID_AVX512_CLMUL_BIT};
×
196

197
#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
198
   if(tok == "altivec" || tok == "simd")
199
      return {CPUID::CPUID_ALTIVEC_BIT};
200
   if(tok == "power_crypto")
201
      return {CPUID::CPUID_POWER_CRYPTO_BIT};
202
   if(tok == "darn_rng")
203
      return {CPUID::CPUID_DARN_BIT};
204

205
#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
206
   if(tok == "neon" || tok == "simd")
207
      return {CPUID::CPUID_ARM_NEON_BIT};
208
   if(tok == "arm_sve")
209
      return {CPUID::CPUID_ARM_SVE_BIT};
210
   if(tok == "armv8sha1" || tok == "arm_sha1")
211
      return {CPUID::CPUID_ARM_SHA1_BIT};
212
   if(tok == "armv8sha2" || tok == "arm_sha2")
213
      return {CPUID::CPUID_ARM_SHA2_BIT};
214
   if(tok == "armv8aes" || tok == "arm_aes")
215
      return {CPUID::CPUID_ARM_AES_BIT};
216
   if(tok == "armv8pmull" || tok == "arm_pmull")
217
      return {CPUID::CPUID_ARM_PMULL_BIT};
218
   if(tok == "armv8sha3" || tok == "arm_sha3")
219
      return {CPUID::CPUID_ARM_SHA3_BIT};
220
   if(tok == "armv8sha2_512" || tok == "arm_sha2_512")
221
      return {CPUID::CPUID_ARM_SHA2_512_BIT};
222
   if(tok == "armv8sm3" || tok == "arm_sm3")
223
      return {CPUID::CPUID_ARM_SM3_BIT};
224
   if(tok == "armv8sm4" || tok == "arm_sm4")
225
      return {CPUID::CPUID_ARM_SM4_BIT};
226

227
#else
228
   BOTAN_UNUSED(tok);
229
#endif
230

231
   return {};
11✔
232
   }
233

234
}
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

© 2025 Coveralls, Inc