/usr/include/botan-2/botan/cpuid.h is in libbotan-2-dev 2.4.0-5ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | /*
* Runtime CPU detection
* (C) 2009,2010,2013,2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
#ifndef BOTAN_CPUID_H_
#define BOTAN_CPUID_H_
#include <botan/types.h>
#include <vector>
#include <string>
#include <iosfwd>
namespace Botan {
/**
* A class handling runtime CPU feature detection. It is limited to
* just the features necessary to implement CPU specific code in Botan,
* rather than being a general purpose utility.
*
* This class supports:
*
* - x86 features using CPUID. x86 is also the only processor with
* accurate cache line detection currently.
*
* - PowerPC AltiVec detection on Linux, NetBSD, OpenBSD, and Darwin
*
* - ARM NEON and crypto extensions detection. On Linux and Android
* systems which support getauxval, that is used to access CPU
* feature information. Otherwise a relatively portable but
* thread-unsafe mechanism involving executing probe functions which
* catching SIGILL signal is used.
*/
class BOTAN_PUBLIC_API(2,1) CPUID final
{
public:
/**
* Probe the CPU and see what extensions are supported
*/
static void initialize();
static bool has_simd_32();
/**
* Deprecated equivalent to
* o << "CPUID flags: " << CPUID::to_string() << "\n";
*/
BOTAN_DEPRECATED("Use CPUID::to_string")
static void print(std::ostream& o);
/**
* Return a possibly empty string containing list of known CPU
* extensions. Each name will be seperated by a space, and the ordering
* will be arbitrary. This list only contains values that are useful to
* Botan (for example FMA instructions are not checked).
*
* Example outputs "sse2 ssse3 rdtsc", "neon arm_aes", "altivec"
*/
static std::string to_string();
/**
* Return a best guess of the cache line size
*/
static size_t cache_line_size()
{
if(g_processor_features == 0)
{
initialize();
}
return g_cache_line_size;
}
static bool is_little_endian()
{
return endian_status() == ENDIAN_LITTLE;
}
static bool is_big_endian()
{
return endian_status() == ENDIAN_BIG;
}
enum CPUID_bits : uint64_t {
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
// These values have no relation to cpuid bitfields
// SIMD instruction sets
CPUID_SSE2_BIT = (1ULL << 0),
CPUID_SSSE3_BIT = (1ULL << 1),
CPUID_SSE41_BIT = (1ULL << 2),
CPUID_SSE42_BIT = (1ULL << 3),
CPUID_AVX2_BIT = (1ULL << 4),
CPUID_AVX512F_BIT = (1ULL << 5),
// Misc useful instructions
CPUID_RDTSC_BIT = (1ULL << 10),
CPUID_BMI2_BIT = (1ULL << 11),
CPUID_ADX_BIT = (1ULL << 12),
// Crypto-specific ISAs
CPUID_AESNI_BIT = (1ULL << 16),
CPUID_CLMUL_BIT = (1ULL << 17),
CPUID_RDRAND_BIT = (1ULL << 18),
CPUID_RDSEED_BIT = (1ULL << 19),
CPUID_SHA_BIT = (1ULL << 20),
#endif
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
CPUID_ALTIVEC_BIT = (1ULL << 0),
#endif
#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
CPUID_ARM_NEON_BIT = (1ULL << 0),
CPUID_ARM_AES_BIT = (1ULL << 16),
CPUID_ARM_PMULL_BIT = (1ULL << 17),
CPUID_ARM_SHA1_BIT = (1ULL << 18),
CPUID_ARM_SHA2_BIT = (1ULL << 19),
#endif
CPUID_INITIALIZED_BIT = (1ULL << 63)
};
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
/**
* Check if the processor supports AltiVec/VMX
*/
static bool has_altivec()
{ return has_cpuid_bit(CPUID_ALTIVEC_BIT); }
#endif
#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
/**
* Check if the processor supports NEON SIMD
*/
static bool has_neon()
{ return has_cpuid_bit(CPUID_ARM_NEON_BIT); }
/**
* Check if the processor supports ARMv8 SHA1
*/
static bool has_arm_sha1()
{ return has_cpuid_bit(CPUID_ARM_SHA1_BIT); }
/**
* Check if the processor supports ARMv8 SHA2
*/
static bool has_arm_sha2()
{ return has_cpuid_bit(CPUID_ARM_SHA2_BIT); }
/**
* Check if the processor supports ARMv8 AES
*/
static bool has_arm_aes()
{ return has_cpuid_bit(CPUID_ARM_AES_BIT); }
/**
* Check if the processor supports ARMv8 PMULL
*/
static bool has_arm_pmull()
{ return has_cpuid_bit(CPUID_ARM_PMULL_BIT); }
#endif
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
/**
* Check if the processor supports RDTSC
*/
static bool has_rdtsc()
{ return has_cpuid_bit(CPUID_RDTSC_BIT); }
/**
* Check if the processor supports SSE2
*/
static bool has_sse2()
{ return has_cpuid_bit(CPUID_SSE2_BIT); }
/**
* Check if the processor supports SSSE3
*/
static bool has_ssse3()
{ return has_cpuid_bit(CPUID_SSSE3_BIT); }
/**
* Check if the processor supports SSE4.1
*/
static bool has_sse41()
{ return has_cpuid_bit(CPUID_SSE41_BIT); }
/**
* Check if the processor supports SSE4.2
*/
static bool has_sse42()
{ return has_cpuid_bit(CPUID_SSE42_BIT); }
/**
* Check if the processor supports AVX2
*/
static bool has_avx2()
{ return has_cpuid_bit(CPUID_AVX2_BIT); }
/**
* Check if the processor supports AVX-512F
*/
static bool has_avx512f()
{ return has_cpuid_bit(CPUID_AVX512F_BIT); }
/**
* Check if the processor supports BMI2
*/
static bool has_bmi2()
{ return has_cpuid_bit(CPUID_BMI2_BIT); }
/**
* Check if the processor supports AES-NI
*/
static bool has_aes_ni()
{ return has_cpuid_bit(CPUID_AESNI_BIT); }
/**
* Check if the processor supports CLMUL
*/
static bool has_clmul()
{ return has_cpuid_bit(CPUID_CLMUL_BIT); }
/**
* Check if the processor supports Intel SHA extension
*/
static bool has_intel_sha()
{ return has_cpuid_bit(CPUID_SHA_BIT); }
/**
* Check if the processor supports ADX extension
*/
static bool has_adx()
{ return has_cpuid_bit(CPUID_ADX_BIT); }
/**
* Check if the processor supports RDRAND
*/
static bool has_rdrand()
{ return has_cpuid_bit(CPUID_RDRAND_BIT); }
/**
* Check if the processor supports RDSEED
*/
static bool has_rdseed()
{ return has_cpuid_bit(CPUID_RDSEED_BIT); }
#endif
/*
* Clear a CPUID bit
* Call CPUID::initialize to reset
*
* This is only exposed for testing, don't use unless you know
* what you are doing.
*/
static void clear_cpuid_bit(CPUID_bits bit)
{
const uint64_t mask = ~(static_cast<uint64_t>(bit));
g_processor_features &= mask;
}
/*
* Don't call this function, use CPUID::has_xxx above
* It is only exposed for the tests.
*/
static bool has_cpuid_bit(CPUID_bits elem)
{
if(g_processor_features == 0)
initialize();
return ((g_processor_features & static_cast<uint64_t>(elem)) != 0);
}
static std::vector<CPUID::CPUID_bits> bit_from_string(const std::string& tok);
private:
enum Endian_status : uint32_t {
ENDIAN_UNKNOWN = 0x00000000,
ENDIAN_BIG = 0x01234567,
ENDIAN_LITTLE = 0x67452301,
};
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) || \
defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY) || \
defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
static uint64_t detect_cpu_features(size_t* cache_line_size);
#endif
static Endian_status runtime_check_endian();
static Endian_status endian_status()
{
if(g_endian_status == ENDIAN_UNKNOWN)
{
g_endian_status = runtime_check_endian();
}
return g_endian_status;
}
static uint64_t g_processor_features;
static size_t g_cache_line_size;
static Endian_status g_endian_status;
};
}
#endif
|