Coverage Report

Created: 2020-02-14 15:38

/src/botan/src/lib/utils/cpuid/cpuid.cpp
Line
Count
Source (jump to first uncovered line)
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
0
   {
18
0
#if defined(BOTAN_TARGET_SUPPORTS_SSE2)
19
0
   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
0
   {
32
0
   std::vector<std::string> flags;
33
0
34
0
#define CPUID_PRINT(flag) do { if(has_##flag()) { flags.push_back(#flag); } } while(0)
35
0
36
0
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
37
0
   CPUID_PRINT(sse2);
38
0
   CPUID_PRINT(ssse3);
39
0
   CPUID_PRINT(sse41);
40
0
   CPUID_PRINT(sse42);
41
0
   CPUID_PRINT(avx2);
42
0
   CPUID_PRINT(avx512f);
43
0
44
0
   CPUID_PRINT(rdtsc);
45
0
   CPUID_PRINT(bmi1);
46
0
   CPUID_PRINT(bmi2);
47
0
   CPUID_PRINT(adx);
48
0
49
0
   CPUID_PRINT(aes_ni);
50
0
   CPUID_PRINT(clmul);
51
0
   CPUID_PRINT(rdrand);
52
0
   CPUID_PRINT(rdseed);
53
0
   CPUID_PRINT(intel_sha);
54
0
#endif
55
0
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
0
#undef CPUID_PRINT
77
0
78
0
   return string_join(flags, ' ');
79
0
   }
80
81
//static
82
void CPUID::print(std::ostream& o)
83
0
   {
84
0
   o << "CPUID flags: " << CPUID::to_string() << "\n";
85
0
   }
86
87
//static
88
void CPUID::initialize()
89
0
   {
90
0
   state() = CPUID_Data();
91
0
   }
92
93
CPUID::CPUID_Data::CPUID_Data()
94
10
   {
95
10
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) || \
96
10
    defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY) || \
97
10
    defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
98
10
99
10
   m_cache_line_size = 0;
100
10
   m_processor_features = detect_cpu_features(&m_cache_line_size);
101
10
102
10
#endif
103
10
104
10
   m_processor_features |= CPUID::CPUID_INITIALIZED_BIT;
105
10
106
10
   if(m_cache_line_size == 0)
107
0
      m_cache_line_size = BOTAN_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE;
108
10
109
10
   m_endian_status = runtime_check_endian();
110
10
   }
111
112
//static
113
CPUID::Endian_Status CPUID::CPUID_Data::runtime_check_endian()
114
10
   {
115
10
   // Check runtime endian
116
10
   const uint32_t endian32 = 0x01234567;
117
10
   const uint8_t* e8 = reinterpret_cast<const uint8_t*>(&endian32);
118
10
119
10
   CPUID::Endian_Status endian = CPUID::Endian_Status::Unknown;
120
10
121
10
   if(e8[0] == 0x01 && e8[1] == 0x23 && e8[2] == 0x45 && e8[3] == 0x67)
122
0
      {
123
0
      endian = CPUID::Endian_Status::Big;
124
0
      }
125
10
   else if(e8[0] == 0x67 && e8[1] == 0x45 && e8[2] == 0x23 && e8[3] == 0x01)
126
10
      {
127
10
      endian = CPUID::Endian_Status::Little;
128
10
      }
129
0
   else
130
0
      {
131
0
      throw Internal_Error("Unexpected endian at runtime, neither big nor little");
132
0
      }
133
10
134
10
   // If we were compiled with a known endian, verify it matches at runtime
135
10
#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
136
10
   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
10
   return endian;
142
10
   }
143
144
std::vector<Botan::CPUID::CPUID_bits>
145
CPUID::bit_from_string(const std::string& tok)
146
0
   {
147
0
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
148
0
   if(tok == "sse2" || tok == "simd")
149
0
      return {Botan::CPUID::CPUID_SSE2_BIT};
150
0
   if(tok == "ssse3")
151
0
      return {Botan::CPUID::CPUID_SSSE3_BIT};
152
0
   if(tok == "aesni")
153
0
      return {Botan::CPUID::CPUID_AESNI_BIT};
154
0
   if(tok == "clmul")
155
0
      return {Botan::CPUID::CPUID_CLMUL_BIT};
156
0
   if(tok == "avx2")
157
0
      return {Botan::CPUID::CPUID_AVX2_BIT};
158
0
   if(tok == "sha")
159
0
      return {Botan::CPUID::CPUID_SHA_BIT};
160
0
   if(tok == "bmi2")
161
0
      return {Botan::CPUID::CPUID_BMI2_BIT};
162
0
   if(tok == "adx")
163
0
      return {Botan::CPUID::CPUID_ADX_BIT};
164
0
   if(tok == "intel_sha")
165
0
      return {Botan::CPUID::CPUID_SHA_BIT};
166
0
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
0
   return {};
198
0
   }
199
200
}