diff options
author | Werner Koch <wk@gnupg.org> | 2012-12-21 17:26:06 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2012-12-21 17:26:06 +0100 |
commit | 09ac5d87d11aa0b1fa0e0a4184ab03b3671a73e2 (patch) | |
tree | fdd126ae4b5c2fa2624edac0052619a70c207c1e /src/hwfeatures.c | |
parent | d842eea55e22c05da3959a7a4422b5fcd7884f60 (diff) | |
download | libgcrypt-09ac5d87d11aa0b1fa0e0a4184ab03b3671a73e2.tar.gz |
Prepare for hardware feature detection on other platforms.
* configure.ac (GCRYPT_HWF_MODULES): New.
(HAVE_CPU_ARCH_X86, HAVE_CPU_ARCH_ALPHA, HAVE_CPU_ARCH_SPARC)
(HAVE_CPU_ARCH_MIPS, HAVE_CPU_ARCH_M68K, HAVE_CPU_ARCH_PPC)
(HAVE_CPU_ARCH_ARM): New AC_DEFINEs.
* mpi/config.links (mpi_cpu_arch): New.
* src/global.c (print_config): Print new tag "cpu-arch".
* src/Makefile.am (libgcrypt_la_SOURCES): Add hwf-common.h
(EXTRA_libgcrypt_la_SOURCES): New.
(gcrypt_hwf_modules): New.
(libgcrypt_la_DEPENDENCIES, libgcrypt_la_LIBADD): Add that one.
* src/hwfeatures.c: Factor most code out to ...
* src/hwf-x86.c: New file.
(detect_x86_gnuc): Return the feature vector.
(_gcry_hwf_detect_x86): New.
* src/hwf-common.h: New.
* src/hwfeatures.c (_gcry_detect_hw_features): Dispatch using
HAVE_CPU_ARCH_ macros.
Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'src/hwfeatures.c')
-rw-r--r-- | src/hwfeatures.c | 188 |
1 files changed, 6 insertions, 182 deletions
diff --git a/src/hwfeatures.c b/src/hwfeatures.c index 62600aa9..87d05d83 100644 --- a/src/hwfeatures.c +++ b/src/hwfeatures.c @@ -1,5 +1,6 @@ /* hwfeatures.c - Detect hardware features. * Copyright (C) 2007, 2011 Free Software Foundation, Inc. + * Copyright (C) 2012 g10 Code GmbH * * This file is part of Libgcrypt. * @@ -25,6 +26,8 @@ #include <unistd.h> #include "g10lib.h" +#include "hwf-common.h" + /* A bit vector describing the hardware features currently available. */ @@ -40,185 +43,6 @@ _gcry_get_hw_features (void) } -#undef HAS_X86_CPUID - -#if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__) -#define HAS_X86_CPUID 1 - -static int -is_cpuid_available(void) -{ - int has_cpuid = 0; - - /* Detect the CPUID feature by testing some undefined behaviour (16 - vs 32 bit pushf/popf). */ - asm volatile - ("pushf\n\t" /* Copy flags to EAX. */ - "popl %%eax\n\t" - "movl %%eax, %%ecx\n\t" /* Save flags into ECX. */ - "xorl $0x200000, %%eax\n\t" /* Toggle ID bit and copy it to the flags. */ - "pushl %%eax\n\t" - "popf\n\t" - "pushf\n\t" /* Copy changed flags again to EAX. */ - "popl %%eax\n\t" - "pushl %%ecx\n\t" /* Restore flags from ECX. */ - "popf\n\t" - "xorl %%eax, %%ecx\n\t" /* Compare flags against saved flags. */ - "jz .Lno_cpuid%=\n\t" /* Toggling did not work, thus no CPUID. */ - "movl $1, %0\n" /* Worked. true -> HAS_CPUID. */ - ".Lno_cpuid%=:\n\t" - : "+r" (has_cpuid) - : - : "%eax", "%ecx", "cc" - ); - - return has_cpuid; -} - -static void -get_cpuid(unsigned int in, unsigned int *eax, unsigned int *ebx, - unsigned int *ecx, unsigned int *edx) -{ - unsigned int regs[4]; - - asm volatile - ("pushl %%ebx\n\t" /* Save GOT register. */ - "cpuid\n\t" - "movl %%ebx, %1\n\t" - "popl %%ebx\n\t" /* Restore GOT register. */ - : "=a" (regs[0]), "=r" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) - : "0" (in) - : "cc" - ); - - if (eax) - *eax = regs[0]; - if (ebx) - *ebx = regs[1]; - if (ecx) - *ecx = regs[2]; - if (edx) - *edx = regs[3]; -} -#endif /* i386 && GNUC */ - - -#if defined (__x86_64__) && defined (__GNUC__) -#define HAS_X86_CPUID 1 - -static int -is_cpuid_available(void) -{ - return 1; -} - -static void -get_cpuid(unsigned int in, unsigned int *eax, unsigned int *ebx, - unsigned int *ecx, unsigned int *edx) -{ - unsigned int regs[4]; - - asm volatile - ("cpuid\n\t" - : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) - : "0" (in) - : "cc" - ); - - if (eax) - *eax = regs[0]; - if (ebx) - *ebx = regs[1]; - if (ecx) - *ecx = regs[2]; - if (edx) - *edx = regs[3]; -} -#endif /* x86-64 && GNUC */ - - -#ifdef HAS_X86_CPUID -static void -detect_x86_gnuc (void) -{ - char vendor_id[12+1]; - unsigned int features; - - if (!is_cpuid_available()) - return; - - get_cpuid(0, NULL, - (unsigned int *)&vendor_id[0], - (unsigned int *)&vendor_id[8], - (unsigned int *)&vendor_id[4]); - vendor_id[12] = 0; - - if (0) - ; /* Just to make "else if" and ifdef macros look pretty. */ -#ifdef ENABLE_PADLOCK_SUPPORT - else if (!strcmp (vendor_id, "CentaurHauls")) - { - /* This is a VIA CPU. Check what PadLock features we have. */ - - /* Check for extended centaur (EAX). */ - get_cpuid(0xC0000000, &features, NULL, NULL, NULL); - - /* Has extended centaur features? */ - if (features > 0xC0000000) - { - /* Ask for the extended feature flags (EDX). */ - get_cpuid(0xC0000001, NULL, NULL, NULL, &features); - - /* Test bits 2 and 3 to see whether the RNG exists and is enabled. */ - if ((features & 0x0C) == 0x0C) - hw_features |= HWF_PADLOCK_RNG; - - /* Test bits 6 and 7 to see whether the ACE exists and is enabled. */ - if ((features & 0xC0) == 0xC0) - hw_features |= HWF_PADLOCK_AES; - - /* Test bits 10 and 11 to see whether the PHE exists and is - enabled. */ - if ((features & 0xC00) == 0xC00) - hw_features |= HWF_PADLOCK_SHA; - - /* Test bits 12 and 13 to see whether the MONTMUL exists and is - enabled. */ - if ((features & 0x3000) == 0x3000) - hw_features |= HWF_PADLOCK_MMUL; - } - } -#endif /*ENABLE_PADLOCK_SUPPORT*/ - else if (!strcmp (vendor_id, "GenuineIntel")) - { - /* This is an Intel CPU. */ - } - else if (!strcmp (vendor_id, "AuthenticAMD")) - { - /* This is an AMD CPU. */ - } - - /* Detect Intel features, that might also be supported by other - vendors. */ - - /* Get CPU info and Intel feature flags (ECX). */ - get_cpuid(1, NULL, NULL, &features, NULL); - -#ifdef ENABLE_AESNI_SUPPORT - /* Test bit 25 for AES-NI. */ - if (features & 0x02000000) - hw_features |= HWF_INTEL_AESNI; -#endif /*ENABLE_AESNI_SUPPORT*/ -#ifdef ENABLE_DRNG_SUPPORT - /* Test bit 30 for RDRAND. */ - if (features & 0x40000000) - hw_features |= HWF_INTEL_RDRAND; -#endif /*ENABLE_DRNG_SUPPORT*/ - -} -#endif /* HAS_X86_CPUID */ - - /* Detect the available hardware features. This function is called once right at startup and we assume that no other threads are running. */ @@ -230,11 +54,11 @@ _gcry_detect_hw_features (unsigned int disabled_features) if (fips_mode ()) return; /* Hardware support is not to be evaluated. */ -#if HAS_X86_CPUID +#if defined (HAVE_CPU_ARCH_X86) { - detect_x86_gnuc (); + hw_features = _gcry_hwf_detect_x86 (); } -#endif /* HAS_X86_CPUID */ +#endif /* HAVE_CPU_ARCH_X86 */ hw_features &= ~disabled_features; } |