To enable hardware acceleration, this commit ports the feature detection logic from libgcrypt. This allows us to check if the compiler supports specific assembly instructions, including SSSE3, Intel SHA extensions, SSE4.1, AVX, AVX2, AVX512, and BMI2.
To simplify the initial implementation, support for x86_64 feature detection is currently limited to the x86_64 EFI target. Signed-off-by: Gary Lin <[email protected]> Reviewed-by: Daniel Kiper <[email protected]> --- conf/Makefile.common | 2 + configure.ac | 233 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 235 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 1036638a9..1f391fa8e 100644 --- a/configure.ac +++ b/configure.ac @@ -1148,6 +1148,239 @@ 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]) +if test x$target_cpu == xx86_64 -a x$platform == xefi; then + CPPFLAGS_GCRY_ASM="-D__x86_64 -DHAVE_CPU_ARCH_X86" + 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]) +else + CPPFLAGS_GCRY_ASM= + amd64_as_feature_detection=no +fi +AC_MSG_RESULT($amd64_as_feature_detection) + +# +# Check whether GCC assembler supports features needed for libgcrypt amd64 +# implementations +# +if test $amd64_as_feature_detection = yes; then + AC_CACHE_CHECK([whether GCC assembler is compatible for amd64 assembly implementations], + [grub_cv_gcc_x86_platform_as_ok], + [if test "$target_cpu" != "x86_64" ; then + grub_cv_gcc_x86_platform_as_ok="n/a" + else + grub_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(); ])], + [grub_cv_gcc_x86_platform_as_ok=yes]) + fi]) + if test "$grub_cv_gcc_x86_platform_as_ok" = "yes"; then + # Define __PIC__ to ensure the assembly code use PIC instructions + CPPFLAGS_GCRY_ASM="$CPPFLAGS_GCRY_ASM -D__PIC__=1 -DHAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS" + fi + + # + # Check whether GCC assembler supports Intel syntax + # + AC_CACHE_CHECK([whether GCC assembler is compatible for Intel syntax assembly implementations], + [grub_cv_gcc_platform_as_ok_for_intel_syntax], + [if test "$target_cpu" != "x86_64" ; then + grub_cv_gcc_platform_as_ok_for_intel_syntax="n/a" + else + grub_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(); ])], + [grub_cv_gcc_platform_as_ok_for_intel_syntax=yes]) + fi]) + if test "$grub_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], + [grub_cv_gcc_inline_asm_ssse3], + [if test "$target_cpu" != "x86_64" ; then + grub_cv_gcc_inline_asm_ssse3="n/a" + else + grub_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(); ] )], + [grub_cv_gcc_inline_asm_ssse3=yes]) + fi]) + if test "$grub_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], + [grub_cv_gcc_inline_asm_shaext], + [if test "$target_cpu" != "x86_64" ; then + grub_cv_gcc_inline_asm_shaext="n/a" + else + grub_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(); ] )], + [grub_cv_gcc_inline_asm_shaext=yes]) + fi]) + if test "$grub_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], + [grub_cv_gcc_inline_asm_sse41], + [if test "$target_cpu" != "x86_64" ; then + grub_cv_gcc_inline_asm_sse41="n/a" + else + grub_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(); ] )], + [grub_cv_gcc_inline_asm_sse41=yes]) + fi]) + if test "$grub_cv_gcc_inline_asm_sse41" = "yes" ; then + 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], + [grub_cv_gcc_inline_asm_avx], + [if test "$target_cpu" != "x86_64" ; then + grub_cv_gcc_inline_asm_avx="n/a" + else + grub_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(); ] )], + [grub_cv_gcc_inline_asm_avx=yes]) + fi]) + if test "$grub_cv_gcc_inline_asm_avx" = "yes" ; then + CPPFLAGS_GCRY_ASM="$CPPFLAGS_GCRY_ASM -DHAVE_GCC_INLINE_ASM_AVX" + fi + + # + # Check whether GCC inline assembler supports AVX2 instructions + # + AC_CACHE_CHECK([whether GCC inline assembler supports AVX2 instructions], + [grub_cv_gcc_inline_asm_avx2], + [if test "$target_cpu" != "x86_64" ; then + grub_cv_gcc_inline_asm_avx2="n/a" + else + grub_cv_gcc_inline_asm_avx2=no + AC_LINK_IFELSE([AC_LANG_PROGRAM( + [[void a(void) { + __asm__("xgetbv; vpbroadcastb %%xmm7,%%ymm1\n\t":::"cc"); + }]], [ a(); ] )], + [grub_cv_gcc_inline_asm_avx2=yes]) + fi]) + if test "$grub_cv_gcc_inline_asm_avx2" = "yes" ; then + CPPFLAGS_GCRY_ASM="$CPPFLAGS_GCRY_ASM -DHAVE_GCC_INLINE_ASM_AVX2" + fi + + # + # Check whether GCC inline assembler supports AVX512 instructions + # + AC_CACHE_CHECK([whether GCC inline assembler supports AVX512 instructions], + [grub_cv_gcc_inline_asm_avx512], + [if test "$target_cpu" != "x86_64" ; then + grub_cv_gcc_inline_asm_avx512="n/a" + else + grub_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(); ] )], + [grub_cv_gcc_inline_asm_avx512=yes]) + fi]) + if test "$grub_cv_gcc_inline_asm_avx512" = "yes" ; then + CPPFLAGS_GCRY_ASM="$CPPFLAGS_GCRY_ASM -DHAVE_GCC_INLINE_ASM_AVX512" + fi + + # + # Check whether GCC inline assembler supports BMI2 instructions + # + AC_CACHE_CHECK([whether GCC inline assembler supports BMI2 instructions], + [grub_cv_gcc_inline_asm_bmi2], + [if test "$target_cpu" != "x86_64" ; then + grub_cv_gcc_inline_asm_bmi2="n/a" + else + grub_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); ] )], + [grub_cv_gcc_inline_asm_bmi2=yes]) + fi]) + if test "$grub_cv_gcc_inline_asm_bmi2" = "yes" ; then + CPPFLAGS_GCRY_ASM="$CPPFLAGS_GCRY_ASM -DHAVE_GCC_INLINE_ASM_BMI2" + fi +fi + +AC_SUBST(CPPFLAGS_GCRY_ASM) + CFLAGS="$TARGET_CFLAGS" -- 2.51.0 _______________________________________________ Grub-devel mailing list [email protected] https://lists.gnu.org/mailman/listinfo/grub-devel
