[PATCH 2/3] Add detection for HW feature "intel-avx512"

Jussi Kivilinna jussi.kivilinna at iki.fi
Sun Mar 6 18:19:09 CET 2022


* configure.ac (avx512support, gcry_cv_gcc_inline_asm_avx512)
(ENABLE_AVX512_SUPPORT): New.
* src/g10lib.h (HWF_INTEL_AVX512): New.
* src/hwf-x86.c (detect_x86_gnuc): Add AVX512 detection.
* src/hwfeatures.c (hwflist): Add "intel-avx512".
--

Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 configure.ac     | 36 +++++++++++++++++++++++++++++++++++
 src/g10lib.h     |  1 +
 src/hwf-x86.c    | 49 +++++++++++++++++++++++++++++++++++++++++++++---
 src/hwfeatures.c |  1 +
 4 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/configure.ac b/configure.ac
index e20f9d13..27d72141 100644
--- a/configure.ac
+++ b/configure.ac
@@ -667,6 +667,14 @@ AC_ARG_ENABLE(avx2-support,
 	      avx2support=$enableval,avx2support=yes)
 AC_MSG_RESULT($avx2support)
 
+# Implementation of the --disable-avx512-support switch.
+AC_MSG_CHECKING([whether AVX512 support is requested])
+AC_ARG_ENABLE(avx512-support,
+              AS_HELP_STRING([--disable-avx512-support],
+                 [Disable support for the Intel AVX512 instructions]),
+	      avx512support=$enableval,avx512support=yes)
+AC_MSG_RESULT($avx512support)
+
 # Implementation of the --disable-neon-support switch.
 AC_MSG_CHECKING([whether NEON support is requested])
 AC_ARG_ENABLE(neon-support,
@@ -1545,6 +1553,29 @@ if test "$gcry_cv_gcc_inline_asm_avx2" = "yes" ; then
 fi
 
 
+#
+# Check whether GCC inline assembler supports AVX512 instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports AVX512 instructions],
+       [gcry_cv_gcc_inline_asm_avx512],
+       [if test "$mpi_cpu_arch" != "x86" ||
+           test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_inline_asm_avx512="n/a"
+        else
+          gcry_cv_gcc_inline_asm_avx512=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[void a(void) {
+              __asm__("xgetbv; vpopcntq %%zmm7, %%zmm1%{%%k1%}%{z%};\n\t":::"cc");
+              __asm__("vpexpandb %%zmm3, %%zmm1;\n\t":::"cc");
+            }]], [ a(); ] )],
+          [gcry_cv_gcc_inline_asm_avx512=yes])
+        fi])
+if test "$gcry_cv_gcc_inline_asm_avx512" = "yes" ; then
+   AC_DEFINE(HAVE_GCC_INLINE_ASM_AVX512,1,
+     [Defined if inline assembler supports AVX512 instructions])
+fi
+
+
 #
 # Check whether GCC inline assembler supports VAES and VPCLMUL instructions
 #
@@ -2409,6 +2440,10 @@ if test x"$avx2support" = xyes ; then
   AC_DEFINE(ENABLE_AVX2_SUPPORT,1,
             [Enable support for Intel AVX2 instructions.])
 fi
+if test x"$avx512support" = xyes ; then
+  AC_DEFINE(ENABLE_AVX512_SUPPORT,1,
+            [Enable support for Intel AVX512 instructions.])
+fi
 if test x"$neonsupport" = xyes ; then
   AC_DEFINE(ENABLE_NEON_SUPPORT,1,
             [Enable support for ARM NEON instructions.])
@@ -3266,6 +3301,7 @@ GCRY_MSG_SHOW([Try using Intel SSE4.1:   ],[$sse41support])
 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([Try using Intel AVX512:   ],[$avx512support])
 GCRY_MSG_SHOW([Try using ARM NEON:       ],[$neonsupport])
 GCRY_MSG_SHOW([Try using ARMv8 crypto:   ],[$armcryptosupport])
 GCRY_MSG_SHOW([Try using PPC crypto:     ],[$ppccryptosupport])
diff --git a/src/g10lib.h b/src/g10lib.h
index 985e75c6..c07ed788 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -237,6 +237,7 @@ char **_gcry_strtokenize (const char *string, const char *delim);
 #define HWF_INTEL_RDTSC         (1 << 15)
 #define HWF_INTEL_SHAEXT        (1 << 16)
 #define HWF_INTEL_VAES_VPCLMUL  (1 << 17)
+#define HWF_INTEL_AVX512        (1 << 18)
 
 #elif defined(HAVE_CPU_ARCH_ARM)
 
diff --git a/src/hwf-x86.c b/src/hwf-x86.c
index a1aa02e7..0a5266c6 100644
--- a/src/hwf-x86.c
+++ b/src/hwf-x86.c
@@ -182,12 +182,14 @@ detect_x86_gnuc (void)
   } vendor_id;
   unsigned int features, features2;
   unsigned int os_supports_avx_avx2_registers = 0;
+  unsigned int os_supports_avx512_registers = 0;
   unsigned int max_cpuid_level;
   unsigned int fms, family, model;
   unsigned int result = 0;
   unsigned int avoid_vpgather = 0;
 
   (void)os_supports_avx_avx2_registers;
+  (void)os_supports_avx512_registers;
 
   if (!is_cpuid_available())
     return 0;
@@ -338,13 +340,22 @@ detect_x86_gnuc (void)
   if (features & 0x02000000)
      result |= HWF_INTEL_AESNI;
 #endif /*ENABLE_AESNI_SUPPORT*/
-#if defined(ENABLE_AVX_SUPPORT) || defined(ENABLE_AVX2_SUPPORT)
-  /* Test bit 27 for OSXSAVE (required for AVX/AVX2).  */
+#if defined(ENABLE_AVX_SUPPORT) || defined(ENABLE_AVX2_SUPPORT) \
+    || defined(ENABLE_AVX512_SUPPORT)
+  /* Test bit 27 for OSXSAVE (required for AVX/AVX2/AVX512).  */
   if (features & 0x08000000)
     {
+      unsigned int xmm_ymm_mask = (1 << 2) | (1 << 1);
+      unsigned int zmm15_ymm31_k7_mask = (1 << 7) | (1 << 6) | (1 << 5);
+      unsigned int xgetbv = get_xgetbv();
+
       /* Check that OS has enabled both XMM and YMM state support.  */
-      if ((get_xgetbv() & 0x6) == 0x6)
+      if ((xgetbv & xmm_ymm_mask) == xmm_ymm_mask)
         os_supports_avx_avx2_registers = 1;
+
+      /* Check that OS has enabled both XMM and YMM state support.  */
+      if ((xgetbv & zmm15_ymm31_k7_mask) == zmm15_ymm31_k7_mask)
+        os_supports_avx512_registers = 1;
     }
 #endif
 #ifdef ENABLE_AVX_SUPPORT
@@ -396,6 +407,38 @@ detect_x86_gnuc (void)
       if ((features2 & 0x00000200) && (features2 & 0x00000400))
         result |= HWF_INTEL_VAES_VPCLMUL;
 #endif
+
+#ifdef ENABLE_AVX512_SUPPORT
+      /* Test for AVX512 features. List of features is selected so that
+       * supporting CPUs are new enough not to suffer from reduced clock
+       * frequencies when AVX512 is used, which was issue on early AVX512
+       * capable CPUs.
+       *  - AVX512F (features bit 16)
+       *  - AVX512DQ (features bit 17)
+       *  - AVX512IFMA (features bit 21)
+       *  - AVX512CD (features bit 28)
+       *  - AVX512BW (features bit 30)
+       *  - AVX512VL (features bit 31)
+       *  - AVX512_VBMI (features2 bit 1)
+       *  - AVX512_VBMI2 (features2 bit 6)
+       *  - AVX512_VNNI (features2 bit 11)
+       *  - AVX512_BITALG (features2 bit 12)
+       *  - AVX512_VPOPCNTDQ (features2 bit 14)
+       */
+      if (os_supports_avx512_registers
+	  && (features & (1 << 16))
+	  && (features & (1 << 17))
+	  && (features & (1 << 21))
+	  && (features & (1 << 28))
+	  && (features & (1 << 30))
+	  && (features & (1 << 31))
+	  && (features2 & (1 << 1))
+	  && (features2 & (1 << 6))
+	  && (features2 & (1 << 11))
+	  && (features2 & (1 << 12))
+	  && (features2 & (1 << 14)))
+	result |= HWF_INTEL_AVX512;
+#endif
     }
 
   return result;
diff --git a/src/hwfeatures.c b/src/hwfeatures.c
index 7060d995..8e92cbdd 100644
--- a/src/hwfeatures.c
+++ b/src/hwfeatures.c
@@ -62,6 +62,7 @@ static struct
     { HWF_INTEL_RDTSC,         "intel-rdtsc" },
     { HWF_INTEL_SHAEXT,        "intel-shaext" },
     { HWF_INTEL_VAES_VPCLMUL,  "intel-vaes-vpclmul" },
+    { HWF_INTEL_AVX512,        "intel-avx512" },
 #elif defined(HAVE_CPU_ARCH_ARM)
     { HWF_ARM_NEON,            "arm-neon" },
     { HWF_ARM_AES,             "arm-aes" },
-- 
2.32.0




More information about the Gcrypt-devel mailing list