From patchwork Wed Jan 6 17:11:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 41651 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2BAEA385702C; Wed, 6 Jan 2021 17:12:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2BAEA385702C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1609953126; bh=+4bW9iDhCDF80dJd0lTqY4Q7gDG1YHoeEEzRRr0/Dhw=; h=References:In-Reply-To:Date:Subject:To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=njup+N27tXCBOle2CGEJJBBnbic2Cl7mMd4odJm72FCLiFABQSVb1Yf4L4KPKQ9xn K4vnJufdKe7QfwR99I/zIBDnYkGJPjISYph6k7TaxI2C5yAYSvTcrMZQGGwdS7lgdK sFLR0g1sqwMXRRcWRKrHQYRA9fn152bm2GLkEGqk= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-ot1-x331.google.com (mail-ot1-x331.google.com [IPv6:2607:f8b0:4864:20::331]) by sourceware.org (Postfix) with ESMTPS id 061C03858036 for ; Wed, 6 Jan 2021 17:11:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 061C03858036 Received: by mail-ot1-x331.google.com with SMTP id d8so3628409otq.6 for ; Wed, 06 Jan 2021 09:11:56 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=+4bW9iDhCDF80dJd0lTqY4Q7gDG1YHoeEEzRRr0/Dhw=; b=UvYzdSmWblgSkb1Gp2WKE6OGMLZhhHFdjF6dqcXmeAOSpDnVicVNXgMoRglfX/0+ZS xHIxKrzBoCj+dhUfQj6pLBkzzjseLQT/+q11M6txxC8N+ZfNvhV6muYdWfRn+UunXSlO nsm7JfN0gyV7biqV2rPINxFT+jn9b8JjDLOb/y8B0ZLSyuWVBE+taNaNPNQ7Qe6fIphl w6B6YQdMSbQRoVEAbgCDdxBZy8Tqn2r44UqtP2Xkf42uZUurphIMr6LoDPW0qUCqAfim LEMnaCzA18N5gDSEBaCMQQhOuNhFGdHe1k5pRnadxQ2jjrkUPVLd5A8hGCVf6xIYRDb7 Pe/g== X-Gm-Message-State: AOAM5313PGeIh6nN3HYHb5QX1dQCx23sOfFqH5PjSp4aa+DSIFJiUrgo KZAr+o4v3SZpTDIU3JDUxiO0QmF5dxhw2Jm29eI= X-Google-Smtp-Source: ABdhPJzQKdfAbZ2Q0Sx2ygxH2pUNg6ptKbnmsDaN/hL71KdCYcvIahRgFZQQEkHXjg331mHFQcTKQXB54l5QhdGLauc= X-Received: by 2002:a9d:6285:: with SMTP id x5mr3929506otk.179.1609953115802; Wed, 06 Jan 2021 09:11:55 -0800 (PST) MIME-Version: 1.0 References: <20201206144952.2109594-1-hjl.tools@gmail.com> <20201206144952.2109594-2-hjl.tools@gmail.com> <83ab601d-adbe-6d26-8d9c-235d52503171@linaro.org> In-Reply-To: <83ab601d-adbe-6d26-8d9c-235d52503171@linaro.org> Date: Wed, 6 Jan 2021 09:11:19 -0800 Message-ID: Subject: V6 [PATCH 1/2] x86: Support GNU_PROPERTY_X86_ISA_1_V[234] marker [BZ #26717] To: Adhemerval Zanella X-Spam-Status: No, score=-3036.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_LOTSOFHASH, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "H.J. Lu via Libc-alpha" From: "H.J. Lu" Reply-To: "H.J. Lu" Cc: Florian Weimer , GNU C Library Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" On Wed, Jan 6, 2021 at 4:01 AM Adhemerval Zanella wrote: > > > > On 06/12/2020 11:49, H.J. Lu via Libc-alpha wrote: > > 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 > > 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 > > 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 in dl-hwcaps-subdirs.c and tst-glibc-hwcaps.c. > > > > 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 | 10 +++ > > sysdeps/x86/abi-note.c | 29 ++++++++ > > sysdeps/x86/configure | 101 ++++++++++++++++++++++++++ > > sysdeps/x86/configure.ac | 26 +++++++ > > 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 | 95 ++++++++++++++++++++++++ > > sysdeps/x86/link_map.h | 18 +++-- > > sysdeps/x86/tst-isa-level-1.c | 74 +++++++++++++++++++ > > sysdeps/x86/tst-isa-level-mod-1.c | 23 ++++++ > > sysdeps/x86/tst-isa-level-mod-1a.c | 2 + > > sysdeps/x86/tst-isa-level-mod-1b.c | 1 + > > sysdeps/x86_64/dl-hwcaps-subdirs.c | 30 ++------ > > sysdeps/x86_64/tst-glibc-hwcaps.c | 41 +++-------- > > 19 files changed, 571 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.c > > create mode 100644 sysdeps/x86/tst-isa-level-mod-1a.c > > create mode 100644 sysdeps/x86/tst-isa-level-mod-1b.c > > > > diff --git a/config.h.in b/config.h.in > > index b823c8e080..dc3854f4eb 100644 > > --- a/config.h.in > > +++ b/config.h.in > > @@ -266,4 +266,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 bd7af7cca4..42fd697129 100644 > > --- a/elf/elf.h > > +++ b/elf/elf.h > > @@ -1325,31 +1325,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. */ > > Shouldn't it follow bintuils 32930e4edbc06 change and move current > GNU_PROPERTY_X86_ISA_1_ definitions to GNU_PROPERTY_X86_COMPAT_2_? > Not sure if this charecterize any exported ABI change, since the > most possible usual consumer (bintuils) does not use glibc version. > > Also, maybe move this change to an specific patch. GNU_PROPERTY_X86_COMPAT_XXX were added to binutils consumers to support existing old binaries. Since glibc never supports old properties, there is no need to add them to glibc. > > > diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile > > index 081cc72e93..109f03e9b9 100644 > > --- a/sysdeps/x86/Makefile > > +++ b/sysdeps/x86/Makefile > > @@ -9,6 +9,16 @@ 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 (yesyes,$(enable-x86-isa-level)$(config-cflags-skylake-avx512)) > > +tests += tst-isa-level-1 > > +modules-names += tst-isa-level-mod-1a tst-isa-level-mod-1b > > + > > +CFLAGS-tst-isa-level-mod-1a.c += -march=skylake-avx512 \ > > + -DINCLUDE_X86_ISA_LEVEL > > +$(objpfx)tst-isa-level-1: $(libdl) > > +$(objpfx)tst-isa-level-1.out: $(objpfx)tst-isa-level-mod-1a.so \ > > + $(objpfx)tst-isa-level-mod-1b.so > > +endif > > endif > > > > ifeq ($(subdir),math) > > This will limit the test to a very narrow set of machines, couldn't > we check only for enable-x86-isa-level and make the conditional check > for ISA inside the test itself? Fixed. > What I have in mind would be something like: > > 1. Create onde module object for each ISA variant, by varying either > -march or using the specific gcc option (not sure it would clash > with the ABI notes isa-level.c already include). > > 2. On tst-isa-level-1.c check current ISA level with get_isa_level > and check against the ISA_BASELINE and load the modules with a > ISA number lower than baseline. > > Something like: > > const struct cpu_features *cpu_features > = __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX); > unsigned int isa_level = get_isa_level (cpu_features); > > bool check_isa_baseline = (isa_level & ISA_BASELINE) == ISA_BASELINE; > bool check_isa_v2 = (isa_level & ISA_V2) == ISA_V2; > bool check_isa_v3 = (isa_level & ISA_V3) == ISA_V3; > bool check_isa_v4 = (isa_level & ISA_V4) == ISA_V4; > > do_test_1 ("tst-isa-level-mod-1-baseline.so", true); > do_test_1 ("tst-isa-level-mod-1-isa_v2.so", true); > do_test_1 ("tst-isa-level-mod-1-isa_v3.so", true); > do_test_1 ("tst-isa-level-mod-1-isa_v4.so", true); Fixed. > You might require to just build the isa_v4 only for > config-cflags-skylake-avx512 and conditionalize with HAVE_SKYLAKE_AVX512_SUPPORT > (which seems to be ununsed in this patch). Fixed. > > 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 > > + . */ > > + > > +#include > > +#include > > Ok, > > > diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure > > index 81cc4e80d6..2738fe47b2 100644 > > --- a/sysdeps/x86/configure > > +++ b/sysdeps/x86/configure > > @@ -68,3 +68,104 @@ elif test $enable_cet = permissive; then > > fi > > config_vars="$config_vars > > enable-cet = $enable_cet" > > + > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -march=skylake-avx512 support" >&5 > > +$as_echo_n "checking for -march=skylake-avx512 support... " >&6; } > > +if ${libc_cv_cc_skylake_avx512+:} false; then : > > + $as_echo_n "(cached) " >&6 > > +else > > + if { ac_try='${CC-cc} -march=skylake-avx512 -xc /dev/null -S -o /dev/null' > > + { { 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 : > > + libc_cv_cc_skylake_avx512=yes > > +else > > + libc_cv_cc_skylake_avx512=no > > +fi > > + > > +fi > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc_skylake_avx512" >&5 > > +$as_echo "$libc_cv_cc_skylake_avx512" >&6; } > > +if test $libc_cv_cc_skylake_avx512 = yes; then > > + $as_echo "#define HAVE_SKYLAKE_AVX512_SUPPORT 1" >>confdefs.h > > + > > +fi > > +config_vars="$config_vars > > +config-cflags-skylake-avx512 = $libc_cv_cc_skylake_avx512" > > + > > +libc_cv_include_x86_isa_level=no > > +if test -z "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then > > + # Check for ld 2.32 or higher. > > + libc_cv_include_x86_isa_level=yes > > + for ac_prog in $LD > > +do > > + # Extract the first word of "$ac_prog", so it can be a program name with args. > > +set dummy $ac_prog; ac_word=$2 > > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 > > +$as_echo_n "checking for $ac_word... " >&6; } > > +if ${ac_cv_prog_LD+:} false; then : > > + $as_echo_n "(cached) " >&6 > > +else > > + if test -n "$LD"; then > > + ac_cv_prog_LD="$LD" # Let the user override the test. > > +else > > +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR > > +for as_dir in $PATH > > +do > > + IFS=$as_save_IFS > > + test -z "$as_dir" && as_dir=. > > + for ac_exec_ext in '' $ac_executable_extensions; do > > + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then > > + ac_cv_prog_LD="$ac_prog" > > + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 > > + break 2 > > + fi > > +done > > + done > > +IFS=$as_save_IFS > > + > > +fi > > +fi > > +LD=$ac_cv_prog_LD > > +if test -n "$LD"; then > > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 > > +$as_echo "$LD" >&6; } > > +else > > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 > > +$as_echo "no" >&6; } > > +fi > > + > > + > > + test -n "$LD" && break > > +done > > + > > +if test -z "$LD"; then > > + ac_verc_fail=yes > > +else > > + # Found it, now check the version. > > + { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $LD" >&5 > > +$as_echo_n "checking version of $LD... " >&6; } > > + ac_prog_version=`$LD --version 2>&1 | sed -n 's/^.*GNU ld.* \([0-9][0-9]*\.[0-9.]*\).*$/\1/p'` > > + case $ac_prog_version in > > + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; > > + 2.3[2-9]*|2.[4-9][0-9]*|[3-9].*|[1-9][0-9]*) > > + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; > > + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; > > + > > + esac > > + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_prog_version" >&5 > > +$as_echo "$ac_prog_version" >&6; } > > +fi > > +if test $ac_verc_fail = yes; then > > + libc_cv_include_x86_isa_level=no > > +fi > > + > > + if test $libc_cv_include_x86_isa_level = yes; then > > + $as_echo "#define INCLUDE_X86_ISA_LEVEL 1" >>confdefs.h > > + > > + fi > > +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..8f00b9663d 100644 > > --- a/sysdeps/x86/configure.ac > > +++ b/sysdeps/x86/configure.ac > > @@ -43,3 +43,29 @@ elif test $enable_cet = permissive; then > > AC_DEFINE(DEFAULT_DL_X86_CET_CONTROL, cet_permissive) > > fi > > LIBC_CONFIG_VAR([enable-cet], [$enable_cet]) > > + > > +dnl Check if -march=skylake-avx512 works. > > +AC_CACHE_CHECK(for -march=skylake-avx512 support, > > + libc_cv_cc_skylake_avx512, [dnl > > +LIBC_TRY_CC_OPTION([-march=skylake-avx512], > > + [libc_cv_cc_skylake_avx512=yes], > > + [libc_cv_cc_skylake_avx512=no]) > > +]) > > +if test $libc_cv_cc_skylake_avx512 = yes; then > > + AC_DEFINE(HAVE_SKYLAKE_AVX512_SUPPORT) > > +fi > > Where is it used specifically? There is no config.h.in tag either. The whole check is removed. > > +LIBC_CONFIG_VAR([config-cflags-skylake-avx512], [$libc_cv_cc_skylake_avx512]) > > + > > +libc_cv_include_x86_isa_level=no > > +if test -z "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then > > + # Check for ld 2.32 or higher. > > + libc_cv_include_x86_isa_level=yes > > + AC_CHECK_PROG_VER(LD, $LD, --version, > > + [GNU ld.* \([0-9][0-9]*\.[0-9.]*\)], > > + [2.3[2-9]*|2.[4-9][0-9]*|[3-9].*|[1-9][0-9]*], > > + libc_cv_include_x86_isa_level=no) > > + if test $libc_cv_include_x86_isa_level = yes; then > > + AC_DEFINE(INCLUDE_X86_ISA_LEVEL) > > + fi > > +fi > > +LIBC_CONFIG_VAR([enable-x86-isa-level], [$libc_cv_include_x86_isa_level]) > > Instead of version check, would it better to check if the linker actually > build a snippet with the expected notes? Fixed. > > diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c > > index fe080b63b2..ec5cdafe81 100644 > > --- a/sysdeps/x86/cpu-features.c > > +++ b/sysdeps/x86/cpu-features.c > > @@ -19,6 +19,7 @@ > > #include > > #include > > #include > > +#include > > #if IS_IN (libc) && !defined SHARED > > # include > > # include > > @@ -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 5524b66038..8986c776e5 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)); > > } > > > > Ok. > > > /* 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; > > Ok. > > > diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h > > index 89911e19e2..61c0624c09 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 > > + > > 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. Not sure if it is worth to translate the _dl_fatal_printf (it seems > that at least one use at elf/dl-open.c does it). I left it unchanged. > > > 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 > > } > > > > Ok. > > > 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 > > Ok. > > > @@ -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; > > > > Ok. > > > - 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"); > > Ok. > > > + 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 || feature_1_and) > > No implicit checks. Fixed. > > + { > > + 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, 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..166dd5df01 > > --- /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 > > + . */ > > + > > +#include > > + > > +/* 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 isa_level = 0; > > s/unsigned/unsigned int/ Fixed. > > + > > + 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; > > +} > > Do we actually support a isa level lower than baseline? Yes. In 32-bit, we require i486 or above. > > diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h > > index f62be0b9b3..ef0c6b4fbc 100644 > > --- a/sysdeps/x86/include/cpu-features.h > > +++ b/sysdeps/x86/include/cpu-features.h > > @@ -129,6 +129,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..0751e86f27 > > --- /dev/null > > +++ b/sysdeps/x86/isa-level.c > > @@ -0,0 +1,95 @@ > > +/* 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 > > + . */ > > + > > +#include > > + > > +/* 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 > > + > > +# define ISA_LEVEL (ISA_BASELINE | ISA_V2 | ISA_V3 | ISA_V4) > > + > > +# 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 2e4f8850f9..3c550e529a 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 > > . */ > > > > -/* 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; > > + > > Ok. > > > +/* 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..c263157c8c > > --- /dev/null > > +++ b/sysdeps/x86/tst-isa-level-1.c > > @@ -0,0 +1,74 @@ > > +/* 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 > > + . */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +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); > > +} > > + > > Ok. > > > +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); > > + /* Skip on x86-64-v4 platforms since dlopen always works. */ > > + if ((isa_level & GNU_PROPERTY_X86_ISA_1_V4) != 0) > > + return EXIT_UNSUPPORTED; > > + do_test_1 ("tst-isa-level-mod-1a.so", true); > > + do_test_1 ("tst-isa-level-mod-1b.so", false); > > + return EXIT_SUCCESS; > > +} > > + > > +#include > > Maybe use my suggestion to improve test coverage. Fixed. > > 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..3816536428 > > --- /dev/null > > +++ b/sysdeps/x86/tst-isa-level-mod-1.c > > @@ -0,0 +1,23 @@ > > +/* 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 > > + . */ > > + > > +int > > +test (void) > > +{ > > + return 0; > > +} > > Ok. > > > diff --git a/sysdeps/x86/tst-isa-level-mod-1a.c b/sysdeps/x86/tst-isa-level-mod-1a.c > > new file mode 100644 > > index 0000000000..4f026dd915 > > --- /dev/null > > +++ b/sysdeps/x86/tst-isa-level-mod-1a.c > > @@ -0,0 +1,2 @@ > > +#include > > +#include "tst-isa-level-mod-1.c" > > diff --git a/sysdeps/x86/tst-isa-level-mod-1b.c b/sysdeps/x86/tst-isa-level-mod-1b.c > > new file mode 100644 > > index 0000000000..d6fe0685a4 > > --- /dev/null > > +++ b/sysdeps/x86/tst-isa-level-mod-1b.c > > @@ -0,0 +1 @@ > > +#include "tst-isa-level-mod-1.c" > > Ok. > > > diff --git a/sysdeps/x86_64/dl-hwcaps-subdirs.c b/sysdeps/x86_64/dl-hwcaps-subdirs.c > > index 8810a822ef..e5640303f9 100644 > > --- a/sysdeps/x86_64/dl-hwcaps-subdirs.c > > +++ b/sysdeps/x86_64/dl-hwcaps-subdirs.c > > @@ -18,6 +18,7 @@ > > > > #include > > #include > > +#include > > > > 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; > > > > Ok. > > > diff --git a/sysdeps/x86_64/tst-glibc-hwcaps.c b/sysdeps/x86_64/tst-glibc-hwcaps.c > > index 3075a8286d..a041a9047d 100644 > > --- a/sysdeps/x86_64/tst-glibc-hwcaps.c > > +++ b/sysdeps/x86_64/tst-glibc-hwcaps.c > > @@ -19,7 +19,8 @@ > > #include > > #include > > #include > > -#include > > +#include > > +#include > > > > 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 > > > > Ok. 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. Reviewed-by: Adhemerval Zanella From 6630e06f9bcb361177d46c277cf8e67cbd722429 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" 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 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 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 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 + . */ + +#include +#include 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 < conftest2.S <&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 < conftest2.S < #include #include +#include #if IS_IN (libc) && !defined SHARED # include # include @@ -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 + 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 + . */ + +#include + +/* 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 + . */ + +#include + +/* 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 . */ -/* 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..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 + . */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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; + + 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 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 + . */ + +#include + +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 #include +#include 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 #include #include -#include +#include +#include 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