Borrow the code from libgcrypt to check whether the compiler supports
the assembly instructions for SSSE3, SHA extensions, SSSE4.1, AVX, AVX2,
AVX512, and BMI2.

Also tweak _gcry_get_hw_features() in include/grub/crypto.h as the
preparation to support the hardware feature detection function from
libgcrypt.

Signed-off-by: Gary Lin <g...@suse.com>
---
 conf/Makefile.common  |   2 +
 configure.ac          | 254 ++++++++++++++++++++++++++++++++++++++++++
 include/grub/crypto.h |   4 +
 3 files changed, 260 insertions(+)

diff --git a/conf/Makefile.common b/conf/Makefile.common
index 4d38ff034..7ef171b2b 100644
--- a/conf/Makefile.common
+++ b/conf/Makefile.common
@@ -24,6 +24,8 @@ if COND_HAVE_PCI
   CFLAGS_PLATFORM += -DGRUB_HAS_PCI
 endif
 
+CPPFLAGS_GCRY_ASM = @CPPFLAGS_GCRY_ASM@
+
 # Other options
 
 CPPFLAGS_DEFAULT = -DGRUB_FILE=\"$(subst $(srcdir)/,,$<)\"
diff --git a/configure.ac b/configure.ac
index 83e3ddf90..c20b5d7c7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1148,6 +1148,259 @@ if test "x$grub_cv_cc_fno_ident" = xyes; then
   TARGET_CFLAGS="$TARGET_CFLAGS -fno-ident"
 fi
 
+# Implementation of the --disable-amd64-as-feature-detection switch.
+AC_MSG_CHECKING([whether to enable AMD64 as(1) feature detection])
+AC_ARG_ENABLE(amd64-as-feature-detection,
+              AS_HELP_STRING([--disable-amd64-as-feature-detection],
+                 [Disable the auto-detection of AMD64 as(1) features]),
+             amd64_as_feature_detection=$enableval,
+              amd64_as_feature_detection=yes)
+AC_MSG_RESULT($amd64_as_feature_detection)
+
+# Implementation of --disable-asm.
+AC_MSG_CHECKING([whether libgcrypt assembler modules are requested])
+AC_ARG_ENABLE([asm],
+              AS_HELP_STRING([--disable-asm],
+                             [Disable libgcrypt assembler modules]),
+              [try_asm_modules=$enableval],
+              [try_asm_modules=yes])
+AC_MSG_RESULT($try_asm_modules)
+if test "$try_asm_modules" != yes ; then
+    AC_DEFINE(ASM_DISABLED,1,[Defined if --disable-asm was used to configure])
+fi
+
+CFLAGS_GCRY_ASM=
+CPPFLAGS_GCRY_ASM=
+
+#
+# Check whether GCC assembler supports features needed for our i386/amd64
+# implementations
+#
+if test $amd64_as_feature_detection = yes; then
+  AC_CACHE_CHECK([whether GCC assembler is compatible for i386/amd64 assembly 
implementations],
+       [gcry_cv_gcc_x86_platform_as_ok],
+       [if test "$target_cpu" != "x86_64" ||
+           test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_x86_platform_as_ok="n/a"
+        else
+          gcry_cv_gcc_x86_platform_as_ok=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[__asm__(
+                /* Test if '.type' and '.size' are supported.  */
+                /* These work only on ELF targets. */
+                ".text\n\t"
+                "asmfunc:\n\t"
+                ".size asmfunc,.-asmfunc;\n\t"
+                ".type asmfunc,@function;\n\t"
+                /* Test if assembler allows use of '/' for constant division
+                 * (Solaris/x86 issue). If previous constant division check
+                 * and "-Wa,--divide" workaround failed, this causes assembly
+                 * to be disable on this machine. */
+                 "xorl \$(123456789/12345678), %ebp;\n\t"
+            );
+            void asmfunc(void);]], [ asmfunc(); ])],
+          [gcry_cv_gcc_x86_platform_as_ok=yes])
+        fi])
+  if test "$gcry_cv_gcc_x86_platform_as_ok" = "yes"; then
+    CPPFLAGS_GCRY_ASM="-D__x86_64 -DHAVE_CPU_ARCH_X86 
-DHAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS"
+  fi
+fi
+
+#
+# Check whether GCC assembler supports features needed for assembly
+# implementations that use Intel syntax
+#
+AC_CACHE_CHECK([whether GCC assembler is compatible for Intel syntax assembly 
implementations],
+       [gcry_cv_gcc_platform_as_ok_for_intel_syntax],
+       [if test "$target_cpu" != "x86_64" ||
+           test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_platform_as_ok_for_intel_syntax="n/a"
+        else
+          gcry_cv_gcc_platform_as_ok_for_intel_syntax=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[__asm__(
+                ".intel_syntax noprefix\n\t"
+                ".text\n\t"
+                "actest:\n\t"
+                "pxor xmm1, xmm7;\n\t"
+                "vperm2i128 ymm2, ymm3, ymm0, 1;\n\t"
+                "add eax, ebp;\n\t"
+                "rorx eax, ebp, 1;\n\t"
+                "sub eax, [esp + 4];\n\t"
+                "add dword ptr [esp + eax], 0b10101;\n\t"
+                ".att_syntax prefix\n\t"
+            );
+            void actest(void);]], [ actest(); ])],
+          [gcry_cv_gcc_platform_as_ok_for_intel_syntax=yes])
+        fi])
+if test "$gcry_cv_gcc_platform_as_ok_for_intel_syntax" = "yes" ; then
+  CPPFLAGS_GCRY_ASM="$CPPFLAGS_GCRY_ASM -DHAVE_INTEL_SYNTAX_PLATFORM_AS"
+fi
+
+#
+# Check whether GCC inline assembler supports SSSE3 instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports SSSE3 instructions],
+       [gcry_cv_gcc_inline_asm_ssse3],
+       [if test "$target_cpu" != "x86_64" ||
+           test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_inline_asm_ssse3="n/a"
+        else
+          gcry_cv_gcc_inline_asm_ssse3=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[static unsigned char be_mask[16] __attribute__ ((aligned (16))) =
+              { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
+            void a(void) {
+              __asm__("pshufb %[mask], %%xmm2\n\t"::[mask]"m"(*be_mask):);
+            }]], [ a(); ] )],
+          [gcry_cv_gcc_inline_asm_ssse3=yes])
+        fi])
+if test "$gcry_cv_gcc_inline_asm_ssse3" = "yes" ; then
+   CPPFLAGS_GCRY_ASM="$CPPFLAGS_GCRY_ASM -DHAVE_GCC_INLINE_ASM_SSSE3"
+fi
+
+#
+# Check whether GCC inline assembler supports SHA Extensions instructions.
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports SHA Extensions 
instructions],
+       [gcry_cv_gcc_inline_asm_shaext],
+       [if test "$target_cpu" != "x86_64" ||
+           test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_inline_asm_shaext="n/a"
+        else
+          gcry_cv_gcc_inline_asm_shaext=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[void a(void) {
+              __asm__("sha1rnds4 \$0, %%xmm1, %%xmm3\n\t":::"cc");
+              __asm__("sha1nexte %%xmm1, %%xmm3\n\t":::"cc");
+              __asm__("sha1msg1 %%xmm1, %%xmm3\n\t":::"cc");
+              __asm__("sha1msg2 %%xmm1, %%xmm3\n\t":::"cc");
+              __asm__("sha256rnds2 %%xmm0, %%xmm1, %%xmm3\n\t":::"cc");
+              __asm__("sha256msg1 %%xmm1, %%xmm3\n\t":::"cc");
+              __asm__("sha256msg2 %%xmm1, %%xmm3\n\t":::"cc");
+            }]], [ a(); ] )],
+          [gcry_cv_gcc_inline_asm_shaext=yes])
+        fi])
+if test "$gcry_cv_gcc_inline_asm_shaext" = "yes" ; then
+   CPPFLAGS_GCRY_ASM="$CPPFLAGS_GCRY_ASM -DHAVE_GCC_INLINE_ASM_SHAEXT 
-DENABLE_SHAEXT_SUPPORT"
+fi
+
+#
+# Check whether GCC inline assembler supports SSE4.1 instructions.
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports SSE4.1 instructions],
+       [gcry_cv_gcc_inline_asm_sse41],
+       [if test "$target_cpu" != "x86_64" ||
+           test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_inline_asm_sse41="n/a"
+        else
+          gcry_cv_gcc_inline_asm_sse41=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[void a(void) {
+              int i;
+              __asm__("pextrd \$2, %%xmm0, %[out]\n\t" : [out] "=m" (i));
+            }]], [ a(); ] )],
+          [gcry_cv_gcc_inline_asm_sse41=yes])
+        fi])
+if test "$gcry_cv_gcc_inline_asm_sse41" = "yes" ; then
+   AC_DEFINE(HAVE_GCC_INLINE_ASM_SSE41,1,
+     [Defined if inline assembler supports SSE4.1 instructions])
+   CPPFLAGS_GCRY_ASM="$CPPFLAGS_GCRY_ASM -DHAVE_GCC_INLINE_ASM_SSE41"
+fi
+
+#
+# Check whether GCC inline assembler supports AVX instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports AVX instructions],
+       [gcry_cv_gcc_inline_asm_avx],
+       [if test "$target_cpu" != "x86_64" ||
+           test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_inline_asm_avx="n/a"
+        else
+          gcry_cv_gcc_inline_asm_avx=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[void a(void) {
+              __asm__("xgetbv; vaesdeclast 
(%[mem]),%%xmm0,%%xmm7\n\t"::[mem]"r"(0):);
+            }]], [ a(); ] )],
+          [gcry_cv_gcc_inline_asm_avx=yes])
+        fi])
+if test "$gcry_cv_gcc_inline_asm_avx" = "yes" ; then
+   CPPFLAGS_GCRY_ASM="$CPPFLAGS_GCRY_ASM -DHAVE_GCC_INLINE_ASM_AVX 
-DENABLE_AVX_SUPPORT"
+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],
+       [if test "$target_cpu" != "x86_64" ||
+           test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_inline_asm_avx2="n/a"
+        else
+          gcry_cv_gcc_inline_asm_avx2=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[void a(void) {
+              __asm__("xgetbv; vpbroadcastb %%xmm7,%%ymm1\n\t":::"cc");
+            }]], [ a(); ] )],
+          [gcry_cv_gcc_inline_asm_avx2=yes])
+        fi])
+if test "$gcry_cv_gcc_inline_asm_avx2" = "yes" ; then
+   CPPFLAGS_GCRY_ASM="$CPPFLAGS_GCRY_ASM -DHAVE_GCC_INLINE_ASM_AVX2 
-DENABLE_AVX2_SUPPORT"
+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 "$target_cpu" != "x86_64" ||
+           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");
+              __asm__("vpxorq %%xmm7, %%xmm7, %%xmm7;\n\t":::"cc");
+              __asm__("vpxorq %%ymm7, %%ymm7, %%ymm7;\n\t":::"cc");
+              __asm__("vpxorq (%%eax)%{1to8%}, %%zmm7, %%zmm7;\n\t":::"cc");
+            }]], [ a(); ] )],
+          [gcry_cv_gcc_inline_asm_avx512=yes])
+        fi])
+if test "$gcry_cv_gcc_inline_asm_avx512" = "yes" ; then
+   CPPFLAGS_GCRY_ASM="$CPPFLAGS_GCRY_ASM -DHAVE_GCC_INLINE_ASM_AVX512 
-DENABLE_AVX512_SUPPORT"
+fi
+
+#
+# Check whether GCC inline assembler supports BMI2 instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports BMI2 instructions],
+       [gcry_cv_gcc_inline_asm_bmi2],
+       [if test "$target_cpu" != "x86_64" ||
+           test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_inline_asm_bmi2="n/a"
+        else
+          gcry_cv_gcc_inline_asm_bmi2=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[unsigned int a(unsigned int x, unsigned int y) {
+              unsigned int tmp1, tmp2;
+              asm ("rorxl %2, %1, %0"
+                   : "=r" (tmp1)
+                   : "rm0" (x), "J" (32 - ((23) & 31)));
+              asm ("andnl %2, %1, %0"
+                   : "=r" (tmp2)
+                   : "r0" (x), "rm" (y));
+              return tmp1 + tmp2;
+            }]], [ a(1, 2); ] )],
+          [gcry_cv_gcc_inline_asm_bmi2=yes])
+        fi])
+if test "$gcry_cv_gcc_inline_asm_bmi2" = "yes" ; then
+   CPPFLAGS_GCRY_ASM="$CPPFLAGS_GCRY_ASM -DHAVE_GCC_INLINE_ASM_BMI2"
+fi
+
+AC_SUBST(CPPFLAGS_GCRY_ASM)
+
 CFLAGS="$TARGET_CFLAGS"
 
 
@@ -2218,6 +2471,7 @@ AM_CONDITIONAL([COND_sparc64_ieee1275], [test 
x$target_cpu = xsparc64 -a x$platf
 AM_CONDITIONAL([COND_sparc64_emu], [test x$target_cpu = xsparc64 -a x$platform 
= xemu])
 AM_CONDITIONAL([COND_x86_64_efi], [test x$target_cpu = xx86_64 -a x$platform = 
xefi])
 AM_CONDITIONAL([COND_x86_64_xen], [test x$target_cpu = xx86_64 -a x$platform = 
xxen])
+AM_CONDITIONAL([COND_emu_hw_asm], [test x$target_cpu = xx86_64])
 
 AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd])
 AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux])
diff --git a/include/grub/crypto.h b/include/grub/crypto.h
index 4f3dd8c63..6ac51138a 100644
--- a/include/grub/crypto.h
+++ b/include/grub/crypto.h
@@ -585,10 +585,14 @@ unsigned int
 _gcry_ct_not_memequal (const void *b1, const void *b2, grub_size_t len);
 
 
+#ifdef GRUB_UTIL
 static inline unsigned int _gcry_get_hw_features(void)
 {
   return 0;
 }
+#else
+extern unsigned int _gcry_get_hw_features(void);
+#endif
 
 void *_gcry_malloc(grub_size_t n);
 void *_gcry_malloc_secure(grub_size_t n);
-- 
2.43.0


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to