aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/utils/cpuid.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/utils/cpuid.h')
-rw-r--r--src/lib/utils/cpuid.h114
1 files changed, 68 insertions, 46 deletions
diff --git a/src/lib/utils/cpuid.h b/src/lib/utils/cpuid.h
index 3781b6f8e..4e276fabe 100644
--- a/src/lib/utils/cpuid.h
+++ b/src/lib/utils/cpuid.h
@@ -15,6 +15,8 @@ namespace Botan {
/**
* A class handling runtime CPU feature detection
+*
+* Currently this class supports only x86 (via CPUID) and PowerPC (AltiVec detection)
*/
class BOTAN_DLL CPUID
{
@@ -24,6 +26,10 @@ class BOTAN_DLL CPUID
*/
static void initialize();
+ static bool has_simd_32();
+
+ static void print(std::ostream& o);
+
/**
* Return a best guess of the cache line size
*/
@@ -36,136 +42,152 @@ class BOTAN_DLL CPUID
return g_cache_line_size;
}
+ enum CPUID_bits {
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
+ // This matches the layout of cpuid(1)
+ CPUID_RDTSC_BIT = 4,
+ CPUID_SSE2_BIT = 26,
+ CPUID_CLMUL_BIT = 33,
+ CPUID_SSSE3_BIT = 41,
+ CPUID_SSE41_BIT = 51,
+ CPUID_SSE42_BIT = 52,
+ CPUID_AESNI_BIT = 57,
+ CPUID_RDRAND_BIT = 62,
+
+ CPUID_AVX2_BIT = 64+5,
+ CPUID_BMI2_BIT = 64+8,
+ CPUID_AVX512F_BIT = 64+16,
+ CPUID_RDSEED_BIT = 64+18,
+ CPUID_ADX_BIT = 64+19,
+ CPUID_SHA_BIT = 64+29,
+#endif
+
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
+ CPUID_ALTIVEC_BIT = 0
+#endif
+
+ // TODO: ARMv8 feature detection
+ };
+
+#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
/**
* Check if the processor supports AltiVec/VMX
*/
static bool has_altivec()
- {
- if(!g_initialized)
- {
- initialize();
- }
+ { return has_cpuid_bit(CPUID_ALTIVEC_BIT); }
+#endif
- return g_altivec_capable;
- }
+#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
/**
* Check if the processor supports RDTSC
*/
static bool has_rdtsc()
- { return x86_processor_flags_has(CPUID_RDTSC_BIT); }
+ { return has_cpuid_bit(CPUID_RDTSC_BIT); }
/**
* Check if the processor supports SSE2
*/
static bool has_sse2()
- { return x86_processor_flags_has(CPUID_SSE2_BIT); }
+ { return has_cpuid_bit(CPUID_SSE2_BIT); }
/**
* Check if the processor supports SSSE3
*/
static bool has_ssse3()
- { return x86_processor_flags_has(CPUID_SSSE3_BIT); }
+ { return has_cpuid_bit(CPUID_SSSE3_BIT); }
/**
* Check if the processor supports SSE4.1
*/
static bool has_sse41()
- { return x86_processor_flags_has(CPUID_SSE41_BIT); }
+ { return has_cpuid_bit(CPUID_SSE41_BIT); }
/**
* Check if the processor supports SSE4.2
*/
static bool has_sse42()
- { return x86_processor_flags_has(CPUID_SSE42_BIT); }
+ { return has_cpuid_bit(CPUID_SSE42_BIT); }
/**
* Check if the processor supports AVX2
*/
static bool has_avx2()
- { return x86_processor_flags_has(CPUID_AVX2_BIT); }
+ { return has_cpuid_bit(CPUID_AVX2_BIT); }
/**
* Check if the processor supports AVX-512F
*/
static bool has_avx512f()
- { return x86_processor_flags_has(CPUID_AVX512F_BIT); }
+ { return has_cpuid_bit(CPUID_AVX512F_BIT); }
/**
* Check if the processor supports BMI2
*/
static bool has_bmi2()
- { return x86_processor_flags_has(CPUID_BMI2_BIT); }
+ { return has_cpuid_bit(CPUID_BMI2_BIT); }
/**
* Check if the processor supports AES-NI
*/
static bool has_aes_ni()
- { return x86_processor_flags_has(CPUID_AESNI_BIT); }
+ { return has_cpuid_bit(CPUID_AESNI_BIT); }
/**
* Check if the processor supports CLMUL
*/
static bool has_clmul()
- { return x86_processor_flags_has(CPUID_CLMUL_BIT); }
+ { return has_cpuid_bit(CPUID_CLMUL_BIT); }
/**
* Check if the processor supports Intel SHA extension
*/
static bool has_intel_sha()
- { return x86_processor_flags_has(CPUID_SHA_BIT); }
+ { return has_cpuid_bit(CPUID_SHA_BIT); }
/**
* Check if the processor supports ADX extension
*/
static bool has_adx()
- { return x86_processor_flags_has(CPUID_ADX_BIT); }
+ { return has_cpuid_bit(CPUID_ADX_BIT); }
/**
* Check if the processor supports RDRAND
*/
static bool has_rdrand()
- { return x86_processor_flags_has(CPUID_RDRAND_BIT); }
+ { return has_cpuid_bit(CPUID_RDRAND_BIT); }
/**
* Check if the processor supports RDSEED
*/
static bool has_rdseed()
- { return x86_processor_flags_has(CPUID_RDSEED_BIT); }
-
- static bool has_simd_32();
-
- static void print(std::ostream& o);
- private:
- enum CPUID_bits {
- CPUID_RDTSC_BIT = 4,
- CPUID_SSE2_BIT = 26,
- CPUID_CLMUL_BIT = 33,
- CPUID_SSSE3_BIT = 41,
- CPUID_SSE41_BIT = 51,
- CPUID_SSE42_BIT = 52,
- CPUID_AESNI_BIT = 57,
- CPUID_RDRAND_BIT = 62,
+ { return has_cpuid_bit(CPUID_RDSEED_BIT); }
+#endif
- CPUID_AVX2_BIT = 64+5,
- CPUID_BMI2_BIT = 64+8,
- CPUID_AVX512F_BIT = 64+16,
- CPUID_RDSEED_BIT = 64+18,
- CPUID_ADX_BIT = 64+19,
- CPUID_SHA_BIT = 64+29,
- };
+ /*
+ * Clear a CPUID bit
+ * Call CPUID::initialize to reset
+ */
+ static void clear_cpuid_bit(CPUID_bits bit)
+ {
+ BOTAN_ASSERT(bit < 128, "CPUID bit within bounds");
+ const uint64_t mask = ~(static_cast<uint64_t>(1) << (bit % 64));
+ g_processor_flags[bit/64] &= mask;
+ }
- static bool x86_processor_flags_has(u64bit bit)
+ static bool has_cpuid_bit(CPUID_bits elem)
{
if(!g_initialized)
initialize();
- return ((g_x86_processor_flags[bit/64] >> (bit % 64)) & 1);
+ const size_t bit = static_cast<size_t>(elem);
+ BOTAN_ASSERT(bit < 128, "CPUID bit within bounds");
+ return ((g_processor_flags[bit/64] >> (bit % 64)) & 1);
}
+ private:
static bool g_initialized;
- static u64bit g_x86_processor_flags[2];
static size_t g_cache_line_size;
- static bool g_altivec_capable;
+ static u64bit g_processor_flags[2];
};
}