summaryrefslogtreecommitdiff
path: root/src/hwfeatures.c
diff options
context:
space:
mode:
authorRafaël Carré <funman@videolan.org>2012-04-20 13:52:01 -0400
committerWerner Koch <wk@gnupg.org>2012-06-21 10:36:05 +0200
commitbaf0dc7e9c26167ab43ba2adebcf2f1abc9d9b3b (patch)
treee431af69640ffa9808127347bfc717ffb48dae2b /src/hwfeatures.c
parent39c123b729a472ace039f8536d07f8b9a5f4675a (diff)
downloadlibgcrypt-baf0dc7e9c26167ab43ba2adebcf2f1abc9d9b3b.tar.gz
Enable VIA Padlock on x86_64 platforms
* cipher/rijndael.c: Duplicate x86 assembly and convert to x86_64. * random/rndhw.c: Likewise. * src/hwfeatures.c: Likewise. -- Changes made to the x86 assembly: - *l -> *q (long -> quad) - e** registers -> r** registers (use widest registers available) - don't mess with ebx GOT register Tested with make check on VIA Nano X2 L4350 Signed-off-by: Rafaël Carré <funman@videolan.org>
Diffstat (limited to 'src/hwfeatures.c')
-rw-r--r--src/hwfeatures.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/hwfeatures.c b/src/hwfeatures.c
index c3567989..73db917f 100644
--- a/src/hwfeatures.c
+++ b/src/hwfeatures.c
@@ -40,6 +40,99 @@ _gcry_get_hw_features (void)
}
+#if defined (__x86_64__) && defined (__GNUC__)
+static void
+detect_x86_64_gnuc (void)
+{
+ /* The code here is only useful for the PadLock engine thus we don't
+ build it if that support has been disabled. */
+ char vendor_id[12+1];
+
+ asm volatile
+ ("xorl %%eax, %%eax\n\t" /* 0 -> EAX. */
+ "cpuid\n\t" /* Get vendor ID. */
+ "movl %%ebx, (%0)\n\t" /* EBX,EDX,ECX -> VENDOR_ID. */
+ "movl %%edx, 4(%0)\n\t"
+ "movl %%ecx, 8(%0)\n\t"
+ :
+ : "S" (&vendor_id[0])
+ : "%eax", "%ecx", "%edx", "cc"
+ );
+ 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. */
+ asm volatile
+ ("movl $0xC0000000, %%eax\n\t" /* Check for extended centaur */
+ "cpuid\n\t" /* feature flags. */
+ "cmpl $0xC0000001, %%eax\n\t"
+ "jb .Lready%=\n\t" /* EAX < 0xC0000000 => no padlock. */
+
+ "movl $0xC0000001, %%eax\n\t" /* Ask for the extended */
+ "cpuid\n\t" /* feature flags. */
+
+ "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */
+ "andl $0x0C, %%eax\n\t" /* Test bits 2 and 3 to see whether */
+ "cmpl $0x0C, %%eax\n\t" /* the RNG exists and is enabled. */
+ "jnz .Lno_rng%=\n\t"
+ "orl $1, %0\n" /* Set our HWF_PADLOCK_RNG bit. */
+
+ ".Lno_rng%=:\n\t"
+ "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */
+ "andl $0xC0, %%eax\n\t" /* Test bits 6 and 7 to see whether */
+ "cmpl $0xC0, %%eax\n\t" /* the ACE exists and is enabled. */
+ "jnz .Lno_ace%=\n\t"
+ "orl $2, %0\n" /* Set our HWF_PADLOCK_AES bit. */
+
+ ".Lno_ace%=:\n\t"
+ "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */
+ "andl $0xC00, %%eax\n\t" /* Test bits 10, 11 to see whether */
+ "cmpl $0xC00, %%eax\n\t" /* the PHE exists and is enabled. */
+ "jnz .Lno_phe%=\n\t"
+ "orl $4, %0\n" /* Set our HWF_PADLOCK_SHA bit. */
+
+ ".Lno_phe%=:\n\t"
+ "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */
+ "andl $0x3000, %%eax\n\t" /* Test bits 12, 13 to see whether */
+ "cmpl $0x3000, %%eax\n\t" /* MONTMUL exists and is enabled. */
+ "jnz .Lready%=\n\t"
+ "orl $8, %0\n" /* Set our HWF_PADLOCK_MMUL bit. */
+
+ ".Lready%=:\n"
+ : "+r" (hw_features)
+ :
+ : "%eax", "%edx", "cc"
+ );
+ }
+#endif /*ENABLE_PADLOCK_SUPPORT*/
+ else if (!strcmp (vendor_id, "GenuineIntel"))
+ {
+ /* This is an Intel CPU. */
+ asm volatile
+ ("movl $1, %%eax\n\t" /* Get CPU info and feature flags. */
+ "cpuid\n"
+ "testl $0x02000000, %%ecx\n\t" /* Test bit 25. */
+ "jz .Lno_aes%=\n\t" /* No AES support. */
+ "orl $256, %0\n" /* Set our HWF_INTEL_AES bit. */
+
+ ".Lno_aes%=:\n"
+ : "+r" (hw_features)
+ :
+ : "%eax", "%ecx", "%edx", "cc"
+ );
+ }
+ else if (!strcmp (vendor_id, "AuthenticAMD"))
+ {
+ /* This is an AMD CPU. */
+
+ }
+}
+#endif /* __x86_64__ && __GNUC__ */
+
#if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__)
static void
detect_ia32_gnuc (void)
@@ -186,6 +279,10 @@ _gcry_detect_hw_features (unsigned int disabled_features)
#elif defined (__i386__) && SIZEOF_UNSIGNED_LONG == 8
#ifdef __GNUC__
#endif
+#elif defined (__x86_64__)
+#ifdef __GNUC__
+ detect_x86_64_gnuc ();
+#endif
#endif
hw_features &= ~disabled_features;