diff options
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/asm_amd64/info.txt | 2 | ||||
-rw-r--r-- | src/utils/asm_ia32/info.txt | 2 | ||||
-rw-r--r-- | src/utils/bswap.h | 33 | ||||
-rw-r--r-- | src/utils/cpuid.cpp | 47 | ||||
-rw-r--r-- | src/utils/cpuid.h | 47 | ||||
-rw-r--r-- | src/utils/dyn_load/dyn_load.cpp | 60 | ||||
-rw-r--r-- | src/utils/dyn_load/dyn_load.h | 56 | ||||
-rw-r--r-- | src/utils/dyn_load/info.txt | 22 |
8 files changed, 212 insertions, 57 deletions
diff --git a/src/utils/asm_amd64/info.txt b/src/utils/asm_amd64/info.txt index 93405e6ce..ac2d73958 100644 --- a/src/utils/asm_amd64/info.txt +++ b/src/utils/asm_amd64/info.txt @@ -14,5 +14,5 @@ icc </cc> <requires> -amd64_eng +asm_engine </requires> diff --git a/src/utils/asm_ia32/info.txt b/src/utils/asm_ia32/info.txt index d490124f4..094d02a75 100644 --- a/src/utils/asm_ia32/info.txt +++ b/src/utils/asm_ia32/info.txt @@ -14,5 +14,5 @@ icc </cc> <requires> -ia32_eng +asm_engine </requires> diff --git a/src/utils/bswap.h b/src/utils/bswap.h index 49962f076..b35dbf123 100644 --- a/src/utils/bswap.h +++ b/src/utils/bswap.h @@ -18,37 +18,56 @@ namespace Botan { -/* -* Byte Swapping Functions +/** +* Swap a 16 bit integer */ inline u16bit reverse_bytes(u16bit input) { return rotate_left(input, 8); } +/** +* Swap a 32 bit integer +*/ inline u32bit reverse_bytes(u32bit input) { -#if BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) +#if BOTAN_GCC_VERSION >= 430 + + // GCC intrinsic added in 4.3, works for a number of CPUs + return __builtin_bswap32(input); + +#elif BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) // GCC-style inline assembly for x86 or x86-64 asm("bswapl %0" : "=r" (input) : "0" (input)); return input; #elif defined(_MSC_VER) && defined(BOTAN_TARGET_ARCH_IS_IA32) + // Visual C++ inline asm for 32-bit x86, by Yves Jerschow __asm mov eax, input; __asm bswap eax; #else + // Generic implementation return (rotate_right(input, 8) & 0xFF00FF00) | (rotate_left (input, 8) & 0x00FF00FF); + #endif } +/** +* Swap a 64 bit integer +*/ inline u64bit reverse_bytes(u64bit input) { -#if BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_ARCH_IS_AMD64) +#if BOTAN_GCC_VERSION >= 430 + + // GCC intrinsic added in 4.3, works for a number of CPUs + return __builtin_bswap64(input); + +#elif BOTAN_USE_GCC_INLINE_ASM && defined(BOTAN_TARGET_ARCH_IS_AMD64) // GCC-style inline assembly for x86-64 asm("bswapq %0" : "=r" (input) : "0" (input)); return input; @@ -69,6 +88,9 @@ inline u64bit reverse_bytes(u64bit input) #endif } +/** +* Swap 4 Ts in an array +*/ template<typename T> inline void bswap_4(T x[4]) { @@ -80,6 +102,9 @@ inline void bswap_4(T x[4]) #if defined(BOTAN_TARGET_CPU_HAS_SSE2) +/** +* Swap 4 u32bits in an array using SSE2 shuffle instructions +*/ template<> inline void bswap_4(u32bit x[4]) { diff --git a/src/utils/cpuid.cpp b/src/utils/cpuid.cpp index 4837e7ac4..b76210865 100644 --- a/src/utils/cpuid.cpp +++ b/src/utils/cpuid.cpp @@ -1,6 +1,6 @@ /* * Runtime CPU detection -* (C) 2009 Jack Lloyd +* (C) 2009-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -47,6 +47,10 @@ namespace Botan { +u64bit CPUID::x86_processor_flags = 0; +u32bit CPUID::cache_line = 32; +bool CPUID::altivec_capable = false; + namespace { u32bit get_x86_cache_line_size() @@ -140,54 +144,21 @@ bool altivec_check_pvr_emul() } -/* -* Call the x86 CPUID instruction and return the contents of ecx and -* edx, which contain the feature masks. -*/ -u64bit CPUID::x86_processor_flags() +void CPUID::initialize() { - 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; + x86_processor_flags = ((u64bit)cpuid[2] << 32) | cpuid[3]; - cl_size = get_x86_cache_line_size(); + cache_line = get_x86_cache_line_size(); - return cl_size; - } + altivec_capable = false; -bool CPUID::has_altivec() - { - static bool first_time = true; - static bool altivec_capable = false; - - if(first_time) - { #if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) if(altivec_check_sysctl() || altivec_check_pvr_emul()) altivec_capable = true; #endif - - first_time = false; - } - - return altivec_capable; } } diff --git a/src/utils/cpuid.h b/src/utils/cpuid.h index a6a278a6e..6cb4092bb 100644 --- a/src/utils/cpuid.h +++ b/src/utils/cpuid.h @@ -1,6 +1,6 @@ /* * Runtime CPU detection -* (C) 2009 Jack Lloyd +* (C) 2009-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -19,9 +19,14 @@ class BOTAN_DLL CPUID { public: /** + * Probe the CPU and see what extensions are supported + */ + static void initialize(); + + /** * Return a best guess of the cache line size */ - static u32bit cache_line_size(); + static u32bit cache_line_size() { return cache_line; } /** * Check if the processor supports RDTSC @@ -60,32 +65,48 @@ class BOTAN_DLL CPUID { return x86_processor_flags_has(CPUID_AVX_BIT); } /** - * Check if the processor supports Intel's AES instructions + * Check if the processor supports AES-NI + */ + static bool has_aes_ni() + { return x86_processor_flags_has(CPUID_AESNI_BIT); } + + /** + * Check if the processor supports PCMULUDQ + */ + static bool has_pcmuludq() + { return x86_processor_flags_has(CPUID_PCMUL_BIT); } + + /** + * Check if the processor supports MOVBE */ - static bool has_aes_intel() - { return x86_processor_flags_has(CPUID_INTEL_AES_BIT); } + static bool has_movbe() + { return x86_processor_flags_has(CPUID_MOVBE_BIT); } /** * Check if the processor supports AltiVec/VMX */ - static bool has_altivec(); + static bool has_altivec() { return altivec_capable; } private: - static bool x86_processor_flags_has(u64bit bit) - { - return ((x86_processor_flags() >> bit) & 1); - } - enum CPUID_bits { CPUID_RDTSC_BIT = 4, CPUID_SSE2_BIT = 26, + CPUID_PCMUL_BIT = 33, CPUID_SSSE3_BIT = 41, CPUID_SSE41_BIT = 51, CPUID_SSE42_BIT = 52, - CPUID_INTEL_AES_BIT = 57, + CPUID_MOVBE_BIT = 54, + CPUID_AESNI_BIT = 57, CPUID_AVX_BIT = 60 }; - static u64bit x86_processor_flags(); + static bool x86_processor_flags_has(u64bit bit) + { + return ((x86_processor_flags >> bit) & 1); + } + + static u64bit x86_processor_flags; + static u32bit cache_line; + static bool altivec_capable; }; } diff --git a/src/utils/dyn_load/dyn_load.cpp b/src/utils/dyn_load/dyn_load.cpp new file mode 100644 index 000000000..6d359bc01 --- /dev/null +++ b/src/utils/dyn_load/dyn_load.cpp @@ -0,0 +1,60 @@ +/** +* Dynamically Loaded Object +* (C) 2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/internal/dyn_load.h> +#include <botan/build.h> +#include <stdexcept> + +#if defined(BOTAN_TARGET_OS_HAS_DLOPEN) + #include <dlfcn.h> +#endif + +namespace Botan { + +Dynamically_Loaded_Library::Dynamically_Loaded_Library( + const std::string& library) : + lib_name(library), lib(0) + { +#if defined(BOTAN_TARGET_OS_HAS_DLOPEN) + lib = ::dlopen(lib_name.c_str(), RTLD_LAZY); + + if(!lib) + { + const char* dl_err = dlerror(); + if(!dl_err) + dl_err = "Unknown error"; + + throw std::runtime_error("Failed to load engine " + lib_name + ": " + + dl_err); + } +#endif + + } + +Dynamically_Loaded_Library::~Dynamically_Loaded_Library() + { +#if defined(BOTAN_TARGET_OS_HAS_DLOPEN) + ::dlclose(lib); +#endif + } + +void* Dynamically_Loaded_Library::resolve_symbol(const std::string& symbol) + { + void* addr = 0; + +#if defined(BOTAN_TARGET_OS_HAS_DLOPEN) + addr = ::dlsym(lib, symbol.c_str()); +#endif + + if(!addr) + throw std::runtime_error("Failed to resolve symbol " + symbol + + " in " + lib_name); + + return addr; + } + +} diff --git a/src/utils/dyn_load/dyn_load.h b/src/utils/dyn_load/dyn_load.h new file mode 100644 index 000000000..d5476b389 --- /dev/null +++ b/src/utils/dyn_load/dyn_load.h @@ -0,0 +1,56 @@ +/** +* Dynamically Loaded Object +* (C) 2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_DYNAMIC_LOADER_H__ +#define BOTAN_DYNAMIC_LOADER_H__ + +#include <string> + +namespace Botan { + +class Dynamically_Loaded_Library + { + public: + /** + * Load a DLL (or fail with an exception) + * @param lib_name name or path to a library + */ + Dynamically_Loaded_Library(const std::string& lib_name); + + /** + * Unload the DLL + * @warning Any pointers returned by resolve()/resolve_symbol() + * should not be used after this destructor runs. + */ + ~Dynamically_Loaded_Library(); + + /** + * Load a symbol (or fail with an exception) + * @param symbol names the symbol to load + * @return address of the loaded symbol + */ + void* resolve_symbol(const std::string& symbol); + + /** + * Convenience function for casting symbol to the right type + * @param symbol names the symbol to load + * @return address of the loaded symbol + */ + template<typename T> + T resolve(const std::string& symbol) + { + return reinterpret_cast<T>(resolve_symbol(symbol)); + } + + private: + std::string lib_name; + void* lib; + }; + +} + +#endif diff --git a/src/utils/dyn_load/info.txt b/src/utils/dyn_load/info.txt new file mode 100644 index 000000000..07a1067bc --- /dev/null +++ b/src/utils/dyn_load/info.txt @@ -0,0 +1,22 @@ +define DYNAMIC_LOADER + +<os> +linux +freebsd +openbsd +netbsd +solaris +</os> + +<libs> +linux -> dl +solaris -> dl +</libs> + +<source> +dyn_load.cpp +</source> + +<header:internal> +dyn_load.h +</header:internal> |