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
next prev parent 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).