[PATCH] Adding better detection of AVX/AVX2 support

Panagiotis Christopoulos (pchrist) pchrist at gentoo.org
Mon Dec 30 00:41:13 CET 2013


After upgrading libgcrypt from 1.5.3 to 1.6.0 on a remote XEN system (linode) my
gpg2 stopped working properly, throwing SIGILL signals when doing sha512
operations etc. I managed to debug this with the help of Doublas Freed
(dwfreed at mtu.edu) and it seems that the current AVX detection just checks for
bit 28 on cpuid but the check still works  on systems that have disabled the avx/avx2
instructions for some reason (eg. performance/unstability) resulting in SIGILLs
(eg. when trying _gcry_sha512_transform_amd64_avx() ).
From Intel resources[1][2], I found additional checks for better AVX
detection and applied them in the following patch. Please review/change
accordingly and commit some better AVX detection mechanism. The AVX part is
tested but could not test the AVX2 one, because I lack proper hardware. I can
provide additional information upon request. Use the patch only as a guideline,
as it's not thoroughly tested. 

[1] http://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled
[2]
http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf
(sections 14.3 and 14.7.1)

Signed-off-by: Panagiotis Christopoulos (pchrist) <pchrist at gentoo.org>
---
 src/hwf-x86.c | 39 +++++++++++++++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/src/hwf-x86.c b/src/hwf-x86.c
index 4e82558..e58641e 100644
--- a/src/hwf-x86.c
+++ b/src/hwf-x86.c
@@ -129,6 +129,22 @@ get_cpuid(unsigned int in, unsigned int *eax, unsigned int *ebx,
   if (edx)
     *edx = regs[3];
 }
+
+static void
+get_xgetbv(unsigned int *eax)
+{
+  unsigned int t_eax;
+
+  asm volatile
+    ("xor %%ecx, %%ecx; xgetbv\n\t"
+     : "=a" (t_eax)
+    );
+
+  if (eax)
+    *eax = t_eax;
+}
+
+
 #endif /* x86-64 && GNUC */
 
 
@@ -138,6 +154,7 @@ detect_x86_gnuc (void)
 {
   char vendor_id[12+1];
   unsigned int features;
+  unsigned int xgetbv_result;
   unsigned int max_cpuid_level;
   unsigned int result = 0;
 
@@ -216,9 +233,12 @@ detect_x86_gnuc (void)
      result |= HWF_INTEL_AESNI;
 #endif /*ENABLE_AESNI_SUPPORT*/
 #ifdef ENABLE_AVX_SUPPORT
-  /* Test bit 28 for AVX.  */
-  if (features & 0x10000000)
-     result |= HWF_INTEL_AVX;
+  /* Test bits 27 and 28 for AVX.  */
+  if ((features & 0x18000000) == 0x18000000 ) {
+    get_xgetbv(&xgetbv_result);
+    if ((xgetbv_result & 0x6) == 0x6) 
+      result |= HWF_INTEL_AVX;
+  }
 #endif /*ENABLE_AVX_SUPPORT*/
 #ifdef ENABLE_DRNG_SUPPORT
   /* Test bit 30 for RDRAND.  */
@@ -241,8 +261,19 @@ detect_x86_gnuc (void)
 
 #ifdef ENABLE_AVX2_SUPPORT
       /* Test bit 5 for AVX2.  */
-      if (features & 0x00000020)
+      if (features & 0x00000020) {
+#ifndef ENABLE_AVX_SUPPORT
+        get_cpuid(1, NULL, NULL, &features, NULL);
+        if ((features & 0x18000000) == 0x18000000 ) {
+          get_xgetbv(&xgetbv_result);
+          if ((xgetbv_result & 0x6) == 0x6) 
+            result |= HWF_INTEL_AVX2;
+        }
+#else
+        if (result & HWF_INTEL_AVX)
           result |= HWF_INTEL_AVX2;
+#endif
+      }
 #endif /*ENABLE_AVX_SUPPORT*/
     }
 
-- 
1.8.5.2


-- 
Panagiotis Christopoulos ( pchrist )
    ( Gentoo Lisp Project )
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 291 bytes
Desc: not available
URL: </pipermail/attachments/20131230/ace890f2/attachment.sig>


More information about the Gcrypt-devel mailing list