df07cd5
commit ee9f98d9cac12e843ca59c6e4d4b225f58a66727
df07cd5
Author: H.J. Lu <hjl.tools@gmail.com>
df07cd5
Date:   Tue Feb 2 13:45:58 2021 -0800
df07cd5
df07cd5
    x86: Set minimum x86-64 level marker [BZ #27318]
df07cd5
    
df07cd5
    Since the full ISA set used in an ELF binary is unknown to compiler,
df07cd5
    an x86-64 ISA level marker indicates the minimum, not maximum, ISA set
df07cd5
    required to run such an ELF binary.  We never guarantee a library with
df07cd5
    an x86-64 ISA level v3 marker doesn't contain other ISAs beyond x86-64
df07cd5
    ISA level v3, like AVX VNNI.  We check the x86-64 ISA level marker for
df07cd5
    the minimum ISA set.  Since -march=sandybridge enables only some ISAs
df07cd5
    in x86-64 ISA level v3, we should set the needed ISA marker to v2.
df07cd5
    Otherwise, libc is compiled with -march=sandybridge will fail to run on
df07cd5
    Sandy Bridge:
df07cd5
    
df07cd5
    $ ./elf/ld.so ./libc.so
df07cd5
    ./libc.so: (p) CPU ISA level is lower than required: needed: 7; got: 3
df07cd5
    
df07cd5
    Set the minimum, instead of maximum, x86-64 ISA level marker should have
df07cd5
    no impact on the glibc-hwcaps directory assignment logic in ldconfig nor
df07cd5
    ld.so.
df07cd5
    
df07cd5
    (cherry picked from commit 339bf918ea4830fb35614632e96f3aab3237adce)
df07cd5
df07cd5
diff --git a/config.h.in b/config.h.in
df07cd5
index 06ee8ae26a0eb833..f21bf04e4791e5dc 100644
df07cd5
--- a/config.h.in
df07cd5
+++ b/config.h.in
df07cd5
@@ -275,4 +275,10 @@
df07cd5
 /* Define if x86 ISA level should be included in shared libraries.  */
df07cd5
 #undef INCLUDE_X86_ISA_LEVEL
df07cd5
 
df07cd5
+/* Define if -msahf is enabled by default on x86.  */
df07cd5
+#undef HAVE_X86_LAHF_SAHF
df07cd5
+
df07cd5
+/* Define if -mmovbe is enabled by default on x86.  */
df07cd5
+#undef HAVE_X86_MOVBE
df07cd5
+
df07cd5
 #endif
df07cd5
diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure
df07cd5
index 5e32dc62b334b27f..ead1295c38cf5f4e 100644
df07cd5
--- a/sysdeps/x86/configure
df07cd5
+++ b/sysdeps/x86/configure
df07cd5
@@ -126,6 +126,8 @@ cat > conftest2.S <
df07cd5
 4:
df07cd5
 EOF
df07cd5
 libc_cv_include_x86_isa_level=no
df07cd5
+libc_cv_have_x86_lahf_sahf=no
df07cd5
+libc_cv_have_x86_movbe=no
df07cd5
 if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest conftest1.S conftest2.S'
df07cd5
   { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
df07cd5
   (eval $ac_try) 2>&5
df07cd5
@@ -135,6 +137,24 @@ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest c
df07cd5
   count=`LC_ALL=C $READELF -n conftest | grep NT_GNU_PROPERTY_TYPE_0 | wc -l`
df07cd5
   if test "$count" = 1; then
df07cd5
     libc_cv_include_x86_isa_level=yes
df07cd5
+    cat > conftest.c <
df07cd5
+EOF
df07cd5
+    if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c'
df07cd5
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
df07cd5
+  (eval $ac_try) 2>&5
df07cd5
+  ac_status=$?
df07cd5
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
df07cd5
+  test $ac_status = 0; }; } | grep -q "\-msahf"; then
df07cd5
+      libc_cv_have_x86_lahf_sahf=yes
df07cd5
+    fi
df07cd5
+    if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c'
df07cd5
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
df07cd5
+  (eval $ac_try) 2>&5
df07cd5
+  ac_status=$?
df07cd5
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
df07cd5
+  test $ac_status = 0; }; } | grep -q "\-mmovbe"; then
df07cd5
+      libc_cv_have_x86_movbe=yes
df07cd5
+    fi
df07cd5
   fi
df07cd5
 fi
df07cd5
 rm -f conftest*
df07cd5
@@ -144,6 +164,14 @@ $as_echo "$libc_cv_include_x86_isa_level" >&6; }
df07cd5
 if test $libc_cv_include_x86_isa_level = yes; then
df07cd5
   $as_echo "#define INCLUDE_X86_ISA_LEVEL 1" >>confdefs.h
df07cd5
 
df07cd5
+fi
df07cd5
+if test $libc_cv_have_x86_lahf_sahf = yes; then
df07cd5
+  $as_echo "#define HAVE_X86_LAHF_SAHF 1" >>confdefs.h
df07cd5
+
df07cd5
+fi
df07cd5
+if test $libc_cv_have_x86_movbe = yes; then
df07cd5
+  $as_echo "#define HAVE_X86_MOVBE 1" >>confdefs.h
df07cd5
+
df07cd5
 fi
df07cd5
 config_vars="$config_vars
df07cd5
 enable-x86-isa-level = $libc_cv_include_x86_isa_level"
df07cd5
diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac
df07cd5
index f94088f377ec95ab..bca97fdc2f1ac1a7 100644
df07cd5
--- a/sysdeps/x86/configure.ac
df07cd5
+++ b/sysdeps/x86/configure.ac
df07cd5
@@ -98,14 +98,30 @@ cat > conftest2.S <
df07cd5
 4:
df07cd5
 EOF
df07cd5
 libc_cv_include_x86_isa_level=no
df07cd5
+libc_cv_have_x86_lahf_sahf=no
df07cd5
+libc_cv_have_x86_movbe=no
df07cd5
 if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest conftest1.S conftest2.S); then
df07cd5
   count=`LC_ALL=C $READELF -n conftest | grep NT_GNU_PROPERTY_TYPE_0 | wc -l`
df07cd5
   if test "$count" = 1; then
df07cd5
     libc_cv_include_x86_isa_level=yes
df07cd5
+    cat > conftest.c <
df07cd5
+EOF
df07cd5
+    if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c) | grep -q "\-msahf"; then
df07cd5
+      libc_cv_have_x86_lahf_sahf=yes
df07cd5
+    fi
df07cd5
+    if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c) | grep -q "\-mmovbe"; then
df07cd5
+      libc_cv_have_x86_movbe=yes
df07cd5
+    fi
df07cd5
   fi
df07cd5
 fi
df07cd5
 rm -f conftest*])
df07cd5
 if test $libc_cv_include_x86_isa_level = yes; then
df07cd5
   AC_DEFINE(INCLUDE_X86_ISA_LEVEL)
df07cd5
 fi
df07cd5
+if test $libc_cv_have_x86_lahf_sahf = yes; then
df07cd5
+  AC_DEFINE(HAVE_X86_LAHF_SAHF)
df07cd5
+fi
df07cd5
+if test $libc_cv_have_x86_movbe = yes; then
df07cd5
+  AC_DEFINE(HAVE_X86_MOVBE)
df07cd5
+fi
df07cd5
 LIBC_CONFIG_VAR([enable-x86-isa-level], [$libc_cv_include_x86_isa_level])
df07cd5
diff --git a/sysdeps/x86/isa-level.c b/sysdeps/x86/isa-level.c
df07cd5
index aaf524cb56c99cb4..49ef4aa6122072cf 100644
df07cd5
--- a/sysdeps/x86/isa-level.c
df07cd5
+++ b/sysdeps/x86/isa-level.c
df07cd5
@@ -29,32 +29,35 @@
df07cd5
 
df07cd5
 /* ELF program property for x86 ISA level.  */
df07cd5
 #ifdef INCLUDE_X86_ISA_LEVEL
df07cd5
-# if defined __x86_64__ || defined __FXSR__ || !defined _SOFT_FLOAT \
df07cd5
-     || defined  __MMX__ || defined __SSE__ || defined __SSE2__
df07cd5
+# if defined __SSE__ && defined __SSE2__
df07cd5
+/* NB: ISAs, excluding MMX, in x86-64 ISA level baseline are used.  */
df07cd5
 #  define ISA_BASELINE	GNU_PROPERTY_X86_ISA_1_BASELINE
df07cd5
 # else
df07cd5
 #  define ISA_BASELINE	0
df07cd5
 # endif
df07cd5
 
df07cd5
-# if defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 \
df07cd5
-     || (defined __x86_64__ && defined __LAHF_SAHF__) \
df07cd5
-     || defined __POPCNT__ || defined __SSE3__ \
df07cd5
-     || defined __SSSE3__ || defined __SSE4_1__ || defined __SSE4_2__
df07cd5
+# if ISA_BASELINE && defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 \
df07cd5
+     && defined HAVE_X86_LAHF_SAHF && defined __POPCNT__ \
df07cd5
+     && defined __SSE3__ && defined __SSSE3__ && defined __SSE4_1__ \
df07cd5
+     && defined __SSE4_2__
df07cd5
+/* NB: ISAs in x86-64 ISA level v2 are used.  */
df07cd5
 #  define ISA_V2	GNU_PROPERTY_X86_ISA_1_V2
df07cd5
 # else
df07cd5
 #  define ISA_V2	0
df07cd5
 # endif
df07cd5
 
df07cd5
-# if defined __AVX__ || defined __AVX2__ || defined __F16C__ \
df07cd5
-     || defined __FMA__ || defined __LZCNT__ || defined __MOVBE__ \
df07cd5
-     || defined __XSAVE__
df07cd5
+# if ISA_V2 && defined __AVX__ && defined __AVX2__ && defined __F16C__ \
df07cd5
+     && defined __FMA__ && defined __LZCNT__ && defined HAVE_X86_MOVBE
df07cd5
+/* NB: ISAs in x86-64 ISA level v3 are used.  */
df07cd5
 #  define ISA_V3	GNU_PROPERTY_X86_ISA_1_V3
df07cd5
 # else
df07cd5
 #  define ISA_V3	0
df07cd5
 # endif
df07cd5
 
df07cd5
-# if defined __AVX512F__ || defined __AVX512BW__ || defined __AVX512CD__ \
df07cd5
-     || defined __AVX512DQ__ || defined __AVX512VL__
df07cd5
+# if ISA_V3 && defined __AVX512F__ && defined __AVX512BW__ \
df07cd5
+     && defined __AVX512CD__ && defined __AVX512DQ__ \
df07cd5
+     && defined __AVX512VL__
df07cd5
+/* NB: ISAs in x86-64 ISA level v4 are used.  */
df07cd5
 #  define ISA_V4	GNU_PROPERTY_X86_ISA_1_V4
df07cd5
 # else
df07cd5
 #  define ISA_V4	0