public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: "H.J. Lu" <hjl.tools@gmail.com>
To: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Cc: GNU C Library <libc-alpha@sourceware.org>,
	Florian Weimer <fweimer@redhat.com>
Subject: Re: V6 [PATCH 1/2] x86: Support GNU_PROPERTY_X86_ISA_1_V[234] marker [BZ #26717]
Date: Thu, 7 Jan 2021 12:58:27 -0800	[thread overview]
Message-ID: <CAMe9rOoQFRKJuoDcMEwo5+YrtrQ4rjNiK9A52AYhCi0wtDojjQ@mail.gmail.com> (raw)
In-Reply-To: <c2f1b233-731a-f1f0-d4fd-a36178c2f0c0@linaro.org>

[-- Attachment #1: Type: text/plain, Size: 49804 bytes --]

On Thu, Jan 7, 2021 at 12:09 PM Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 06/01/2021 14:11, H.J. Lu wrote:
> > Here is the updated patch.  Tested under i686, x32 and x86-64 modes
> > on x86-64-v2, x86-64-v3 and x86-64-v4 machines.
> >
> > OK for master?
> >
> > Thanks.
> >
>
> LGTM with just two clarification below.
>
> Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
>
> > From 6630e06f9bcb361177d46c277cf8e67cbd722429 Mon Sep 17 00:00:00 2001
> > From: "H.J. Lu" <hjl.tools@gmail.com>
> > Date: Fri, 9 Oct 2020 06:06:56 -0700
> > Subject: [PATCH] x86: Support GNU_PROPERTY_X86_ISA_1_V[234] marker [BZ #26717]
> >
> > GCC 11 supports -march=x86-64-v[234] to enable x86 micro-architecture ISA
> > levels:
> >
> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97250
> >
> > and -mneeded to emit GNU_PROPERTY_X86_ISA_1_NEEDED property with
> > GNU_PROPERTY_X86_ISA_1_V[234] marker:
> >
> > https://gitlab.com/x86-psABIs/x86-64-ABI/-/merge_requests/13
> >
> > Binutils support for GNU_PROPERTY_X86_ISA_1_V[234] marker were added by
> >
> > commit b0ab06937385e0ae25cebf1991787d64f439bf12
> > Author: H.J. Lu <hjl.tools@gmail.com>
> > Date:   Fri Oct 30 06:49:57 2020 -0700
> >
> >     x86: Support GNU_PROPERTY_X86_ISA_1_BASELINE marker
> >
> > and
> >
> > commit 32930e4edbc06bc6f10c435dbcc63131715df678
> > Author: H.J. Lu <hjl.tools@gmail.com>
> > Date:   Fri Oct 9 05:05:57 2020 -0700
> >
> >     x86: Support GNU_PROPERTY_X86_ISA_1_V[234] marker
> >
> > GNU_PROPERTY_X86_ISA_1_NEEDED property in x86 ELF binaries indicate the
> > micro-architecture ISA level required to execute the binary.  The marker
> > must be added by programmers explicitly in one of 3 ways:
> >
> > 1. Pass -mneeded to GCC.
> > 2. Add the marker in the linker inputs as this patch does.
> > 3. Pass -z x86-64-v[234] to the linker.
> >
> > Add GNU_PROPERTY_X86_ISA_1_BASELINE and GNU_PROPERTY_X86_ISA_1_V[234]
> > marker support to ld.so if binutils 2.32 or newer is used to build glibc:
> >
> > 1. Add GNU_PROPERTY_X86_ISA_1_BASELINE and GNU_PROPERTY_X86_ISA_1_V[234]
> > markers to elf.h.
> > 2. Add GNU_PROPERTY_X86_ISA_1_BASELINE and GNU_PROPERTY_X86_ISA_1_V[234]
> > marker to abi-note.o based on the ISA level used to compile abi-note.o,
> > assuming that the same ISA level is used to compile the whole glibc.
> > 3. Add isa_1 to cpu_features to record the supported x86 ISA level.
> > 4. Rename _dl_process_cet_property_note to _dl_process_property_note and
> > add GNU_PROPERTY_X86_ISA_1_V[234] marker detection.
> > 5. Update _rtld_main_check and _dl_open_check to check loaded objects
> > with the incompatible ISA level.
> > 6. Add a testcase to verify that dlopen an x86-64-v4 shared object fails
> > on lesser platforms.
> > 7. Use <get-isa-level.h> in dl-hwcaps-subdirs.c and tst-glibc-hwcaps.c.
> >
> > Tested under i686, x32 and x86-64 modes on x86-64-v2, x86-64-v3 and
> > x86-64-v4 machines.
> >
> > Marked elf/tst-isa-level-1 with x86-64-v4, ran it on x86-64-v3 machine
> > and got:
> >
> > [hjl@gnu-cfl-2 build-x86_64-linux]$ ./elf/tst-isa-level-1
> > ./elf/tst-isa-level-1: CPU ISA level is lower than required
> > [hjl@gnu-cfl-2 build-x86_64-linux]$
> > ---
> >  config.h.in                                |   3 +
> >  elf/elf.h                                  |  35 +++----
> >  sysdeps/x86/Makefile                       |  30 ++++++
> >  sysdeps/x86/abi-note.c                     |  29 ++++++
> >  sysdeps/x86/configure                      |  79 ++++++++++++++
> >  sysdeps/x86/configure.ac                   |  66 ++++++++++++
> >  sysdeps/x86/cpu-features.c                 |   3 +
> >  sysdeps/x86/dl-cet.c                       |  12 ++-
> >  sysdeps/x86/dl-prop.h                      | 113 +++++++++++++++------
> >  sysdeps/x86/get-isa-level.h                |  66 ++++++++++++
> >  sysdeps/x86/include/cpu-features.h         |   2 +
> >  sysdeps/x86/isa-level.c                    |  97 ++++++++++++++++++
> >  sysdeps/x86/link_map.h                     |  18 ++--
> >  sysdeps/x86/tst-isa-level-1.c              | 104 +++++++++++++++++++
> >  sysdeps/x86/tst-isa-level-mod-1-baseline.c |   1 +
> >  sysdeps/x86/tst-isa-level-mod-1-v2.c       |   1 +
> >  sysdeps/x86/tst-isa-level-mod-1-v3.c       |   1 +
> >  sysdeps/x86/tst-isa-level-mod-1-v4.c       |   1 +
> >  sysdeps/x86/tst-isa-level-mod-1.c          |  25 +++++
> >  sysdeps/x86_64/dl-hwcaps-subdirs.c         |  30 ++----
> >  sysdeps/x86_64/tst-glibc-hwcaps.c          |  41 ++------
> >  21 files changed, 644 insertions(+), 113 deletions(-)
> >  create mode 100644 sysdeps/x86/abi-note.c
> >  create mode 100644 sysdeps/x86/get-isa-level.h
> >  create mode 100644 sysdeps/x86/isa-level.c
> >  create mode 100644 sysdeps/x86/tst-isa-level-1.c
> >  create mode 100644 sysdeps/x86/tst-isa-level-mod-1-baseline.c
> >  create mode 100644 sysdeps/x86/tst-isa-level-mod-1-v2.c
> >  create mode 100644 sysdeps/x86/tst-isa-level-mod-1-v3.c
> >  create mode 100644 sysdeps/x86/tst-isa-level-mod-1-v4.c
> >  create mode 100644 sysdeps/x86/tst-isa-level-mod-1.c
> >
> > diff --git a/config.h.in b/config.h.in
> > index eca2d66a2c..947feeff36 100644
> > --- a/config.h.in
> > +++ b/config.h.in
> > @@ -269,4 +269,7 @@
> >  /* The default value of x86 CET control.  */
> >  #define DEFAULT_DL_X86_CET_CONTROL cet_elf_property
> >
> > +/* Define if x86 ISA level should be included in shared libraries.  */
> > +#undef INCLUDE_X86_ISA_LEVEL
> > +
> >  #endif
> > diff --git a/elf/elf.h b/elf/elf.h
>
> Ok.
>
> > index 4a9ae97dfc..9ebd052c8a 100644
> > --- a/elf/elf.h
> > +++ b/elf/elf.h
> > @@ -1324,31 +1324,26 @@ typedef struct
> >
> >  /* The x86 instruction sets indicated by the corresponding bits are
> >     used in program.  Their support in the hardware is optional.  */
> > -#define GNU_PROPERTY_X86_ISA_1_USED          0xc0000000
> > +#define GNU_PROPERTY_X86_ISA_1_USED          0xc0010002
> >  /* The x86 instruction sets indicated by the corresponding bits are
> >     used in program and they must be supported by the hardware.   */
> > -#define GNU_PROPERTY_X86_ISA_1_NEEDED                0xc0000001
> > +#define GNU_PROPERTY_X86_ISA_1_NEEDED                0xc0008002
> >  /* X86 processor-specific features used in program.  */
> >  #define GNU_PROPERTY_X86_FEATURE_1_AND               0xc0000002
> >
> > -#define GNU_PROPERTY_X86_ISA_1_486           (1U << 0)
> > -#define GNU_PROPERTY_X86_ISA_1_586           (1U << 1)
> > -#define GNU_PROPERTY_X86_ISA_1_686           (1U << 2)
> > -#define GNU_PROPERTY_X86_ISA_1_SSE           (1U << 3)
> > -#define GNU_PROPERTY_X86_ISA_1_SSE2          (1U << 4)
> > -#define GNU_PROPERTY_X86_ISA_1_SSE3          (1U << 5)
> > -#define GNU_PROPERTY_X86_ISA_1_SSSE3         (1U << 6)
> > -#define GNU_PROPERTY_X86_ISA_1_SSE4_1                (1U << 7)
> > -#define GNU_PROPERTY_X86_ISA_1_SSE4_2                (1U << 8)
> > -#define GNU_PROPERTY_X86_ISA_1_AVX           (1U << 9)
> > -#define GNU_PROPERTY_X86_ISA_1_AVX2          (1U << 10)
> > -#define GNU_PROPERTY_X86_ISA_1_AVX512F               (1U << 11)
> > -#define GNU_PROPERTY_X86_ISA_1_AVX512CD              (1U << 12)
> > -#define GNU_PROPERTY_X86_ISA_1_AVX512ER              (1U << 13)
> > -#define GNU_PROPERTY_X86_ISA_1_AVX512PF              (1U << 14)
> > -#define GNU_PROPERTY_X86_ISA_1_AVX512VL              (1U << 15)
> > -#define GNU_PROPERTY_X86_ISA_1_AVX512DQ              (1U << 16)
> > -#define GNU_PROPERTY_X86_ISA_1_AVX512BW              (1U << 17)
> > +/* GNU_PROPERTY_X86_ISA_1_BASELINE: CMOV, CX8 (cmpxchg8b), FPU (fld),
> > +   MMX, OSFXSR (fxsave), SCE (syscall), SSE and SSE2.  */
> > +#define GNU_PROPERTY_X86_ISA_1_BASELINE              (1U << 0)
> > +/* GNU_PROPERTY_X86_ISA_1_V2: GNU_PROPERTY_X86_ISA_1_BASELINE,
> > +   CMPXCHG16B (cmpxchg16b), LAHF-SAHF (lahf), POPCNT (popcnt), SSE3,
> > +   SSSE3, SSE4.1 and SSE4.2.  */
> > +#define GNU_PROPERTY_X86_ISA_1_V2            (1U << 1)
> > +/* GNU_PROPERTY_X86_ISA_1_V3: GNU_PROPERTY_X86_ISA_1_V2, AVX, AVX2, BMI1,
> > +   BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE.  */
> > +#define GNU_PROPERTY_X86_ISA_1_V3            (1U << 2)
> > +/* GNU_PROPERTY_X86_ISA_1_V4: GNU_PROPERTY_X86_ISA_1_V3, AVX512F,
> > +   AVX512BW, AVX512CD, AVX512DQ and AVX512VL.  */
> > +#define GNU_PROPERTY_X86_ISA_1_V4            (1U << 3)
> >
> >  /* This indicates that all executable sections are compatible with
> >     IBT.  */
>
> Ok.
>
> > diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
> > index 081cc72e93..c814d5a195 100644
> > --- a/sysdeps/x86/Makefile
> > +++ b/sysdeps/x86/Makefile
> > @@ -9,6 +9,36 @@ sysdep_headers += sys/platform/x86.h
> >  tests += tst-get-cpu-features tst-get-cpu-features-static \
> >        tst-cpu-features-cpuinfo tst-cpu-features-supports
> >  tests-static += tst-get-cpu-features-static
> > +ifeq (yes,$(enable-x86-isa-level))
> > +tests += tst-isa-level-1
> > +modules-names += tst-isa-level-mod-1-baseline \
> > +              tst-isa-level-mod-1-v2 \
> > +              tst-isa-level-mod-1-v3 \
> > +              tst-isa-level-mod-1-v4 \
> > +
> > +# X86 ISA level baseline
> > +CFLAGS-tst-isa-level-mod-1-baseline.c += -DINCLUDE_X86_ISA_LEVEL \
> > +                                      -DISA_LEVEL=0x1 \
> > +                                      -march=x86-64
> > +# X86 ISA level v2
> > +CFLAGS-tst-isa-level-mod-1-v2.c += -DINCLUDE_X86_ISA_LEVEL \
> > +                                -DISA_LEVEL=0x3 \
> > +                                -march=x86-64
> > +# X86 ISA level v3
> > +CFLAGS-tst-isa-level-mod-1-v3.c += -DINCLUDE_X86_ISA_LEVEL \
> > +                                -DISA_LEVEL=0x7 \
> > +                                -march=x86-64
> > +# X86 ISA level v4
> > +CFLAGS-tst-isa-level-mod-1-v4.c += -DINCLUDE_X86_ISA_LEVEL \
> > +                                -DISA_LEVEL=0xf \
> > +                                -march=x86-64
> > +
> > +$(objpfx)tst-isa-level-1: $(libdl)
> > +$(objpfx)tst-isa-level-1.out: $(objpfx)tst-isa-level-mod-1-baseline.so \
> > +                           $(objpfx)tst-isa-level-mod-1-v2.so \
> > +                           $(objpfx)tst-isa-level-mod-1-v3.so \
> > +                           $(objpfx)tst-isa-level-mod-1-v4.so
> > +endif
> >  endif
> >
> >  ifeq ($(subdir),math)
>
> Ok.
>
> > diff --git a/sysdeps/x86/abi-note.c b/sysdeps/x86/abi-note.c
> > new file mode 100644
> > index 0000000000..5140e6ab47
> > --- /dev/null
> > +++ b/sysdeps/x86/abi-note.c
> > @@ -0,0 +1,29 @@
> > +/* Special .init and .fini section support.  x86-64 version.
> > +   Copyright (C) 2020 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   In addition to the permissions in the GNU Lesser General Public
> > +   License, the Free Software Foundation gives you unlimited
> > +   permission to link the compiled version of this file with other
> > +   programs, and to distribute those programs without any restriction
> > +   coming from the use of this file.  (The Lesser General Public
> > +   License restrictions do apply in other respects; for example, they
> > +   cover modification of the file, and distribution when not linked
> > +   into another program.)
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#include <isa-level.c>
> > +#include <csu/abi-note.c>
>
> Ok.
>
> > diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure
> > index 81cc4e80d6..5e32dc62b3 100644
> > --- a/sysdeps/x86/configure
> > +++ b/sysdeps/x86/configure
> > @@ -68,3 +68,82 @@ elif test $enable_cet = permissive; then
> >  fi
> >  config_vars="$config_vars
> >  enable-cet = $enable_cet"
> > +
> > +# Check if linker supports x86 ISA level.
> > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker x86 ISA level support" >&5
> > +$as_echo_n "checking for linker x86 ISA level support... " >&6; }
> > +if ${libc_cv_include_x86_isa_level+:} false; then :
> > +  $as_echo_n "(cached) " >&6
> > +else
> > +  cat > conftest1.S <<EOF
> > +#ifdef __LP64__
> > +# define P2ALIGN 3
> > +#else
> > +# define P2ALIGN 2
> > +#endif
> > +     .section ".note.gnu.property", "a"
> > +     .p2align P2ALIGN
> > +     .long 1f - 0f           /* name length.  */
> > +     .long 4f - 1f           /* data length.  */
> > +     /* NT_GNU_PROPERTY_TYPE_0 */
> > +     .long 5                 /* note type.  */
> > +0:
> > +     .asciz "GNU"            /* vendor name.  */
> > +1:
> > +     .p2align P2ALIGN
> > +     /* GNU_PROPERTY_X86_ISA_1_NEEDED */
> > +     .long 0xc0008002        /* pr_type.  */
> > +     .long 3f - 2f           /* pr_datasz.  */
> > +2:
> > +     .long 0x1
> > +3:
> > +     .p2align P2ALIGN
> > +4:
> > +EOF
> > +cat > conftest2.S <<EOF
> > +#ifdef __LP64__
> > +# define P2ALIGN 3
> > +#else
> > +# define P2ALIGN 2
> > +#endif
> > +     .section ".note.gnu.property", "a"
> > +     .p2align P2ALIGN
> > +     .long 1f - 0f           /* name length.  */
> > +     .long 4f - 1f           /* data length.  */
> > +     /* NT_GNU_PROPERTY_TYPE_0 */
> > +     .long 5                 /* note type.  */
> > +0:
> > +     .asciz "GNU"            /* vendor name.  */
> > +1:
> > +     .p2align P2ALIGN
> > +     /* GNU_PROPERTY_X86_ISA_1_NEEDED */
> > +     .long 0xc0008002        /* pr_type.  */
> > +     .long 3f - 2f           /* pr_datasz.  */
> > +2:
> > +     .long 0x2
> > +3:
> > +     .p2align P2ALIGN
> > +4:
> > +EOF
> > +libc_cv_include_x86_isa_level=no
> > +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest conftest1.S conftest2.S'
> > +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
> > +  (eval $ac_try) 2>&5
> > +  ac_status=$?
> > +  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> > +  test $ac_status = 0; }; }; then
> > +  count=`LC_ALL=C $READELF -n conftest | grep NT_GNU_PROPERTY_TYPE_0 | wc -l`
> > +  if test "$count" = 1; then
> > +    libc_cv_include_x86_isa_level=yes
> > +  fi
> > +fi
> > +rm -f conftest*
> > +fi
> > +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_include_x86_isa_level" >&5
> > +$as_echo "$libc_cv_include_x86_isa_level" >&6; }
> > +if test $libc_cv_include_x86_isa_level = yes; then
> > +  $as_echo "#define INCLUDE_X86_ISA_LEVEL 1" >>confdefs.h
> > +
> > +fi
> > +config_vars="$config_vars
> > +enable-x86-isa-level = $libc_cv_include_x86_isa_level"
> > diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac
> > index 8f3e1191f6..f94088f377 100644
> > --- a/sysdeps/x86/configure.ac
> > +++ b/sysdeps/x86/configure.ac
> > @@ -43,3 +43,69 @@ elif test $enable_cet = permissive; then
> >    AC_DEFINE(DEFAULT_DL_X86_CET_CONTROL, cet_permissive)
> >  fi
> >  LIBC_CONFIG_VAR([enable-cet], [$enable_cet])
> > +
> > +# Check if linker supports x86 ISA level.
> > +AC_CACHE_CHECK([for linker x86 ISA level support],
> > +            libc_cv_include_x86_isa_level, [dnl
> > +cat > conftest1.S <<EOF
> > +#ifdef __LP64__
> > +# define P2ALIGN 3
> > +#else
> > +# define P2ALIGN 2
> > +#endif
> > +     .section ".note.gnu.property", "a"
> > +     .p2align P2ALIGN
> > +     .long 1f - 0f           /* name length.  */
> > +     .long 4f - 1f           /* data length.  */
> > +     /* NT_GNU_PROPERTY_TYPE_0 */
> > +     .long 5                 /* note type.  */
> > +0:
> > +     .asciz "GNU"            /* vendor name.  */
> > +1:
> > +     .p2align P2ALIGN
> > +     /* GNU_PROPERTY_X86_ISA_1_NEEDED */
> > +     .long 0xc0008002        /* pr_type.  */
> > +     .long 3f - 2f           /* pr_datasz.  */
> > +2:
> > +     .long 0x1
> > +3:
> > +     .p2align P2ALIGN
> > +4:
> > +EOF
> > +cat > conftest2.S <<EOF
> > +#ifdef __LP64__
> > +# define P2ALIGN 3
> > +#else
> > +# define P2ALIGN 2
> > +#endif
> > +     .section ".note.gnu.property", "a"
> > +     .p2align P2ALIGN
> > +     .long 1f - 0f           /* name length.  */
> > +     .long 4f - 1f           /* data length.  */
> > +     /* NT_GNU_PROPERTY_TYPE_0 */
> > +     .long 5                 /* note type.  */
> > +0:
> > +     .asciz "GNU"            /* vendor name.  */
> > +1:
> > +     .p2align P2ALIGN
> > +     /* GNU_PROPERTY_X86_ISA_1_NEEDED */
> > +     .long 0xc0008002        /* pr_type.  */
> > +     .long 3f - 2f           /* pr_datasz.  */
> > +2:
> > +     .long 0x2
> > +3:
> > +     .p2align P2ALIGN
> > +4:
> > +EOF
> > +libc_cv_include_x86_isa_level=no
> > +if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest conftest1.S conftest2.S); then
> > +  count=`LC_ALL=C $READELF -n conftest | grep NT_GNU_PROPERTY_TYPE_0 | wc -l`
> > +  if test "$count" = 1; then
> > +    libc_cv_include_x86_isa_level=yes
> > +  fi
> > +fi
> > +rm -f conftest*])
> > +if test $libc_cv_include_x86_isa_level = yes; then
> > +  AC_DEFINE(INCLUDE_X86_ISA_LEVEL)
> > +fi
> > +LIBC_CONFIG_VAR([enable-x86-isa-level], [$libc_cv_include_x86_isa_level])
>
> Skipping autogenerated file.
>
> > diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
> > index 529c586193..e7da682a2e 100644
> > --- a/sysdeps/x86/cpu-features.c
> > +++ b/sysdeps/x86/cpu-features.c
> > @@ -19,6 +19,7 @@
> >  #include <cpuid.h>
> >  #include <dl-hwcap.h>
> >  #include <libc-pointer-arith.h>
> > +#include <get-isa-level.h>
> >  #if IS_IN (libc) && !defined SHARED
> >  # include <assert.h>
> >  # include <unistd.h>
> > @@ -290,6 +291,8 @@ update_usable (struct cpu_features *cpu_features)
> >        CPU_FEATURE_SET_USABLE (cpu_features, KL);
> >        CPU_FEATURE_SET_USABLE (cpu_features, WIDE_KL);
> >      }
> > +
> > +  cpu_features->isa_1 = get_isa_level (cpu_features);
> >  }
> >
> >  static void
>
> Ok.
>
> > diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c
> > index b4910f7634..ed7fd6d10d 100644
> > --- a/sysdeps/x86/dl-cet.c
> > +++ b/sysdeps/x86/dl-cet.c
> > @@ -76,10 +76,12 @@ dl_cet_check (struct link_map *m, const char *program)
> >          */
> >         enable_ibt &= (HAS_CPU_FEATURE (IBT)
> >                        && (enable_ibt_type == cet_always_on
> > -                          || (m->l_cet & lc_ibt) != 0));
> > +                          || (m->l_x86_feature_1_and
> > +                              & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0));
> >         enable_shstk &= (HAS_CPU_FEATURE (SHSTK)
> >                          && (enable_shstk_type == cet_always_on
> > -                            || (m->l_cet & lc_shstk) != 0));
> > +                            || (m->l_x86_feature_1_and
> > +                                & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0));
> >       }
> >
> >        /* ld.so is CET-enabled by kernel.  But shared objects may not
>
> Ok.
>
> > @@ -111,7 +113,8 @@ dl_cet_check (struct link_map *m, const char *program)
> >             /* IBT is enabled only if it is enabled in executable as
> >                well as all shared objects.  */
> >             enable_ibt &= (enable_ibt_type == cet_always_on
> > -                          || (l->l_cet & lc_ibt) != 0);
> > +                          || (l->l_x86_feature_1_and
> > +                              & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0);
> >             if (!found_ibt_legacy && enable_ibt != ibt_enabled)
> >               {
> >                 found_ibt_legacy = true;
> > @@ -121,7 +124,8 @@ dl_cet_check (struct link_map *m, const char *program)
> >             /* SHSTK is enabled only if it is enabled in executable as
> >                well as all shared objects.  */
> >             enable_shstk &= (enable_shstk_type == cet_always_on
> > -                            || (l->l_cet & lc_shstk) != 0);
> > +                            || (l->l_x86_feature_1_and
> > +                                & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0);
> >             if (enable_shstk != shstk_enabled)
> >               {
> >                 found_shstk_legacy = true;
>
> Ok.
>
> > diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h
> > index ce1667dc7a..56bd020b3c 100644
> > --- a/sysdeps/x86/dl-prop.h
> > +++ b/sysdeps/x86/dl-prop.h
> > @@ -19,14 +19,54 @@
> >  #ifndef _DL_PROP_H
> >  #define _DL_PROP_H
> >
> > +#include <libintl.h>
> > +
> >  extern void _dl_cet_check (struct link_map *, const char *)
> >      attribute_hidden;
> >  extern void _dl_cet_open_check (struct link_map *)
> >      attribute_hidden;
> >
> > +static void
> > +dl_isa_level_check (struct link_map *m, const char *program)
> > +{
> > +  const struct cpu_features *cpu_features = __get_cpu_features ();
> > +  unsigned int i;
> > +  struct link_map *l;
> > +
> > +  i = m->l_searchlist.r_nlist;
> > +  while (i-- > 0)
> > +    {
> > +      /* Check each shared object to see if ISA level is compatible.  */
> > +      l = m->l_initfini[i];
> > +
> > +      /* Skip ISA level check if functions have been executed.  */
> > +      if (l->l_init_called)
> > +     continue;
> > +
> > +#ifdef SHARED
> > +      /* Skip ISA level check for ld.so since ld.so won't run if its ISA
> > +      level is higher than CPU.  */
> > +      if (l == &GL(dl_rtld_map) || l->l_real == &GL(dl_rtld_map))
> > +     continue;
> > +#endif
> > +
> > +      if ((l->l_x86_isa_1_needed & cpu_features->isa_1)
> > +       != l->l_x86_isa_1_needed)
> > +     {
> > +       if (program)
> > +         _dl_fatal_printf ("%s: CPU ISA level is lower than required\n",
> > +                           *l->l_name != '\0' ? l->l_name : program);
> > +       else
> > +         _dl_signal_error (0, l->l_name, "dlopen",
> > +                           N_("CPU ISA level is lower than required"));
> > +     }
> > +    }
> > +}
> > +
>
> Ok.
>
> >  static inline void __attribute__ ((always_inline))
> >  _rtld_main_check (struct link_map *m, const char *program)
> >  {
> > +  dl_isa_level_check (m, program);
> >  #if CET_ENABLED
> >    _dl_cet_check (m, program);
> >  #endif
> > @@ -35,20 +75,18 @@ _rtld_main_check (struct link_map *m, const char *program)
> >  static inline void __attribute__ ((always_inline))
> >  _dl_open_check (struct link_map *m)
> >  {
> > +  dl_isa_level_check (m, NULL);
> >  #if CET_ENABLED
> >    _dl_cet_open_check (m);
> >  #endif
> >  }
> >
> >  static inline void __attribute__ ((unused))
> > -_dl_process_cet_property_note (struct link_map *l,
> > -                           const ElfW(Nhdr) *note,
> > -                           const ElfW(Addr) size,
> > -                           const ElfW(Addr) align)
> > +_dl_process_property_note (struct link_map *l, const ElfW(Nhdr) *note,
> > +                        const ElfW(Addr) size, const ElfW(Addr) align)
> >  {
> > -#if CET_ENABLED
> >    /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before.  */
> > -  if (l->l_cet != lc_unknown)
> > +  if (l->l_property != lc_property_unknown)
> >      return;
> >
> >    /* The NT_GNU_PROPERTY_TYPE_0 note must be aliged to 4 bytes in
>
> Ok.
>
> > @@ -59,7 +97,8 @@ _dl_process_cet_property_note (struct link_map *l,
> >
> >    const ElfW(Addr) start = (ElfW(Addr)) note;
> >
> > -  unsigned int feature_1 = 0;
> > +  unsigned int feature_1_and = 0;
> > +  unsigned int isa_1_needed = 0;
> >    unsigned int last_type = 0;
> >
> >    while ((ElfW(Addr)) (note + 1) - start < size)
> > @@ -71,11 +110,11 @@ _dl_process_cet_property_note (struct link_map *l,
> >       {
> >         /* Stop if we see more than one GNU property note which may
> >            be generated by the older linker.  */
> > -       if (l->l_cet != lc_unknown)
> > +       if (l->l_property != lc_property_unknown)
> >           return;
> >
> > -       /* Check CET status now.  */
> > -       l->l_cet = lc_none;
> > +       /* Check CET status and ISA levels now.  */
> > +       l->l_property = lc_property_none;
> >
> >         /* Check for invalid property.  */
> >         if (note->n_descsz < 8
> > @@ -101,26 +140,37 @@ _dl_process_cet_property_note (struct link_map *l,
> >
> >             last_type = type;
> >
> > -           if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
> > +           if (type == GNU_PROPERTY_X86_FEATURE_1_AND
> > +               || type == GNU_PROPERTY_X86_ISA_1_NEEDED)
> >               {
> > -               /* The size of GNU_PROPERTY_X86_FEATURE_1_AND is 4
> > -                  bytes.  When seeing GNU_PROPERTY_X86_FEATURE_1_AND,
> > -                  we stop the search regardless if its size is correct
> > -                  or not.  There is no point to continue if this note
> > -                  is ill-formed.  */
> > +               /* The sizes of types which we are searching for are
> > +                  4 bytes.  There is no point to continue if this
> > +                  note is ill-formed.  */
> >                 if (datasz != 4)
> >                   return;
> >
> > -               feature_1 = *(unsigned int *) ptr;
> > -
> > -               /* Keep searching for the next GNU property note
> > -                  generated by the older linker.  */
> > -               break;
> > +               /* NB: Stop the scan only after seeing all types which
> > +                  we are searching for.  */
> > +               _Static_assert ((GNU_PROPERTY_X86_ISA_1_NEEDED >
> > +                                GNU_PROPERTY_X86_FEATURE_1_AND),
> > +                               "GNU_PROPERTY_X86_ISA_1_NEEDED > "
> > +                               "GNU_PROPERTY_X86_FEATURE_1_AND");
> > +               if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
> > +                 feature_1_and = *(unsigned int *) ptr;
> > +               else
> > +                 {
> > +                   isa_1_needed = *(unsigned int *) ptr;
> > +
> > +                   /* Keep searching for the next GNU property note
> > +                      generated by the older linker.  */
> > +                   break;
> > +                 }
> >               }
> > -           else if (type > GNU_PROPERTY_X86_FEATURE_1_AND)
> > +           else if (type > GNU_PROPERTY_X86_ISA_1_NEEDED)
> >               {
> > -               /* Stop since property type is in ascending order.  */
> > -               return;
> > +               /* Stop the scan since property type is in ascending
> > +                  order.  */
> > +               break;
> >               }
> >
> >             /* Check the next property item.  */
>
> Ok.
>
> > @@ -137,18 +187,21 @@ _dl_process_cet_property_note (struct link_map *l,
> >      }
> >
> >    /* We get here only if there is one or no GNU property note.  */
> > -  if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT))
> > -    l->l_cet |= lc_ibt;
> > -  if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
> > -    l->l_cet |= lc_shstk;
> > -#endif
> > +  if (isa_1_needed != 0 || feature_1_and != 0)
> > +    {
> > +      l->l_property = lc_property_valid;
> > +      l->l_x86_isa_1_needed = isa_1_needed;
> > +      l->l_x86_feature_1_and = feature_1_and;
> > +    }
> > +  else
> > +    l->l_property = lc_property_none;
> >  }
> >
> >  static inline void __attribute__ ((unused))
> >  _dl_process_pt_note (struct link_map *l, int fd, const ElfW(Phdr) *ph)
> >  {
> >    const ElfW(Nhdr) *note = (const void *) (ph->p_vaddr + l->l_addr);
> > -  _dl_process_cet_property_note (l, note, ph->p_memsz, ph->p_align);
> > +  _dl_process_property_note (l, note, ph->p_memsz, ph->p_align);
> >  }
> >
> >  static inline int __attribute__ ((always_inline))
>
> Ok.
>
> > diff --git a/sysdeps/x86/get-isa-level.h b/sysdeps/x86/get-isa-level.h
> > new file mode 100644
> > index 0000000000..a86e1e8941
> > --- /dev/null
> > +++ b/sysdeps/x86/get-isa-level.h
> > @@ -0,0 +1,66 @@
> > +/* Get x86 ISA level.
> > +   This file is part of the GNU C Library.
> > +   Copyright (C) 2020 Free Software Foundation, Inc.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#include <sys/platform/x86.h>
> > +
> > +/* Get GNU_PROPERTY_X86_ISA_1_BASELINE and GNU_PROPERTY_X86_ISA_1_V[234]
> > +   ISA level.  */
> > +
> > +static unsigned int
> > +get_isa_level (const struct cpu_features *cpu_features)
> > +{
> > +  unsigned int isa_level = 0;
> > +
> > +  if (CPU_FEATURE_USABLE_P (cpu_features, CMOV)
> > +      && CPU_FEATURE_USABLE_P (cpu_features, CX8)
> > +      && CPU_FEATURE_CPU_P (cpu_features, FPU)
> > +      && CPU_FEATURE_USABLE_P (cpu_features, FXSR)
> > +      && CPU_FEATURE_USABLE_P (cpu_features, MMX)
> > +      && CPU_FEATURE_USABLE_P (cpu_features, SSE)
> > +      && CPU_FEATURE_USABLE_P (cpu_features, SSE2))
> > +    {
> > +      isa_level = GNU_PROPERTY_X86_ISA_1_BASELINE;
> > +      if (CPU_FEATURE_USABLE_P (cpu_features, CMPXCHG16B)
> > +       && CPU_FEATURE_USABLE_P (cpu_features, LAHF64_SAHF64)
> > +       && CPU_FEATURE_USABLE_P (cpu_features, POPCNT)
> > +       && CPU_FEATURE_USABLE_P (cpu_features, SSE3)
> > +       && CPU_FEATURE_USABLE_P (cpu_features, SSSE3)
> > +       && CPU_FEATURE_USABLE_P (cpu_features, SSE4_1)
> > +       && CPU_FEATURE_USABLE_P (cpu_features, SSE4_2))
> > +     {
> > +       isa_level |= GNU_PROPERTY_X86_ISA_1_V2;
> > +       if (CPU_FEATURE_USABLE_P (cpu_features, AVX)
> > +           && CPU_FEATURE_USABLE_P (cpu_features, AVX2)
> > +           && CPU_FEATURE_USABLE_P (cpu_features, F16C)
> > +           && CPU_FEATURE_USABLE_P (cpu_features, FMA)
> > +           && CPU_FEATURE_USABLE_P (cpu_features, LZCNT)
> > +           && CPU_FEATURE_USABLE_P (cpu_features, MOVBE))
> > +         {
> > +           isa_level |= GNU_PROPERTY_X86_ISA_1_V3;
> > +           if (CPU_FEATURE_USABLE_P (cpu_features, AVX512F)
> > +               && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW)
> > +               && CPU_FEATURE_USABLE_P (cpu_features, AVX512CD)
> > +               && CPU_FEATURE_USABLE_P (cpu_features, AVX512DQ)
> > +               && CPU_FEATURE_USABLE_P (cpu_features, AVX512VL))
> > +             isa_level |= GNU_PROPERTY_X86_ISA_1_V4;
> > +         }
> > +     }
> > +    }
> > +
> > +  return isa_level;
> > +}
>
> Ok, is there any plan to add the gcc ISA_1_VX for 32-bit ABI as well? I am
> asking because if there is no upcoming plan maybe an option is just to
> return 0 for !__X86_64__.

Although there is no official plan to support it in 32-bit,  since the ISA level
support implemented in GCC and binutils is independent of 32-bit or 64-bit,
32-bit also get the same feature:

[hjl@gnu-cfl-2 tmp]$ touch x.c
[hjl@gnu-cfl-2 tmp]$ /usr/gcc-11.0.0-x32/bin/gcc -c -mneeded x.c -mavx2
[hjl@gnu-cfl-2 tmp]$ readelf -n x.o

Displaying notes found in: .note.gnu.property
  Owner                Data size Description
  GNU                  0x00000010 NT_GNU_PROPERTY_TYPE_0
      Properties: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3
  GNU                  0x00000020 NT_GNU_PROPERTY_TYPE_0
      Properties: x86 ISA used:
x86 feature used: x86
[hjl@gnu-cfl-2 tmp]$ /usr/gcc-11.0.0-x32/bin/gcc -c -mneeded x.c -mavx2 -m32
[hjl@gnu-cfl-2 tmp]$ readelf -n x.o

Displaying notes found in: .note.gnu.property
  Owner                Data size Description
  GNU                  0x0000000c NT_GNU_PROPERTY_TYPE_0
      Properties: x86 ISA needed: x86-64-baseline, x86-64-v2, x86-64-v3
  GNU                  0x00000018 NT_GNU_PROPERTY_TYPE_0
      Properties: x86 ISA used:
x86 feature used: x86
[hjl@gnu-cfl-2 tmp]$

The glibc implementation also works on 32-bit.

> > diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
> > index ffe300c931..99e7ee08cf 100644
> > --- a/sysdeps/x86/include/cpu-features.h
> > +++ b/sysdeps/x86/include/cpu-features.h
> > @@ -123,6 +123,8 @@ struct cpu_features
> >    struct cpu_features_basic basic;
> >    struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
> >    unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
> > +  /* X86 micro-architecture ISA levels.  */
> > +  unsigned int isa_1;
> >    /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
> >       int so that we use
> >
>
> Ok.
>
> > diff --git a/sysdeps/x86/isa-level.c b/sysdeps/x86/isa-level.c
> > new file mode 100644
> > index 0000000000..aaf524cb56
> > --- /dev/null
> > +++ b/sysdeps/x86/isa-level.c
> > @@ -0,0 +1,97 @@
> > +/* ELF program property for x86 ISA level.
> > +   Copyright (C) 2020 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   In addition to the permissions in the GNU Lesser General Public
> > +   License, the Free Software Foundation gives you unlimited
> > +   permission to link the compiled version of this file with other
> > +   programs, and to distribute those programs without any restriction
> > +   coming from the use of this file.  (The Lesser General Public
> > +   License restrictions do apply in other respects; for example, they
> > +   cover modification of the file, and distribution when not linked
> > +   into another program.)
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#include <elf.h>
> > +
> > +/* ELF program property for x86 ISA level.  */
> > +#ifdef INCLUDE_X86_ISA_LEVEL
> > +# if defined __x86_64__ || defined __FXSR__ || !defined _SOFT_FLOAT \
> > +     || defined  __MMX__ || defined __SSE__ || defined __SSE2__
> > +#  define ISA_BASELINE       GNU_PROPERTY_X86_ISA_1_BASELINE
> > +# else
> > +#  define ISA_BASELINE       0
> > +# endif
> > +
> > +# if defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 \
> > +     || (defined __x86_64__ && defined __LAHF_SAHF__) \
> > +     || defined __POPCNT__ || defined __SSE3__ \
> > +     || defined __SSSE3__ || defined __SSE4_1__ || defined __SSE4_2__
> > +#  define ISA_V2     GNU_PROPERTY_X86_ISA_1_V2
> > +# else
> > +#  define ISA_V2     0
> > +# endif
> > +
> > +# if defined __AVX__ || defined __AVX2__ || defined __F16C__ \
> > +     || defined __FMA__ || defined __LZCNT__ || defined __MOVBE__ \
> > +     || defined __XSAVE__
> > +#  define ISA_V3     GNU_PROPERTY_X86_ISA_1_V3
> > +# else
> > +#  define ISA_V3     0
> > +# endif
> > +
> > +# if defined __AVX512F__ || defined __AVX512BW__ || defined __AVX512CD__ \
> > +     || defined __AVX512DQ__ || defined __AVX512VL__
> > +#  define ISA_V4     GNU_PROPERTY_X86_ISA_1_V4
> > +# else
> > +#  define ISA_V4     0
> > +# endif
> > +
> > +# ifndef ISA_LEVEL
> > +#  define ISA_LEVEL (ISA_BASELINE | ISA_V2 | ISA_V3 | ISA_V4)
> > +# endif
> > +
> > +# if ISA_LEVEL
> > +#  ifdef __LP64__
> > +#   define PROPERTY_ALIGN 3
> > +#  else
> > +#   define PROPERTY_ALIGN 2
> > +#  endif
> > +
> > +#  define note_stringify(arg) note_stringify_1(arg)
> > +#  define note_stringify_1(arg) #arg
> > +
> > +asm(".pushsection \".note.gnu.property\",\"a\",@note\n"
> > +"    .p2align " note_stringify (PROPERTY_ALIGN)
> > +     /* name length.  */
> > +"\n  .long 1f - 0f\n"
> > +     /* data length.  */
> > +"    .long 4f - 1f\n"
> > +     /* note type: NT_GNU_PROPERTY_TYPE_0.  */
> > +"    .long " note_stringify (NT_GNU_PROPERTY_TYPE_0)
> > +     /* vendor name.  */
> > +"\n0:        .asciz \"GNU\"\n"
> > +"1:  .p2align " note_stringify (PROPERTY_ALIGN)
> > +     /* pr_type: GNU_PROPERTY_X86_ISA_1_NEEDED.  */
> > +"\n  .long " note_stringify (GNU_PROPERTY_X86_ISA_1_NEEDED)
> > +     /* pr_datasz.  */
> > +"\n  .long 3f - 2f\n"
> > +     /* GNU_PROPERTY_X86_ISA_1_V[234].  */
> > +"2:\n         .long " note_stringify (ISA_LEVEL)
> > +"\n3:\n      .p2align " note_stringify (PROPERTY_ALIGN)
> > +"\n4:\n .popsection");
> > +# endif /* ISA_LEVEL */
> > +#endif /* INCLUDE_X86_ISA_LEVEL */
>
> Ok.
>
> > diff --git a/sysdeps/x86/link_map.h b/sysdeps/x86/link_map.h
> > index 8074739b47..4c46a25f83 100644
> > --- a/sysdeps/x86/link_map.h
> > +++ b/sysdeps/x86/link_map.h
> > @@ -16,12 +16,16 @@
> >     License along with the GNU C Library; if not, see
> >     <https://www.gnu.org/licenses/>.  */
> >
> > -/* If this object is enabled with CET.  */
> > +/* if this object has GNU property.  */
> >  enum
> >    {
> > -    lc_unknown = 0,                   /* Unknown CET status.  */
> > -    lc_none = 1 << 0,                         /* Not enabled with CET.  */
> > -    lc_ibt = 1 << 1,                  /* Enabled with IBT.  */
> > -    lc_shstk = 1 << 2,                        /* Enabled with STSHK.  */
> > -    lc_ibt_and_shstk = lc_ibt | lc_shstk /* Enabled with both.  */
> > -  } l_cet:3;
> > +    lc_property_unknown = 0,         /* Unknown property status.  */
> > +    lc_property_none = 1 << 0,               /* No property.  */
> > +    lc_property_valid = 1 << 1               /* Has valid property.  */
> > +  } l_property:2;
> > +
> > +/* GNU_PROPERTY_X86_FEATURE_1_AND of this object.  */
> > +unsigned int l_x86_feature_1_and;
> > +
> > +/* GNU_PROPERTY_X86_ISA_1_NEEDED of this object.  */
> > +unsigned int l_x86_isa_1_needed;
>
> Ok.
>
> > diff --git a/sysdeps/x86/tst-isa-level-1.c b/sysdeps/x86/tst-isa-level-1.c
> > new file mode 100644
> > index 0000000000..dc31d71ad2
> > --- /dev/null
> > +++ b/sysdeps/x86/tst-isa-level-1.c
> > @@ -0,0 +1,104 @@
> > +/* Check ISA level on dlopened shared object.
> > +   Copyright (C) 2020 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#include <stdlib.h>
> > +#include <stdbool.h>
> > +#include <string.h>
> > +#include <elf.h>
> > +#include <get-isa-level.h>
> > +#include <support/xdlfcn.h>
> > +#include <support/check.h>
> > +#include <support/test-driver.h>
> > +
> > +static void
> > +do_test_1 (const char *modname, bool fail)
> > +{
> > +  int (*fp) (void);
> > +  void *h;
> > +
> > +  h = dlopen (modname, RTLD_LAZY);
> > +  if (h == NULL)
> > +    {
> > +      const char *err = dlerror ();
> > +      if (fail)
> > +     {
> > +       if (strstr (err, "CPU ISA level is lower than required") == NULL)
> > +         FAIL_EXIT1 ("incorrect dlopen '%s' error: %s\n", modname, err);
> > +
> > +       return;
> > +     }
> > +
> > +      FAIL_EXIT1 ("cannot open '%s': %s\n", modname, err);
> > +    }
> > +
> > +  if (fail)
> > +    FAIL_EXIT1 ("dlopen '%s' should have failed\n", modname);
> > +
> > +  fp = xdlsym (h, "test");
> > +
> > +  if (fp () != 0)
> > +    FAIL_EXIT1 ("test () != 0\n");
> > +
> > +  dlclose (h);
> > +}
> > +
> > +static int
> > +do_test (void)
> > +{
> > +  const struct cpu_features *cpu_features
> > +    = __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX);
> > +  unsigned int isa_level = get_isa_level (cpu_features);
> > +  bool has_isa_baseline = ((isa_level & GNU_PROPERTY_X86_ISA_1_BASELINE)
> > +                        == GNU_PROPERTY_X86_ISA_1_BASELINE);
> > +  bool has_isa_v2 = ((isa_level & GNU_PROPERTY_X86_ISA_1_V2)
> > +                        == GNU_PROPERTY_X86_ISA_1_V2);
> > +  bool has_isa_v3 = ((isa_level & GNU_PROPERTY_X86_ISA_1_V3)
> > +                        == GNU_PROPERTY_X86_ISA_1_V3);
> > +  bool has_isa_v4 = ((isa_level & GNU_PROPERTY_X86_ISA_1_V4)
> > +                        == GNU_PROPERTY_X86_ISA_1_V4);
> > +
> > +  if (!has_isa_baseline)
> > +    {
> > +      do_test_1 ("tst-isa-level-mod-1-baseline.so", true);
> > +      return EXIT_SUCCESS;
> > +    }
> > +
> > +  do_test_1 ("tst-isa-level-mod-1-baseline.so", false);
> > +
> > +  /* Skip on x86-64-v4 platforms since dlopen v4 module always works.  */
> > +  if (has_isa_v4)
> > +    return EXIT_UNSUPPORTED;
>
> Not sure if unsupported is the right error code here, since the isa
> selection is just ignored (not really not supported).

I will change it to EXIT_SUCCESS.

> > +
> > +  do_test_1 ("tst-isa-level-mod-1-v4.so", true);
> > +
> > +  /* Skip on x86-64-v3 platforms since dlopen v3 module always works.  */
> > +  if (has_isa_v3)
> > +    return EXIT_SUCCESS;
> > +
> > +  do_test_1 ("tst-isa-level-mod-1-v3.so", true);
> > +
> > +  /* Skip on x86-64-v2 platforms since dlopen v2 module always works.  */
> > +  if (has_isa_v2)
> > +    return EXIT_SUCCESS;
> > +
> > +  do_test_1 ("tst-isa-level-mod-1-v2.so", true);
> > +
> > +  return EXIT_SUCCESS;
> > +}
> > +
> > +#include <support/test-driver.c>
> > diff --git a/sysdeps/x86/tst-isa-level-mod-1-baseline.c b/sysdeps/x86/tst-isa-level-mod-1-baseline.c
> > new file mode 100644
> > index 0000000000..d6fe0685a4
> > --- /dev/null
> > +++ b/sysdeps/x86/tst-isa-level-mod-1-baseline.c
> > @@ -0,0 +1 @@
> > +#include "tst-isa-level-mod-1.c"
> > diff --git a/sysdeps/x86/tst-isa-level-mod-1-v2.c b/sysdeps/x86/tst-isa-level-mod-1-v2.c
> > new file mode 100644
> > index 0000000000..d6fe0685a4
> > --- /dev/null
> > +++ b/sysdeps/x86/tst-isa-level-mod-1-v2.c
> > @@ -0,0 +1 @@
> > +#include "tst-isa-level-mod-1.c"
> > diff --git a/sysdeps/x86/tst-isa-level-mod-1-v3.c b/sysdeps/x86/tst-isa-level-mod-1-v3.c
> > new file mode 100644
> > index 0000000000..d6fe0685a4
> > --- /dev/null
> > +++ b/sysdeps/x86/tst-isa-level-mod-1-v3.c
> > @@ -0,0 +1 @@
> > +#include "tst-isa-level-mod-1.c"
> > diff --git a/sysdeps/x86/tst-isa-level-mod-1-v4.c b/sysdeps/x86/tst-isa-level-mod-1-v4.c
> > new file mode 100644
> > index 0000000000..d6fe0685a4
> > --- /dev/null
> > +++ b/sysdeps/x86/tst-isa-level-mod-1-v4.c
> > @@ -0,0 +1 @@
> > +#include "tst-isa-level-mod-1.c"
>
> Ok.
>
> > diff --git a/sysdeps/x86/tst-isa-level-mod-1.c b/sysdeps/x86/tst-isa-level-mod-1.c
> > new file mode 100644
> > index 0000000000..40a2e1d99f
> > --- /dev/null
> > +++ b/sysdeps/x86/tst-isa-level-mod-1.c
> > @@ -0,0 +1,25 @@
> > +/* Check ISA level on dlopened shared object.
> > +   Copyright (C) 2019-2020 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later version.
> > +
> > +   The GNU C Library is distributed in the hope that it will be useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#include <isa-level.c>
> > +
> > +int
> > +test (void)
> > +{
> > +  return 0;
> > +}
>
> Ok.
>
> > diff --git a/sysdeps/x86_64/dl-hwcaps-subdirs.c b/sysdeps/x86_64/dl-hwcaps-subdirs.c
> > index 0aaa635a00..e030534f1b 100644
> > --- a/sysdeps/x86_64/dl-hwcaps-subdirs.c
> > +++ b/sysdeps/x86_64/dl-hwcaps-subdirs.c
> > @@ -18,6 +18,7 @@
> >
> >  #include <dl-hwcaps.h>
> >  #include <cpu-features.h>
> > +#include <get-isa-level.h>
> >
> >  const char _dl_hwcaps_subdirs[] = "x86-64-v4:x86-64-v3:x86-64-v2";
> >  enum { subdirs_count = 3 }; /* Number of components in _dl_hwcaps_subdirs.  */
> > @@ -25,40 +26,25 @@ enum { subdirs_count = 3 }; /* Number of components in _dl_hwcaps_subdirs.  */
> >  uint32_t
> >  _dl_hwcaps_subdirs_active (void)
> >  {
> > +  const struct cpu_features *cpu_features
> > +    = __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX);
> > +  unsigned int isa_level = get_isa_level (cpu_features);
> >    int active = 0;
> >
> >    /* Test in reverse preference order.  */
> >
> >    /* x86-64-v2.  */
> > -  if (!(CPU_FEATURE_USABLE (CMPXCHG16B)
> > -        && CPU_FEATURE_USABLE (LAHF64_SAHF64)
> > -        && CPU_FEATURE_USABLE (POPCNT)
> > -        && CPU_FEATURE_USABLE (SSE3)
> > -        && CPU_FEATURE_USABLE (SSE4_1)
> > -        && CPU_FEATURE_USABLE (SSE4_2)
> > -        && CPU_FEATURE_USABLE (SSSE3)))
> > +  if (!(isa_level & GNU_PROPERTY_X86_ISA_1_V2))
> >      return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
> >    ++active;
> >
> >    /* x86-64-v3.  */
> > -  if (!(CPU_FEATURE_USABLE (AVX)
> > -        && CPU_FEATURE_USABLE (AVX2)
> > -        && CPU_FEATURE_USABLE (BMI1)
> > -        && CPU_FEATURE_USABLE (BMI2)
> > -        && CPU_FEATURE_USABLE (F16C)
> > -        && CPU_FEATURE_USABLE (FMA)
> > -        && CPU_FEATURE_USABLE (LZCNT)
> > -        && CPU_FEATURE_USABLE (MOVBE)
> > -        && CPU_FEATURE_USABLE (OSXSAVE)))
> > +  if (!(isa_level & GNU_PROPERTY_X86_ISA_1_V3))
> >      return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
> >    ++active;
> >
> > - /* x86-64-v4.  */
> > -  if (!(CPU_FEATURE_USABLE (AVX512F)
> > -        && CPU_FEATURE_USABLE (AVX512BW)
> > -        && CPU_FEATURE_USABLE (AVX512CD)
> > -        && CPU_FEATURE_USABLE (AVX512DQ)
> > -        && CPU_FEATURE_USABLE (AVX512VL)))
> > +  /* x86-64-v4.  */
> > +  if (!(isa_level & GNU_PROPERTY_X86_ISA_1_V4))
> >      return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
> >    ++active;
> >
> > diff --git a/sysdeps/x86_64/tst-glibc-hwcaps.c b/sysdeps/x86_64/tst-glibc-hwcaps.c
> > index 8bdcb91db0..37b61d3c84 100644
> > --- a/sysdeps/x86_64/tst-glibc-hwcaps.c
> > +++ b/sysdeps/x86_64/tst-glibc-hwcaps.c
> > @@ -19,7 +19,8 @@
> >  #include <stdio.h>
> >  #include <support/check.h>
> >  #include <sys/param.h>
> > -#include <sys/platform/x86.h>
> > +#include <elf.h>
> > +#include <get-isa-level.h>
> >
> >  extern int marker2 (void);
> >  extern int marker3 (void);
> > @@ -31,35 +32,15 @@ compute_level (void)
> >  {
> >    const struct cpu_features *cpu_features
> >      = __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX);
> > -
> > - if (!(CPU_FEATURE_USABLE_P (cpu_features, CMPXCHG16B)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, LAHF64_SAHF64)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, POPCNT)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, MMX)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, SSE)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, SSE2)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, SSE3)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, SSSE3)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, SSE4_1)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, SSE4_2)))
> > -   return 1;
> > - if (!(CPU_FEATURE_USABLE_P (cpu_features, AVX)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, AVX2)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, BMI1)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, BMI2)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, F16C)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, FMA)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, LZCNT)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, MOVBE)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, OSXSAVE)))
> > -   return 2;
> > - if (!(CPU_FEATURE_USABLE_P (cpu_features, AVX512F)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, AVX512CD)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, AVX512DQ)
> > -       && CPU_FEATURE_USABLE_P (cpu_features, AVX512VL)))
> > -   return 3;
> > - return 4;
> > +  unsigned int isa_level = get_isa_level (cpu_features);
> > +
> > +  if (!(isa_level & GNU_PROPERTY_X86_ISA_1_V2))
> > +    return 1;
> > +  if (!(isa_level & GNU_PROPERTY_X86_ISA_1_V3))
> > +    return 2;
> > +  if (!(isa_level & GNU_PROPERTY_X86_ISA_1_V4))
> > +    return 3;
> > +  return 4;
> >  }
> >
> >  static int
> > --
> > 2.29.2
>
> Ok.

This is the patch I am checking in.

Thanks.

-- 
H.J.

[-- Attachment #2: 0001-x86-Support-GNU_PROPERTY_X86_ISA_1_V-234-marker-BZ-2.patch --]
[-- Type: text/x-patch, Size: 40535 bytes --]

From 6dfa1ac62635e05d13600bd1e6e0a770a44875b4 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Fri, 9 Oct 2020 06:06:56 -0700
Subject: [PATCH] x86: Support GNU_PROPERTY_X86_ISA_1_V[234] marker [BZ #26717]

GCC 11 supports -march=x86-64-v[234] to enable x86 micro-architecture ISA
levels:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97250

and -mneeded to emit GNU_PROPERTY_X86_ISA_1_NEEDED property with
GNU_PROPERTY_X86_ISA_1_V[234] marker:

https://gitlab.com/x86-psABIs/x86-64-ABI/-/merge_requests/13

Binutils support for GNU_PROPERTY_X86_ISA_1_V[234] marker were added by

commit b0ab06937385e0ae25cebf1991787d64f439bf12
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Oct 30 06:49:57 2020 -0700

    x86: Support GNU_PROPERTY_X86_ISA_1_BASELINE marker

and

commit 32930e4edbc06bc6f10c435dbcc63131715df678
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Oct 9 05:05:57 2020 -0700

    x86: Support GNU_PROPERTY_X86_ISA_1_V[234] marker

GNU_PROPERTY_X86_ISA_1_NEEDED property in x86 ELF binaries indicate the
micro-architecture ISA level required to execute the binary.  The marker
must be added by programmers explicitly in one of 3 ways:

1. Pass -mneeded to GCC.
2. Add the marker in the linker inputs as this patch does.
3. Pass -z x86-64-v[234] to the linker.

Add GNU_PROPERTY_X86_ISA_1_BASELINE and GNU_PROPERTY_X86_ISA_1_V[234]
marker support to ld.so if binutils 2.32 or newer is used to build glibc:

1. Add GNU_PROPERTY_X86_ISA_1_BASELINE and GNU_PROPERTY_X86_ISA_1_V[234]
markers to elf.h.
2. Add GNU_PROPERTY_X86_ISA_1_BASELINE and GNU_PROPERTY_X86_ISA_1_V[234]
marker to abi-note.o based on the ISA level used to compile abi-note.o,
assuming that the same ISA level is used to compile the whole glibc.
3. Add isa_1 to cpu_features to record the supported x86 ISA level.
4. Rename _dl_process_cet_property_note to _dl_process_property_note and
add GNU_PROPERTY_X86_ISA_1_V[234] marker detection.
5. Update _rtld_main_check and _dl_open_check to check loaded objects
with the incompatible ISA level.
6. Add a testcase to verify that dlopen an x86-64-v4 shared object fails
on lesser platforms.
7. Use <get-isa-level.h> in dl-hwcaps-subdirs.c and tst-glibc-hwcaps.c.

Tested under i686, x32 and x86-64 modes on x86-64-v2, x86-64-v3 and
x86-64-v4 machines.

Marked elf/tst-isa-level-1 with x86-64-v4, ran it on x86-64-v3 machine
and got:

[hjl@gnu-cfl-2 build-x86_64-linux]$ ./elf/tst-isa-level-1
./elf/tst-isa-level-1: CPU ISA level is lower than required
[hjl@gnu-cfl-2 build-x86_64-linux]$
---
 config.h.in                                |   3 +
 elf/elf.h                                  |  35 +++----
 sysdeps/x86/Makefile                       |  30 ++++++
 sysdeps/x86/abi-note.c                     |  29 ++++++
 sysdeps/x86/configure                      |  79 ++++++++++++++
 sysdeps/x86/configure.ac                   |  66 ++++++++++++
 sysdeps/x86/cpu-features.c                 |   3 +
 sysdeps/x86/dl-cet.c                       |  12 ++-
 sysdeps/x86/dl-prop.h                      | 113 +++++++++++++++------
 sysdeps/x86/get-isa-level.h                |  66 ++++++++++++
 sysdeps/x86/include/cpu-features.h         |   2 +
 sysdeps/x86/isa-level.c                    |  97 ++++++++++++++++++
 sysdeps/x86/link_map.h                     |  18 ++--
 sysdeps/x86/tst-isa-level-1.c              | 104 +++++++++++++++++++
 sysdeps/x86/tst-isa-level-mod-1-baseline.c |   1 +
 sysdeps/x86/tst-isa-level-mod-1-v2.c       |   1 +
 sysdeps/x86/tst-isa-level-mod-1-v3.c       |   1 +
 sysdeps/x86/tst-isa-level-mod-1-v4.c       |   1 +
 sysdeps/x86/tst-isa-level-mod-1.c          |  25 +++++
 sysdeps/x86_64/dl-hwcaps-subdirs.c         |  30 ++----
 sysdeps/x86_64/tst-glibc-hwcaps.c          |  41 ++------
 21 files changed, 644 insertions(+), 113 deletions(-)
 create mode 100644 sysdeps/x86/abi-note.c
 create mode 100644 sysdeps/x86/get-isa-level.h
 create mode 100644 sysdeps/x86/isa-level.c
 create mode 100644 sysdeps/x86/tst-isa-level-1.c
 create mode 100644 sysdeps/x86/tst-isa-level-mod-1-baseline.c
 create mode 100644 sysdeps/x86/tst-isa-level-mod-1-v2.c
 create mode 100644 sysdeps/x86/tst-isa-level-mod-1-v3.c
 create mode 100644 sysdeps/x86/tst-isa-level-mod-1-v4.c
 create mode 100644 sysdeps/x86/tst-isa-level-mod-1.c

diff --git a/config.h.in b/config.h.in
index eca2d66a2c..947feeff36 100644
--- a/config.h.in
+++ b/config.h.in
@@ -269,4 +269,7 @@
 /* The default value of x86 CET control.  */
 #define DEFAULT_DL_X86_CET_CONTROL cet_elf_property
 
+/* Define if x86 ISA level should be included in shared libraries.  */
+#undef INCLUDE_X86_ISA_LEVEL
+
 #endif
diff --git a/elf/elf.h b/elf/elf.h
index 4a9ae97dfc..9ebd052c8a 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -1324,31 +1324,26 @@ typedef struct
 
 /* The x86 instruction sets indicated by the corresponding bits are
    used in program.  Their support in the hardware is optional.  */
-#define GNU_PROPERTY_X86_ISA_1_USED		0xc0000000
+#define GNU_PROPERTY_X86_ISA_1_USED		0xc0010002
 /* The x86 instruction sets indicated by the corresponding bits are
    used in program and they must be supported by the hardware.   */
-#define GNU_PROPERTY_X86_ISA_1_NEEDED		0xc0000001
+#define GNU_PROPERTY_X86_ISA_1_NEEDED		0xc0008002
 /* X86 processor-specific features used in program.  */
 #define GNU_PROPERTY_X86_FEATURE_1_AND		0xc0000002
 
-#define GNU_PROPERTY_X86_ISA_1_486		(1U << 0)
-#define GNU_PROPERTY_X86_ISA_1_586		(1U << 1)
-#define GNU_PROPERTY_X86_ISA_1_686		(1U << 2)
-#define GNU_PROPERTY_X86_ISA_1_SSE		(1U << 3)
-#define GNU_PROPERTY_X86_ISA_1_SSE2		(1U << 4)
-#define GNU_PROPERTY_X86_ISA_1_SSE3		(1U << 5)
-#define GNU_PROPERTY_X86_ISA_1_SSSE3		(1U << 6)
-#define GNU_PROPERTY_X86_ISA_1_SSE4_1		(1U << 7)
-#define GNU_PROPERTY_X86_ISA_1_SSE4_2		(1U << 8)
-#define GNU_PROPERTY_X86_ISA_1_AVX		(1U << 9)
-#define GNU_PROPERTY_X86_ISA_1_AVX2		(1U << 10)
-#define GNU_PROPERTY_X86_ISA_1_AVX512F		(1U << 11)
-#define GNU_PROPERTY_X86_ISA_1_AVX512CD		(1U << 12)
-#define GNU_PROPERTY_X86_ISA_1_AVX512ER		(1U << 13)
-#define GNU_PROPERTY_X86_ISA_1_AVX512PF		(1U << 14)
-#define GNU_PROPERTY_X86_ISA_1_AVX512VL		(1U << 15)
-#define GNU_PROPERTY_X86_ISA_1_AVX512DQ		(1U << 16)
-#define GNU_PROPERTY_X86_ISA_1_AVX512BW		(1U << 17)
+/* GNU_PROPERTY_X86_ISA_1_BASELINE: CMOV, CX8 (cmpxchg8b), FPU (fld),
+   MMX, OSFXSR (fxsave), SCE (syscall), SSE and SSE2.  */
+#define GNU_PROPERTY_X86_ISA_1_BASELINE		(1U << 0)
+/* GNU_PROPERTY_X86_ISA_1_V2: GNU_PROPERTY_X86_ISA_1_BASELINE,
+   CMPXCHG16B (cmpxchg16b), LAHF-SAHF (lahf), POPCNT (popcnt), SSE3,
+   SSSE3, SSE4.1 and SSE4.2.  */
+#define GNU_PROPERTY_X86_ISA_1_V2		(1U << 1)
+/* GNU_PROPERTY_X86_ISA_1_V3: GNU_PROPERTY_X86_ISA_1_V2, AVX, AVX2, BMI1,
+   BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE.  */
+#define GNU_PROPERTY_X86_ISA_1_V3		(1U << 2)
+/* GNU_PROPERTY_X86_ISA_1_V4: GNU_PROPERTY_X86_ISA_1_V3, AVX512F,
+   AVX512BW, AVX512CD, AVX512DQ and AVX512VL.  */
+#define GNU_PROPERTY_X86_ISA_1_V4		(1U << 3)
 
 /* This indicates that all executable sections are compatible with
    IBT.  */
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index 081cc72e93..c814d5a195 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -9,6 +9,36 @@ sysdep_headers += sys/platform/x86.h
 tests += tst-get-cpu-features tst-get-cpu-features-static \
 	 tst-cpu-features-cpuinfo tst-cpu-features-supports
 tests-static += tst-get-cpu-features-static
+ifeq (yes,$(enable-x86-isa-level))
+tests += tst-isa-level-1
+modules-names += tst-isa-level-mod-1-baseline \
+		 tst-isa-level-mod-1-v2 \
+		 tst-isa-level-mod-1-v3 \
+		 tst-isa-level-mod-1-v4 \
+
+# X86 ISA level baseline
+CFLAGS-tst-isa-level-mod-1-baseline.c += -DINCLUDE_X86_ISA_LEVEL \
+					 -DISA_LEVEL=0x1 \
+					 -march=x86-64
+# X86 ISA level v2
+CFLAGS-tst-isa-level-mod-1-v2.c += -DINCLUDE_X86_ISA_LEVEL \
+				   -DISA_LEVEL=0x3 \
+				   -march=x86-64
+# X86 ISA level v3
+CFLAGS-tst-isa-level-mod-1-v3.c += -DINCLUDE_X86_ISA_LEVEL \
+				   -DISA_LEVEL=0x7 \
+				   -march=x86-64
+# X86 ISA level v4
+CFLAGS-tst-isa-level-mod-1-v4.c += -DINCLUDE_X86_ISA_LEVEL \
+				   -DISA_LEVEL=0xf \
+				   -march=x86-64
+
+$(objpfx)tst-isa-level-1: $(libdl)
+$(objpfx)tst-isa-level-1.out: $(objpfx)tst-isa-level-mod-1-baseline.so \
+			      $(objpfx)tst-isa-level-mod-1-v2.so \
+			      $(objpfx)tst-isa-level-mod-1-v3.so \
+			      $(objpfx)tst-isa-level-mod-1-v4.so
+endif
 endif
 
 ifeq ($(subdir),math)
diff --git a/sysdeps/x86/abi-note.c b/sysdeps/x86/abi-note.c
new file mode 100644
index 0000000000..5140e6ab47
--- /dev/null
+++ b/sysdeps/x86/abi-note.c
@@ -0,0 +1,29 @@
+/* Special .init and .fini section support.  x86-64 version.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file.  (The Lesser General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <isa-level.c>
+#include <csu/abi-note.c>
diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure
index 81cc4e80d6..5e32dc62b3 100644
--- a/sysdeps/x86/configure
+++ b/sysdeps/x86/configure
@@ -68,3 +68,82 @@ elif test $enable_cet = permissive; then
 fi
 config_vars="$config_vars
 enable-cet = $enable_cet"
+
+# Check if linker supports x86 ISA level.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker x86 ISA level support" >&5
+$as_echo_n "checking for linker x86 ISA level support... " >&6; }
+if ${libc_cv_include_x86_isa_level+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest1.S <<EOF
+#ifdef __LP64__
+# define P2ALIGN 3
+#else
+# define P2ALIGN 2
+#endif
+	.section ".note.gnu.property", "a"
+	.p2align P2ALIGN
+	.long 1f - 0f		/* name length.  */
+	.long 4f - 1f		/* data length.  */
+	/* NT_GNU_PROPERTY_TYPE_0 */
+	.long 5			/* note type.  */
+0:
+	.asciz "GNU"		/* vendor name.  */
+1:
+	.p2align P2ALIGN
+	/* GNU_PROPERTY_X86_ISA_1_NEEDED */
+	.long 0xc0008002	/* pr_type.  */
+	.long 3f - 2f		/* pr_datasz.  */
+2:
+	.long 0x1
+3:
+	.p2align P2ALIGN
+4:
+EOF
+cat > conftest2.S <<EOF
+#ifdef __LP64__
+# define P2ALIGN 3
+#else
+# define P2ALIGN 2
+#endif
+	.section ".note.gnu.property", "a"
+	.p2align P2ALIGN
+	.long 1f - 0f		/* name length.  */
+	.long 4f - 1f		/* data length.  */
+	/* NT_GNU_PROPERTY_TYPE_0 */
+	.long 5			/* note type.  */
+0:
+	.asciz "GNU"		/* vendor name.  */
+1:
+	.p2align P2ALIGN
+	/* GNU_PROPERTY_X86_ISA_1_NEEDED */
+	.long 0xc0008002	/* pr_type.  */
+	.long 3f - 2f		/* pr_datasz.  */
+2:
+	.long 0x2
+3:
+	.p2align P2ALIGN
+4:
+EOF
+libc_cv_include_x86_isa_level=no
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest conftest1.S conftest2.S'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+  count=`LC_ALL=C $READELF -n conftest | grep NT_GNU_PROPERTY_TYPE_0 | wc -l`
+  if test "$count" = 1; then
+    libc_cv_include_x86_isa_level=yes
+  fi
+fi
+rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_include_x86_isa_level" >&5
+$as_echo "$libc_cv_include_x86_isa_level" >&6; }
+if test $libc_cv_include_x86_isa_level = yes; then
+  $as_echo "#define INCLUDE_X86_ISA_LEVEL 1" >>confdefs.h
+
+fi
+config_vars="$config_vars
+enable-x86-isa-level = $libc_cv_include_x86_isa_level"
diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac
index 8f3e1191f6..f94088f377 100644
--- a/sysdeps/x86/configure.ac
+++ b/sysdeps/x86/configure.ac
@@ -43,3 +43,69 @@ elif test $enable_cet = permissive; then
   AC_DEFINE(DEFAULT_DL_X86_CET_CONTROL, cet_permissive)
 fi
 LIBC_CONFIG_VAR([enable-cet], [$enable_cet])
+
+# Check if linker supports x86 ISA level.
+AC_CACHE_CHECK([for linker x86 ISA level support],
+	       libc_cv_include_x86_isa_level, [dnl
+cat > conftest1.S <<EOF
+#ifdef __LP64__
+# define P2ALIGN 3
+#else
+# define P2ALIGN 2
+#endif
+	.section ".note.gnu.property", "a"
+	.p2align P2ALIGN
+	.long 1f - 0f		/* name length.  */
+	.long 4f - 1f		/* data length.  */
+	/* NT_GNU_PROPERTY_TYPE_0 */
+	.long 5			/* note type.  */
+0:
+	.asciz "GNU"		/* vendor name.  */
+1:
+	.p2align P2ALIGN
+	/* GNU_PROPERTY_X86_ISA_1_NEEDED */
+	.long 0xc0008002	/* pr_type.  */
+	.long 3f - 2f		/* pr_datasz.  */
+2:
+	.long 0x1
+3:
+	.p2align P2ALIGN
+4:
+EOF
+cat > conftest2.S <<EOF
+#ifdef __LP64__
+# define P2ALIGN 3
+#else
+# define P2ALIGN 2
+#endif
+	.section ".note.gnu.property", "a"
+	.p2align P2ALIGN
+	.long 1f - 0f		/* name length.  */
+	.long 4f - 1f		/* data length.  */
+	/* NT_GNU_PROPERTY_TYPE_0 */
+	.long 5			/* note type.  */
+0:
+	.asciz "GNU"		/* vendor name.  */
+1:
+	.p2align P2ALIGN
+	/* GNU_PROPERTY_X86_ISA_1_NEEDED */
+	.long 0xc0008002	/* pr_type.  */
+	.long 3f - 2f		/* pr_datasz.  */
+2:
+	.long 0x2
+3:
+	.p2align P2ALIGN
+4:
+EOF
+libc_cv_include_x86_isa_level=no
+if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest conftest1.S conftest2.S); then
+  count=`LC_ALL=C $READELF -n conftest | grep NT_GNU_PROPERTY_TYPE_0 | wc -l`
+  if test "$count" = 1; then
+    libc_cv_include_x86_isa_level=yes
+  fi
+fi
+rm -f conftest*])
+if test $libc_cv_include_x86_isa_level = yes; then
+  AC_DEFINE(INCLUDE_X86_ISA_LEVEL)
+fi
+LIBC_CONFIG_VAR([enable-x86-isa-level], [$libc_cv_include_x86_isa_level])
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
index 529c586193..e7da682a2e 100644
--- a/sysdeps/x86/cpu-features.c
+++ b/sysdeps/x86/cpu-features.c
@@ -19,6 +19,7 @@
 #include <cpuid.h>
 #include <dl-hwcap.h>
 #include <libc-pointer-arith.h>
+#include <get-isa-level.h>
 #if IS_IN (libc) && !defined SHARED
 # include <assert.h>
 # include <unistd.h>
@@ -290,6 +291,8 @@ update_usable (struct cpu_features *cpu_features)
       CPU_FEATURE_SET_USABLE (cpu_features, KL);
       CPU_FEATURE_SET_USABLE (cpu_features, WIDE_KL);
     }
+
+  cpu_features->isa_1 = get_isa_level (cpu_features);
 }
 
 static void
diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c
index b4910f7634..ed7fd6d10d 100644
--- a/sysdeps/x86/dl-cet.c
+++ b/sysdeps/x86/dl-cet.c
@@ -76,10 +76,12 @@ dl_cet_check (struct link_map *m, const char *program)
 	   */
 	  enable_ibt &= (HAS_CPU_FEATURE (IBT)
 			 && (enable_ibt_type == cet_always_on
-			     || (m->l_cet & lc_ibt) != 0));
+			     || (m->l_x86_feature_1_and
+				 & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0));
 	  enable_shstk &= (HAS_CPU_FEATURE (SHSTK)
 			   && (enable_shstk_type == cet_always_on
-			       || (m->l_cet & lc_shstk) != 0));
+			       || (m->l_x86_feature_1_and
+				   & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0));
 	}
 
       /* ld.so is CET-enabled by kernel.  But shared objects may not
@@ -111,7 +113,8 @@ dl_cet_check (struct link_map *m, const char *program)
 	      /* IBT is enabled only if it is enabled in executable as
 		 well as all shared objects.  */
 	      enable_ibt &= (enable_ibt_type == cet_always_on
-			     || (l->l_cet & lc_ibt) != 0);
+			     || (l->l_x86_feature_1_and
+				 & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0);
 	      if (!found_ibt_legacy && enable_ibt != ibt_enabled)
 		{
 		  found_ibt_legacy = true;
@@ -121,7 +124,8 @@ dl_cet_check (struct link_map *m, const char *program)
 	      /* SHSTK is enabled only if it is enabled in executable as
 		 well as all shared objects.  */
 	      enable_shstk &= (enable_shstk_type == cet_always_on
-			       || (l->l_cet & lc_shstk) != 0);
+			       || (l->l_x86_feature_1_and
+				   & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0);
 	      if (enable_shstk != shstk_enabled)
 		{
 		  found_shstk_legacy = true;
diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h
index ce1667dc7a..56bd020b3c 100644
--- a/sysdeps/x86/dl-prop.h
+++ b/sysdeps/x86/dl-prop.h
@@ -19,14 +19,54 @@
 #ifndef _DL_PROP_H
 #define _DL_PROP_H
 
+#include <libintl.h>
+
 extern void _dl_cet_check (struct link_map *, const char *)
     attribute_hidden;
 extern void _dl_cet_open_check (struct link_map *)
     attribute_hidden;
 
+static void
+dl_isa_level_check (struct link_map *m, const char *program)
+{
+  const struct cpu_features *cpu_features = __get_cpu_features ();
+  unsigned int i;
+  struct link_map *l;
+
+  i = m->l_searchlist.r_nlist;
+  while (i-- > 0)
+    {
+      /* Check each shared object to see if ISA level is compatible.  */
+      l = m->l_initfini[i];
+
+      /* Skip ISA level check if functions have been executed.  */
+      if (l->l_init_called)
+	continue;
+
+#ifdef SHARED
+      /* Skip ISA level check for ld.so since ld.so won't run if its ISA
+	 level is higher than CPU.  */
+      if (l == &GL(dl_rtld_map) || l->l_real == &GL(dl_rtld_map))
+	continue;
+#endif
+
+      if ((l->l_x86_isa_1_needed & cpu_features->isa_1)
+	  != l->l_x86_isa_1_needed)
+	{
+	  if (program)
+	    _dl_fatal_printf ("%s: CPU ISA level is lower than required\n",
+			      *l->l_name != '\0' ? l->l_name : program);
+	  else
+	    _dl_signal_error (0, l->l_name, "dlopen",
+			      N_("CPU ISA level is lower than required"));
+	}
+    }
+}
+
 static inline void __attribute__ ((always_inline))
 _rtld_main_check (struct link_map *m, const char *program)
 {
+  dl_isa_level_check (m, program);
 #if CET_ENABLED
   _dl_cet_check (m, program);
 #endif
@@ -35,20 +75,18 @@ _rtld_main_check (struct link_map *m, const char *program)
 static inline void __attribute__ ((always_inline))
 _dl_open_check (struct link_map *m)
 {
+  dl_isa_level_check (m, NULL);
 #if CET_ENABLED
   _dl_cet_open_check (m);
 #endif
 }
 
 static inline void __attribute__ ((unused))
-_dl_process_cet_property_note (struct link_map *l,
-			      const ElfW(Nhdr) *note,
-			      const ElfW(Addr) size,
-			      const ElfW(Addr) align)
+_dl_process_property_note (struct link_map *l, const ElfW(Nhdr) *note,
+			   const ElfW(Addr) size, const ElfW(Addr) align)
 {
-#if CET_ENABLED
   /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before.  */
-  if (l->l_cet != lc_unknown)
+  if (l->l_property != lc_property_unknown)
     return;
 
   /* The NT_GNU_PROPERTY_TYPE_0 note must be aliged to 4 bytes in
@@ -59,7 +97,8 @@ _dl_process_cet_property_note (struct link_map *l,
 
   const ElfW(Addr) start = (ElfW(Addr)) note;
 
-  unsigned int feature_1 = 0;
+  unsigned int feature_1_and = 0;
+  unsigned int isa_1_needed = 0;
   unsigned int last_type = 0;
 
   while ((ElfW(Addr)) (note + 1) - start < size)
@@ -71,11 +110,11 @@ _dl_process_cet_property_note (struct link_map *l,
 	{
 	  /* Stop if we see more than one GNU property note which may
 	     be generated by the older linker.  */
-	  if (l->l_cet != lc_unknown)
+	  if (l->l_property != lc_property_unknown)
 	    return;
 
-	  /* Check CET status now.  */
-	  l->l_cet = lc_none;
+	  /* Check CET status and ISA levels now.  */
+	  l->l_property = lc_property_none;
 
 	  /* Check for invalid property.  */
 	  if (note->n_descsz < 8
@@ -101,26 +140,37 @@ _dl_process_cet_property_note (struct link_map *l,
 
 	      last_type = type;
 
-	      if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
+	      if (type == GNU_PROPERTY_X86_FEATURE_1_AND
+		  || type == GNU_PROPERTY_X86_ISA_1_NEEDED)
 		{
-		  /* The size of GNU_PROPERTY_X86_FEATURE_1_AND is 4
-		     bytes.  When seeing GNU_PROPERTY_X86_FEATURE_1_AND,
-		     we stop the search regardless if its size is correct
-		     or not.  There is no point to continue if this note
-		     is ill-formed.  */
+		  /* The sizes of types which we are searching for are
+		     4 bytes.  There is no point to continue if this
+		     note is ill-formed.  */
 		  if (datasz != 4)
 		    return;
 
-		  feature_1 = *(unsigned int *) ptr;
-
-		  /* Keep searching for the next GNU property note
-		     generated by the older linker.  */
-		  break;
+		  /* NB: Stop the scan only after seeing all types which
+		     we are searching for.  */
+		  _Static_assert ((GNU_PROPERTY_X86_ISA_1_NEEDED >
+				   GNU_PROPERTY_X86_FEATURE_1_AND),
+				  "GNU_PROPERTY_X86_ISA_1_NEEDED > "
+				  "GNU_PROPERTY_X86_FEATURE_1_AND");
+		  if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
+		    feature_1_and = *(unsigned int *) ptr;
+		  else
+		    {
+		      isa_1_needed = *(unsigned int *) ptr;
+
+		      /* Keep searching for the next GNU property note
+			 generated by the older linker.  */
+		      break;
+		    }
 		}
-	      else if (type > GNU_PROPERTY_X86_FEATURE_1_AND)
+	      else if (type > GNU_PROPERTY_X86_ISA_1_NEEDED)
 		{
-		  /* Stop since property type is in ascending order.  */
-		  return;
+		  /* Stop the scan since property type is in ascending
+		     order.  */
+		  break;
 		}
 
 	      /* Check the next property item.  */
@@ -137,18 +187,21 @@ _dl_process_cet_property_note (struct link_map *l,
     }
 
   /* We get here only if there is one or no GNU property note.  */
-  if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT))
-    l->l_cet |= lc_ibt;
-  if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
-    l->l_cet |= lc_shstk;
-#endif
+  if (isa_1_needed != 0 || feature_1_and != 0)
+    {
+      l->l_property = lc_property_valid;
+      l->l_x86_isa_1_needed = isa_1_needed;
+      l->l_x86_feature_1_and = feature_1_and;
+    }
+  else
+    l->l_property = lc_property_none;
 }
 
 static inline void __attribute__ ((unused))
 _dl_process_pt_note (struct link_map *l, int fd, const ElfW(Phdr) *ph)
 {
   const ElfW(Nhdr) *note = (const void *) (ph->p_vaddr + l->l_addr);
-  _dl_process_cet_property_note (l, note, ph->p_memsz, ph->p_align);
+  _dl_process_property_note (l, note, ph->p_memsz, ph->p_align);
 }
 
 static inline int __attribute__ ((always_inline))
diff --git a/sysdeps/x86/get-isa-level.h b/sysdeps/x86/get-isa-level.h
new file mode 100644
index 0000000000..a86e1e8941
--- /dev/null
+++ b/sysdeps/x86/get-isa-level.h
@@ -0,0 +1,66 @@
+/* Get x86 ISA level.
+   This file is part of the GNU C Library.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <sys/platform/x86.h>
+
+/* Get GNU_PROPERTY_X86_ISA_1_BASELINE and GNU_PROPERTY_X86_ISA_1_V[234]
+   ISA level.  */
+
+static unsigned int
+get_isa_level (const struct cpu_features *cpu_features)
+{
+  unsigned int isa_level = 0;
+
+  if (CPU_FEATURE_USABLE_P (cpu_features, CMOV)
+      && CPU_FEATURE_USABLE_P (cpu_features, CX8)
+      && CPU_FEATURE_CPU_P (cpu_features, FPU)
+      && CPU_FEATURE_USABLE_P (cpu_features, FXSR)
+      && CPU_FEATURE_USABLE_P (cpu_features, MMX)
+      && CPU_FEATURE_USABLE_P (cpu_features, SSE)
+      && CPU_FEATURE_USABLE_P (cpu_features, SSE2))
+    {
+      isa_level = GNU_PROPERTY_X86_ISA_1_BASELINE;
+      if (CPU_FEATURE_USABLE_P (cpu_features, CMPXCHG16B)
+	  && CPU_FEATURE_USABLE_P (cpu_features, LAHF64_SAHF64)
+	  && CPU_FEATURE_USABLE_P (cpu_features, POPCNT)
+	  && CPU_FEATURE_USABLE_P (cpu_features, SSE3)
+	  && CPU_FEATURE_USABLE_P (cpu_features, SSSE3)
+	  && CPU_FEATURE_USABLE_P (cpu_features, SSE4_1)
+	  && CPU_FEATURE_USABLE_P (cpu_features, SSE4_2))
+	{
+	  isa_level |= GNU_PROPERTY_X86_ISA_1_V2;
+	  if (CPU_FEATURE_USABLE_P (cpu_features, AVX)
+	      && CPU_FEATURE_USABLE_P (cpu_features, AVX2)
+	      && CPU_FEATURE_USABLE_P (cpu_features, F16C)
+	      && CPU_FEATURE_USABLE_P (cpu_features, FMA)
+	      && CPU_FEATURE_USABLE_P (cpu_features, LZCNT)
+	      && CPU_FEATURE_USABLE_P (cpu_features, MOVBE))
+	    {
+	      isa_level |= GNU_PROPERTY_X86_ISA_1_V3;
+	      if (CPU_FEATURE_USABLE_P (cpu_features, AVX512F)
+		  && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW)
+		  && CPU_FEATURE_USABLE_P (cpu_features, AVX512CD)
+		  && CPU_FEATURE_USABLE_P (cpu_features, AVX512DQ)
+		  && CPU_FEATURE_USABLE_P (cpu_features, AVX512VL))
+		isa_level |= GNU_PROPERTY_X86_ISA_1_V4;
+	    }
+	}
+    }
+
+  return isa_level;
+}
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
index ffe300c931..99e7ee08cf 100644
--- a/sysdeps/x86/include/cpu-features.h
+++ b/sysdeps/x86/include/cpu-features.h
@@ -123,6 +123,8 @@ struct cpu_features
   struct cpu_features_basic basic;
   struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
   unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
+  /* X86 micro-architecture ISA levels.  */
+  unsigned int isa_1;
   /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
      int so that we use
 
diff --git a/sysdeps/x86/isa-level.c b/sysdeps/x86/isa-level.c
new file mode 100644
index 0000000000..aaf524cb56
--- /dev/null
+++ b/sysdeps/x86/isa-level.c
@@ -0,0 +1,97 @@
+/* ELF program property for x86 ISA level.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file with other
+   programs, and to distribute those programs without any restriction
+   coming from the use of this file.  (The Lesser General Public
+   License restrictions do apply in other respects; for example, they
+   cover modification of the file, and distribution when not linked
+   into another program.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <elf.h>
+
+/* ELF program property for x86 ISA level.  */
+#ifdef INCLUDE_X86_ISA_LEVEL
+# if defined __x86_64__ || defined __FXSR__ || !defined _SOFT_FLOAT \
+     || defined  __MMX__ || defined __SSE__ || defined __SSE2__
+#  define ISA_BASELINE	GNU_PROPERTY_X86_ISA_1_BASELINE
+# else
+#  define ISA_BASELINE	0
+# endif
+
+# if defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 \
+     || (defined __x86_64__ && defined __LAHF_SAHF__) \
+     || defined __POPCNT__ || defined __SSE3__ \
+     || defined __SSSE3__ || defined __SSE4_1__ || defined __SSE4_2__
+#  define ISA_V2	GNU_PROPERTY_X86_ISA_1_V2
+# else
+#  define ISA_V2	0
+# endif
+
+# if defined __AVX__ || defined __AVX2__ || defined __F16C__ \
+     || defined __FMA__ || defined __LZCNT__ || defined __MOVBE__ \
+     || defined __XSAVE__
+#  define ISA_V3	GNU_PROPERTY_X86_ISA_1_V3
+# else
+#  define ISA_V3	0
+# endif
+
+# if defined __AVX512F__ || defined __AVX512BW__ || defined __AVX512CD__ \
+     || defined __AVX512DQ__ || defined __AVX512VL__
+#  define ISA_V4	GNU_PROPERTY_X86_ISA_1_V4
+# else
+#  define ISA_V4	0
+# endif
+
+# ifndef ISA_LEVEL
+#  define ISA_LEVEL (ISA_BASELINE | ISA_V2 | ISA_V3 | ISA_V4)
+# endif
+
+# if ISA_LEVEL
+#  ifdef __LP64__
+#   define PROPERTY_ALIGN 3
+#  else
+#   define PROPERTY_ALIGN 2
+#  endif
+
+#  define note_stringify(arg) note_stringify_1(arg)
+#  define note_stringify_1(arg) #arg
+
+asm(".pushsection \".note.gnu.property\",\"a\",@note\n"
+"	.p2align " note_stringify (PROPERTY_ALIGN)
+	/* name length.  */
+"\n	.long 1f - 0f\n"
+	/* data length.  */
+"	.long 4f - 1f\n"
+	/* note type: NT_GNU_PROPERTY_TYPE_0.  */
+"	.long " note_stringify (NT_GNU_PROPERTY_TYPE_0)
+	/* vendor name.  */
+"\n0:	.asciz \"GNU\"\n"
+"1:	.p2align " note_stringify (PROPERTY_ALIGN)
+	/* pr_type: GNU_PROPERTY_X86_ISA_1_NEEDED.  */
+"\n	.long " note_stringify (GNU_PROPERTY_X86_ISA_1_NEEDED)
+	/* pr_datasz.  */
+"\n	.long 3f - 2f\n"
+	/* GNU_PROPERTY_X86_ISA_1_V[234].  */
+"2:\n	 .long " note_stringify (ISA_LEVEL)
+"\n3:\n	.p2align " note_stringify (PROPERTY_ALIGN)
+"\n4:\n .popsection");
+# endif /* ISA_LEVEL */
+#endif /* INCLUDE_X86_ISA_LEVEL */
diff --git a/sysdeps/x86/link_map.h b/sysdeps/x86/link_map.h
index 8074739b47..4c46a25f83 100644
--- a/sysdeps/x86/link_map.h
+++ b/sysdeps/x86/link_map.h
@@ -16,12 +16,16 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-/* If this object is enabled with CET.  */
+/* if this object has GNU property.  */
 enum
   {
-    lc_unknown = 0,			 /* Unknown CET status.  */
-    lc_none = 1 << 0,			 /* Not enabled with CET.  */
-    lc_ibt = 1 << 1,			 /* Enabled with IBT.  */
-    lc_shstk = 1 << 2,			 /* Enabled with STSHK.  */
-    lc_ibt_and_shstk = lc_ibt | lc_shstk /* Enabled with both.  */
-  } l_cet:3;
+    lc_property_unknown = 0,		/* Unknown property status.  */
+    lc_property_none = 1 << 0,		/* No property.  */
+    lc_property_valid = 1 << 1		/* Has valid property.  */
+  } l_property:2;
+
+/* GNU_PROPERTY_X86_FEATURE_1_AND of this object.  */
+unsigned int l_x86_feature_1_and;
+
+/* GNU_PROPERTY_X86_ISA_1_NEEDED of this object.  */
+unsigned int l_x86_isa_1_needed;
diff --git a/sysdeps/x86/tst-isa-level-1.c b/sysdeps/x86/tst-isa-level-1.c
new file mode 100644
index 0000000000..cf611e8b78
--- /dev/null
+++ b/sysdeps/x86/tst-isa-level-1.c
@@ -0,0 +1,104 @@
+/* Check ISA level on dlopened shared object.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <elf.h>
+#include <get-isa-level.h>
+#include <support/xdlfcn.h>
+#include <support/check.h>
+#include <support/test-driver.h>
+
+static void
+do_test_1 (const char *modname, bool fail)
+{
+  int (*fp) (void);
+  void *h;
+
+  h = dlopen (modname, RTLD_LAZY);
+  if (h == NULL)
+    {
+      const char *err = dlerror ();
+      if (fail)
+	{
+	  if (strstr (err, "CPU ISA level is lower than required") == NULL)
+	    FAIL_EXIT1 ("incorrect dlopen '%s' error: %s\n", modname, err);
+
+	  return;
+	}
+
+      FAIL_EXIT1 ("cannot open '%s': %s\n", modname, err);
+    }
+
+  if (fail)
+    FAIL_EXIT1 ("dlopen '%s' should have failed\n", modname);
+
+  fp = xdlsym (h, "test");
+
+  if (fp () != 0)
+    FAIL_EXIT1 ("test () != 0\n");
+
+  dlclose (h);
+}
+
+static int
+do_test (void)
+{
+  const struct cpu_features *cpu_features
+    = __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX);
+  unsigned int isa_level = get_isa_level (cpu_features);
+  bool has_isa_baseline = ((isa_level & GNU_PROPERTY_X86_ISA_1_BASELINE)
+			   == GNU_PROPERTY_X86_ISA_1_BASELINE);
+  bool has_isa_v2 = ((isa_level & GNU_PROPERTY_X86_ISA_1_V2)
+			   == GNU_PROPERTY_X86_ISA_1_V2);
+  bool has_isa_v3 = ((isa_level & GNU_PROPERTY_X86_ISA_1_V3)
+			   == GNU_PROPERTY_X86_ISA_1_V3);
+  bool has_isa_v4 = ((isa_level & GNU_PROPERTY_X86_ISA_1_V4)
+			   == GNU_PROPERTY_X86_ISA_1_V4);
+
+  if (!has_isa_baseline)
+    {
+      do_test_1 ("tst-isa-level-mod-1-baseline.so", true);
+      return EXIT_SUCCESS;
+    }
+
+  do_test_1 ("tst-isa-level-mod-1-baseline.so", false);
+
+  /* Skip on x86-64-v4 platforms since dlopen v4 module always works.  */
+  if (has_isa_v4)
+    return EXIT_SUCCESS;
+
+  do_test_1 ("tst-isa-level-mod-1-v4.so", true);
+
+  /* Skip on x86-64-v3 platforms since dlopen v3 module always works.  */
+  if (has_isa_v3)
+    return EXIT_SUCCESS;
+
+  do_test_1 ("tst-isa-level-mod-1-v3.so", true);
+
+  /* Skip on x86-64-v2 platforms since dlopen v2 module always works.  */
+  if (has_isa_v2)
+    return EXIT_SUCCESS;
+
+  do_test_1 ("tst-isa-level-mod-1-v2.so", true);
+
+  return EXIT_SUCCESS;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/x86/tst-isa-level-mod-1-baseline.c b/sysdeps/x86/tst-isa-level-mod-1-baseline.c
new file mode 100644
index 0000000000..d6fe0685a4
--- /dev/null
+++ b/sysdeps/x86/tst-isa-level-mod-1-baseline.c
@@ -0,0 +1 @@
+#include "tst-isa-level-mod-1.c"
diff --git a/sysdeps/x86/tst-isa-level-mod-1-v2.c b/sysdeps/x86/tst-isa-level-mod-1-v2.c
new file mode 100644
index 0000000000..d6fe0685a4
--- /dev/null
+++ b/sysdeps/x86/tst-isa-level-mod-1-v2.c
@@ -0,0 +1 @@
+#include "tst-isa-level-mod-1.c"
diff --git a/sysdeps/x86/tst-isa-level-mod-1-v3.c b/sysdeps/x86/tst-isa-level-mod-1-v3.c
new file mode 100644
index 0000000000..d6fe0685a4
--- /dev/null
+++ b/sysdeps/x86/tst-isa-level-mod-1-v3.c
@@ -0,0 +1 @@
+#include "tst-isa-level-mod-1.c"
diff --git a/sysdeps/x86/tst-isa-level-mod-1-v4.c b/sysdeps/x86/tst-isa-level-mod-1-v4.c
new file mode 100644
index 0000000000..d6fe0685a4
--- /dev/null
+++ b/sysdeps/x86/tst-isa-level-mod-1-v4.c
@@ -0,0 +1 @@
+#include "tst-isa-level-mod-1.c"
diff --git a/sysdeps/x86/tst-isa-level-mod-1.c b/sysdeps/x86/tst-isa-level-mod-1.c
new file mode 100644
index 0000000000..40a2e1d99f
--- /dev/null
+++ b/sysdeps/x86/tst-isa-level-mod-1.c
@@ -0,0 +1,25 @@
+/* Check ISA level on dlopened shared object.
+   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <isa-level.c>
+
+int
+test (void)
+{
+  return 0;
+}
diff --git a/sysdeps/x86_64/dl-hwcaps-subdirs.c b/sysdeps/x86_64/dl-hwcaps-subdirs.c
index 0aaa635a00..e030534f1b 100644
--- a/sysdeps/x86_64/dl-hwcaps-subdirs.c
+++ b/sysdeps/x86_64/dl-hwcaps-subdirs.c
@@ -18,6 +18,7 @@
 
 #include <dl-hwcaps.h>
 #include <cpu-features.h>
+#include <get-isa-level.h>
 
 const char _dl_hwcaps_subdirs[] = "x86-64-v4:x86-64-v3:x86-64-v2";
 enum { subdirs_count = 3 }; /* Number of components in _dl_hwcaps_subdirs.  */
@@ -25,40 +26,25 @@ enum { subdirs_count = 3 }; /* Number of components in _dl_hwcaps_subdirs.  */
 uint32_t
 _dl_hwcaps_subdirs_active (void)
 {
+  const struct cpu_features *cpu_features
+    = __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX);
+  unsigned int isa_level = get_isa_level (cpu_features);
   int active = 0;
 
   /* Test in reverse preference order.  */
 
   /* x86-64-v2.  */
-  if (!(CPU_FEATURE_USABLE (CMPXCHG16B)
-        && CPU_FEATURE_USABLE (LAHF64_SAHF64)
-        && CPU_FEATURE_USABLE (POPCNT)
-        && CPU_FEATURE_USABLE (SSE3)
-        && CPU_FEATURE_USABLE (SSE4_1)
-        && CPU_FEATURE_USABLE (SSE4_2)
-        && CPU_FEATURE_USABLE (SSSE3)))
+  if (!(isa_level & GNU_PROPERTY_X86_ISA_1_V2))
     return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
   ++active;
 
   /* x86-64-v3.  */
-  if (!(CPU_FEATURE_USABLE (AVX)
-        && CPU_FEATURE_USABLE (AVX2)
-        && CPU_FEATURE_USABLE (BMI1)
-        && CPU_FEATURE_USABLE (BMI2)
-        && CPU_FEATURE_USABLE (F16C)
-        && CPU_FEATURE_USABLE (FMA)
-        && CPU_FEATURE_USABLE (LZCNT)
-        && CPU_FEATURE_USABLE (MOVBE)
-        && CPU_FEATURE_USABLE (OSXSAVE)))
+  if (!(isa_level & GNU_PROPERTY_X86_ISA_1_V3))
     return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
   ++active;
 
- /* x86-64-v4.  */
-  if (!(CPU_FEATURE_USABLE (AVX512F)
-        && CPU_FEATURE_USABLE (AVX512BW)
-        && CPU_FEATURE_USABLE (AVX512CD)
-        && CPU_FEATURE_USABLE (AVX512DQ)
-        && CPU_FEATURE_USABLE (AVX512VL)))
+  /* x86-64-v4.  */
+  if (!(isa_level & GNU_PROPERTY_X86_ISA_1_V4))
     return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
   ++active;
 
diff --git a/sysdeps/x86_64/tst-glibc-hwcaps.c b/sysdeps/x86_64/tst-glibc-hwcaps.c
index 8bdcb91db0..37b61d3c84 100644
--- a/sysdeps/x86_64/tst-glibc-hwcaps.c
+++ b/sysdeps/x86_64/tst-glibc-hwcaps.c
@@ -19,7 +19,8 @@
 #include <stdio.h>
 #include <support/check.h>
 #include <sys/param.h>
-#include <sys/platform/x86.h>
+#include <elf.h>
+#include <get-isa-level.h>
 
 extern int marker2 (void);
 extern int marker3 (void);
@@ -31,35 +32,15 @@ compute_level (void)
 {
   const struct cpu_features *cpu_features
     = __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX);
-
- if (!(CPU_FEATURE_USABLE_P (cpu_features, CMPXCHG16B)
-       && CPU_FEATURE_USABLE_P (cpu_features, LAHF64_SAHF64)
-       && CPU_FEATURE_USABLE_P (cpu_features, POPCNT)
-       && CPU_FEATURE_USABLE_P (cpu_features, MMX)
-       && CPU_FEATURE_USABLE_P (cpu_features, SSE)
-       && CPU_FEATURE_USABLE_P (cpu_features, SSE2)
-       && CPU_FEATURE_USABLE_P (cpu_features, SSE3)
-       && CPU_FEATURE_USABLE_P (cpu_features, SSSE3)
-       && CPU_FEATURE_USABLE_P (cpu_features, SSE4_1)
-       && CPU_FEATURE_USABLE_P (cpu_features, SSE4_2)))
-   return 1;
- if (!(CPU_FEATURE_USABLE_P (cpu_features, AVX)
-       && CPU_FEATURE_USABLE_P (cpu_features, AVX2)
-       && CPU_FEATURE_USABLE_P (cpu_features, BMI1)
-       && CPU_FEATURE_USABLE_P (cpu_features, BMI2)
-       && CPU_FEATURE_USABLE_P (cpu_features, F16C)
-       && CPU_FEATURE_USABLE_P (cpu_features, FMA)
-       && CPU_FEATURE_USABLE_P (cpu_features, LZCNT)
-       && CPU_FEATURE_USABLE_P (cpu_features, MOVBE)
-       && CPU_FEATURE_USABLE_P (cpu_features, OSXSAVE)))
-   return 2;
- if (!(CPU_FEATURE_USABLE_P (cpu_features, AVX512F)
-       && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW)
-       && CPU_FEATURE_USABLE_P (cpu_features, AVX512CD)
-       && CPU_FEATURE_USABLE_P (cpu_features, AVX512DQ)
-       && CPU_FEATURE_USABLE_P (cpu_features, AVX512VL)))
-   return 3;
- return 4;
+  unsigned int isa_level = get_isa_level (cpu_features);
+
+  if (!(isa_level & GNU_PROPERTY_X86_ISA_1_V2))
+    return 1;
+  if (!(isa_level & GNU_PROPERTY_X86_ISA_1_V3))
+    return 2;
+  if (!(isa_level & GNU_PROPERTY_X86_ISA_1_V4))
+    return 3;
+  return 4;
 }
 
 static int
-- 
2.29.2


  reply	other threads:[~2021-01-07 20:59 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-06 14:49 V5 [PATCH 0/2] x86: Support GNU_PROPERTY_X86_ISA_1_NEEDED " H.J. Lu
2020-12-06 14:49 ` V5 [PATCH 1/2] x86: Support GNU_PROPERTY_X86_ISA_1_V[234] " H.J. Lu
2021-01-06 12:00   ` Adhemerval Zanella
2021-01-06 17:11     ` V6 " H.J. Lu
2021-01-07 20:09       ` Adhemerval Zanella
2021-01-07 20:58         ` H.J. Lu [this message]
2021-01-18 11:17           ` Florian Weimer
2021-01-18 13:49             ` H.J. Lu
2021-01-18 15:15               ` Florian Weimer
2020-12-06 14:49 ` V5 [PATCH 2/2] ldconfig/x86: Add ISA level check to glibc-hwcaps H.J. Lu
2020-12-07 10:00   ` Florian Weimer
2020-12-08 13:25     ` H.J. Lu
2020-12-08 13:31       ` Florian Weimer
2020-12-08 14:10         ` H.J. Lu
2020-12-08 14:18           ` Florian Weimer
2020-12-08 14:23             ` H.J. Lu
2020-12-08 15:15               ` Florian Weimer
2020-12-08 15:31                 ` H.J. Lu
2020-12-09  3:27                   ` [PATCH] ldconfig/x86: Store ISA level in cache and aux cache H.J. Lu
2021-01-12 16:25                     ` Adhemerval Zanella
2021-01-12 23:32                       ` V2 " H.J. Lu
2021-01-13 13:47                         ` Adhemerval Zanella
2021-01-13 14:12                           ` H.J. Lu
2021-01-28 20:20                     ` Florian Weimer
2021-01-28 20:43                       ` H.J. Lu
2021-01-29  8:56                         ` Florian Weimer
2021-01-29 12:44                           ` H.J. Lu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAMe9rOoQFRKJuoDcMEwo5+YrtrQ4rjNiK9A52AYhCi0wtDojjQ@mail.gmail.com \
    --to=hjl.tools@gmail.com \
    --cc=adhemerval.zanella@linaro.org \
    --cc=fweimer@redhat.com \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).