aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils/cpuid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/cpuid.cpp')
-rw-r--r--src/utils/cpuid.cpp101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/utils/cpuid.cpp b/src/utils/cpuid.cpp
new file mode 100644
index 000000000..f79e3a912
--- /dev/null
+++ b/src/utils/cpuid.cpp
@@ -0,0 +1,101 @@
+/**
+* Runtime CPU detection
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/cpuid.h>
+#include <botan/types.h>
+#include <botan/loadstor.h>
+#include <botan/mem_ops.h>
+
+#if defined(BOTAN_TARGET_ARCH_IS_IA32) || defined(BOTAN_TARGET_ARCH_IS_AMD64)
+
+#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
+
+ #include <intrin.h>
+ #define CALL_CPUID(type, out) do { __cpuid((int*)out, type); } while(0)
+
+#elif defined(BOTAN_BUILD_COMPILER_IS_ICC)
+
+ #include <ia32intrin.h>
+ #define CALL_CPUID(type, out) do { __cpuid(out, type) } while(0);
+
+#elif defined(BOTAN_BUILD_COMPILER_IS_GCC)
+
+ #include <cpuid.h>
+ #define CALL_CPUID(type, out) \
+ do { __get_cpuid(type, out, out+1, out+2, out+3); } while(0);
+
+#endif
+
+#endif
+
+#ifndef CALL_CPUID
+ // In all other cases, just zeroize the supposed cpuid output
+ #define CALL_CPUID(type, out) \
+ do { out[0] = out[1] = out[2] = out[3] = 0; } while(0);
+#endif
+
+namespace Botan {
+
+namespace {
+
+u32bit get_x86_cache_line_size()
+ {
+ const u32bit INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 };
+ const u32bit AMD_CPUID[3] = { 0x68747541, 0x444D4163, 0x69746E65 };
+
+ u32bit cpuid[4] = { 0 };
+ CALL_CPUID(0, cpuid);
+
+ if(same_mem(cpuid + 1, INTEL_CPUID, 3))
+ {
+ CALL_CPUID(1, cpuid);
+ return 8 * get_byte(2, cpuid[1]);
+ }
+ else if(same_mem(cpuid + 1, AMD_CPUID, 3))
+ {
+ CALL_CPUID(0x80000005, cpuid);
+ return get_byte(3, cpuid[2]);
+ }
+ else
+ return 32; // default cache line guess
+ }
+
+}
+
+/*
+* Call the x86 CPUID instruction and return the contents of ecx and
+* edx, which contain the feature masks.
+*/
+u64bit CPUID::x86_processor_flags()
+ {
+ static u64bit proc_flags = 0;
+
+ if(proc_flags)
+ return proc_flags;
+
+ u32bit cpuid[4] = { 0 };
+ CALL_CPUID(1, cpuid);
+
+ // Set the FPU bit on to force caching in proc_flags
+ proc_flags = ((u64bit)cpuid[2] << 32) | cpuid[3] | 1;
+
+ return proc_flags;
+ }
+
+u32bit CPUID::cache_line_size()
+ {
+ static u32bit cl_size = 0;
+
+ if(cl_size)
+ return cl_size;
+
+ cl_size = get_x86_cache_line_size();
+
+ return cl_size;
+ }
+
+}