diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/utils/cpuid.cpp | 118 | ||||
-rw-r--r-- | src/utils/cpuid.h | 68 |
2 files changed, 99 insertions, 87 deletions
diff --git a/src/utils/cpuid.cpp b/src/utils/cpuid.cpp index d5149e2e5..6326e84ad 100644 --- a/src/utils/cpuid.cpp +++ b/src/utils/cpuid.cpp @@ -7,6 +7,10 @@ #include <botan/cpuid.h> #include <botan/types.h> +#include <botan/loadstor.h> +#include <botan/mem_ops.h> + +#include <stdio.h> #if defined(_MSC_VER) #include <intrin.h> @@ -14,95 +18,87 @@ namespace Botan { -namespace CPUID { - namespace { -/* -* Call the x86 CPUID instruction and return the contents of ecx and -* edx, which contain the feature masks. -*/ -u64bit x86_processor_flags() +void x86_cpuid(u32bit type, u32bit out[4]) { - static u64bit proc_flags = 0; - - if(proc_flags) - return proc_flags; - -#if defined(BOTAN_TARGET_ARCH_IS_X86) || defined(BOTAN_TARGET_ARCH_IS_AMD64) + out[0] = out[1] = out[2] = out[3] = 0; #if defined(BOTAN_BUILD_COMPILER_IS_GCC) - u32bit a = 1, b = 0, c = 0, d = 0; +#if defined(BOTAN_TARGET_ARCH_IS_X86) -#if defined(__i386__) && defined(__PIC__) - // ebx is reserved for PIC on 32-bit x86, so save and restore it - asm("xchgl %%ebx, %1\n\t" - "cpuid\n\t" - "xchgl %%ebx, %1\n\t" - : "=a" (a), "=r" (b), "=c" (c), "=d" (d) : "0" (a)); -#else - // if not PIC or in 64-bit mode, can smash ebx - asm("cpuid" : "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "0" (a)); + asm("pushq %%ebx; cpuid; mov %%ebx, %%edi; popq %%ebx" + : "=a" (out[0]), "=D" (out[1]), "=c" (out[2]), "=d" (out[3]) + : "0" (type)); -#endif +#elif defined(BOTAN_TARGET_ARCH_IS_AMD64) - proc_flags = ((u64bit)c << 32) | d; + asm("pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx" + : "=a" (out[0]), "=D" (out[1]), "=c" (out[2]), "=d" (out[3]) + : "0" (type)); +#endif #elif defined(BOTAN_BUILD_COMPILER_IS_MSVC) + __cpuid(out, type); +#endif + } - int cpuinfo[4] = { 0 }; - __cpuid(cpuinfo, 1); +u32bit get_x86_cache_line_size() + { + const u32bit INTEL_CPUID[3] = { 0x756E6547, 0x6C65746E, 0x49656E69 }; + const u32bit AMD_CPUID[3] = { 0, 0, 0 }; - proc_flags = ((u64bit)cpuinfo[2] << 32) | cpuinfo[3]; + u32bit cpuid[4] = { 0 }; + x86_cpuid(0, cpuid); -#endif + if(same_mem(cpuid + 1, INTEL_CPUID, 3) && cpuid[0] > 2) + { + x86_cpuid(1, cpuid); + return 8 * get_byte(2, cpuid[1]); + } -#endif + if(same_mem(cpuid + 1, AMD_CPUID, 3)) + { + x86_cpuid(0x80000005, cpuid); + return get_byte(3, cpuid[2]); + } - return proc_flags; + return 32; // default cache line guess } -enum CPUID_bits { - CPUID_RDTSC_BIT = 4, - CPUID_SSE2_BIT = 26, - CPUID_SSSE3_BIT = 41, - CPUID_SSE41_BIT = 51, - CPUID_SSE42_BIT = 52 -}; - } -u32bit cache_line_size() +/* +* Call the x86 CPUID instruction and return the contents of ecx and +* edx, which contain the feature masks. +*/ +u64bit CPUID::x86_processor_flags() { - return 32; // FIXME! - } + static u64bit proc_flags = 0; -bool has_rdtsc() - { - return ((x86_processor_flags() >> CPUID_RDTSC_BIT) & 1); - } + if(proc_flags) + return proc_flags; -bool has_sse2() - { - return ((x86_processor_flags() >> CPUID_SSE2_BIT) & 1); - } + u32bit cpuid[4] = { 0 }; + x86_cpuid(1, cpuid); -bool has_ssse3() - { - return ((x86_processor_flags() >> CPUID_SSSE3_BIT) & 1); - } + // Set the FPU bit on to force caching in proc_flags + proc_flags = ((u64bit)cpuid[2] << 32) | cpuid[3] | 1; -bool has_sse41() - { - return ((x86_processor_flags() >> CPUID_SSE41_BIT) & 1); + return proc_flags; } -bool has_sse42() +u32bit CPUID::cache_line_size() { - return ((x86_processor_flags() >> CPUID_SSE42_BIT) & 1); - } + static u32bit cl_size = 0; -} + if(cl_size) + return cl_size; + + cl_size = get_x86_cache_line_size(); + + return cl_size; + } } diff --git a/src/utils/cpuid.h b/src/utils/cpuid.h index 557590db8..5f21e2310 100644 --- a/src/utils/cpuid.h +++ b/src/utils/cpuid.h @@ -12,39 +12,55 @@ namespace Botan { -namespace CPUID { +class CPUID + { + public: + enum CPUID_bits { + CPUID_RDTSC_BIT = 4, + CPUID_SSE2_BIT = 26, + CPUID_SSSE3_BIT = 41, + CPUID_SSE41_BIT = 51, + CPUID_SSE42_BIT = 52 + }; -/** -* Return a best guess of the cache line size -*/ -u32bit cache_line_size(); + /** + * Return a best guess of the cache line size + */ + static u32bit cache_line_size(); -/** -* Check if the processor supports RDTSC -*/ -bool has_rdtsc(); + /** + * Check if the processor supports RDTSC + */ + static bool has_rdtsc() + { return ((x86_processor_flags() >> CPUID_RDTSC_BIT) & 1); } -/** -* Check if the processor supports SSE2 -*/ -bool has_sse2(); + /** + * Check if the processor supports SSE2 + */ + static bool has_sse2() + { return ((x86_processor_flags() >> CPUID_SSE2_BIT) & 1); } -/** -* Check if the processor supports SSSE3 -*/ -bool has_ssse3(); + /** + * Check if the processor supports SSSE3 + */ + static bool has_ssse3() + { return ((x86_processor_flags() >> CPUID_SSSE3_BIT) & 1); } -/** -* Check if the processor supports SSE4.1 -*/ -bool has_sse41(); + /** + * Check if the processor supports SSE4.1 + */ + static bool has_sse41() + { return ((x86_processor_flags() >> CPUID_SSE41_BIT) & 1); } -/** -* Check if the processor supports SSE4.2 -*/ -bool has_sse42(); + /** + * Check if the processor supports SSE4.2 + */ + static bool has_sse42() + { return ((x86_processor_flags() >> CPUID_SSE42_BIT) & 1); } -} + private: + static u64bit x86_processor_flags(); + }; } |