Add detection for Intel AVX2 instruction set
authorJussi Kivilinna <jussi.kivilinna@iki.fi>
Sun, 9 Jun 2013 13:37:38 +0000 (16:37 +0300)
committerJussi Kivilinna <jussi.kivilinna@iki.fi>
Sun, 9 Jun 2013 13:37:42 +0000 (16:37 +0300)
* configure.ac: Add option --disable-avx2-support.
(HAVE_GCC_INLINE_ASM_AVX2): New.
(ENABLE_AVX2_SUPPORT): New.
* src/g10lib.h (HWF_INTEL_AVX2): New.
* src/global.c (hwflist): Add HWF_INTEL_AVX2.
* src/hwf-x86.c [__i386__] (get_cpuid): Initialize registers to zero
before cpuid.
[__x86_64__] (get_cpuid): Initialize registers to zero before cpuid.
(detect_x86_gnuc): Store maximum cpuid level.
(detect_x86_gnuc) [ENABLE_AVX2_SUPPORT]: Add detection for AVX2.
--

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
configure.ac
src/g10lib.h
src/global.c
src/hwf-x86.c

index 8cb980c..7fc7935 100644 (file)
@@ -594,6 +594,14 @@ AC_ARG_ENABLE(avx-support,
              avxsupport=$enableval,avxsupport=yes)
 AC_MSG_RESULT($avxsupport)
 
+# Implementation of the --disable-avx2-support switch.
+AC_MSG_CHECKING([whether AVX2 support is requested])
+AC_ARG_ENABLE(avx2-support,
+              AC_HELP_STRING([--disable-avx2-support],
+                 [Disable support for the Intel AVX2 instructions]),
+             avx2support=$enableval,avx2support=yes)
+AC_MSG_RESULT($avx2support)
+
 # Implementation of the --disable-O-flag-munging switch.
 AC_MSG_CHECKING([whether a -O flag munging is requested])
 AC_ARG_ENABLE([O-flag-munging],
@@ -916,6 +924,23 @@ if test "$gcry_cv_gcc_inline_asm_avx" = "yes" ; then
 fi
 
 
+#
+# Check whether GCC inline assembler supports AVX2 instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports AVX2 instructions],
+       [gcry_cv_gcc_inline_asm_avx2],
+       [gcry_cv_gcc_inline_asm_avx2=no
+        AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          [[void a(void) {
+              __asm__("vpbroadcastb %%xmm7,%%ymm1\n\t":::);
+            }]])],
+          [gcry_cv_gcc_inline_asm_avx2=yes])])
+if test "$gcry_cv_gcc_inline_asm_avx2" = "yes" ; then
+   AC_DEFINE(HAVE_GCC_INLINE_ASM_AVX2,1,
+     [Defined if inline assembler supports AVX2 instructions])
+fi
+
+
 #######################################
 #### Checks for library functions. ####
 #######################################
@@ -1165,6 +1190,11 @@ if test x"$avxsupport" = xyes ; then
     avxsupport="no (unsupported by compiler)"
   fi
 fi
+if test x"$avx2support" = xyes ; then
+  if test "$gcry_cv_gcc_inline_asm_avx2" != "yes" ; then
+    avx2support="no (unsupported by compiler)"
+  fi
+fi
 
 if test x"$aesnisupport" = xyes ; then
   AC_DEFINE(ENABLE_AESNI_SUPPORT, 1,
@@ -1174,6 +1204,10 @@ if test x"$avxsupport" = xyes ; then
   AC_DEFINE(ENABLE_AVX_SUPPORT,1,
             [Enable support for Intel AVX instructions.])
 fi
+if test x"$avx2support" = xyes ; then
+  AC_DEFINE(ENABLE_AVX2_SUPPORT,1,
+            [Enable support for Intel AVX2 instructions.])
+fi
 
 
 # Define conditional sources and config.h symbols depending on the
@@ -1513,6 +1547,7 @@ GCRY_MSG_SHOW([Try using Padlock crypto: ],[$padlocksupport])
 GCRY_MSG_SHOW([Try using AES-NI crypto:  ],[$aesnisupport])
 GCRY_MSG_SHOW([Try using DRNG (RDRAND):  ],[$drngsupport])
 GCRY_MSG_SHOW([Try using Intel AVX:      ],[$avxsupport])
+GCRY_MSG_SHOW([Try using Intel AVX2:     ],[$avx2support])
 GCRY_MSG_SHOW([],[])
 
 if test "$print_egd_notice" = "yes"; then
index 23ea096..e6d20e9 100644 (file)
@@ -153,6 +153,7 @@ int _gcry_log_verbosity( int level );
 #define HWF_INTEL_AESNI  256
 #define HWF_INTEL_RDRAND 512
 #define HWF_INTEL_AVX    1024
+#define HWF_INTEL_AVX2   2048
 
 
 unsigned int _gcry_get_hw_features (void);
index a6fe980..9c80573 100644 (file)
@@ -69,6 +69,7 @@ static struct
     { HWF_INTEL_AESNI, "intel-aesni" },
     { HWF_INTEL_RDRAND,"intel-rdrand" },
     { HWF_INTEL_AVX,   "intel-avx" },
+    { HWF_INTEL_AVX2,  "intel-avx2" },
     { 0, NULL}
   };
 
index 1e6ec94..2ceb04c 100644 (file)
@@ -77,11 +77,12 @@ get_cpuid(unsigned int in, unsigned int *eax, unsigned int *ebx,
 
   asm volatile
     ("pushl %%ebx\n\t"           /* Save GOT register.  */
+     "movl %1, %%ebx\n\t"
      "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)
+     : "0" (in), "1" (0), "2" (0), "3" (0)
      : "cc"
      );
 
@@ -115,7 +116,7 @@ get_cpuid(unsigned int in, unsigned int *eax, unsigned int *ebx,
   asm volatile
     ("cpuid\n\t"
      : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
-     : "0" (in)
+     : "0" (in), "1" (0), "2" (0), "3" (0)
      : "cc"
      );
 
@@ -137,12 +138,13 @@ detect_x86_gnuc (void)
 {
   char vendor_id[12+1];
   unsigned int features;
+  unsigned int max_cpuid_level;
   unsigned int result = 0;
 
   if (!is_cpuid_available())
     return 0;
 
-  get_cpuid(0, NULL,
+  get_cpuid(0, &max_cpuid_level,
             (unsigned int *)&vendor_id[0],
             (unsigned int *)&vendor_id[8],
             (unsigned int *)&vendor_id[4]);
@@ -215,6 +217,22 @@ detect_x86_gnuc (void)
      result |= HWF_INTEL_RDRAND;
 #endif /*ENABLE_DRNG_SUPPORT*/
 
+  /* Check additional Intel feature flags.  Early Intel P5 processors report
+   * too high max_cpuid_level, so don't check level 7 if processor does not
+   * support SSE3 (as cpuid:7 contains only features for newer processors).
+   * Source: http://www.sandpile.org/x86/cpuid.htm  */
+  if (max_cpuid_level >= 7 && (features & 0x00000001))
+    {
+#ifdef ENABLE_AVX2_SUPPORT
+      /* Get CPUID:7 contains further Intel feature flags. */
+      get_cpuid(7, NULL, &features, NULL, NULL);
+
+      /* Test bit 5 for AVX2.  */
+      if (features & 0x00000020)
+          result |= HWF_INTEL_AVX2;
+#endif /*ENABLE_AVX_SUPPORT*/
+    }
+
   return result;
 }
 #endif /* HAS_X86_CPUID */