V8 [PATCH 2/2] x86: Install <sys/platform/x86.h> [BZ #26124]

Message ID 20200805230137.3572872-2-hjl.tools@gmail.com
State New
Headers show
Series
  • V8 [PATCH 2/2] x86: Install <sys/platform/x86.h> [BZ #26124]
Related show

Commit Message

Install <sys/platform/x86.h> so that programmers can do

 #if __has_include(<sys/platform/x86.h>)
 #include <sys/platform/x86.h>
 #endif
 ...

   if (CPU_FEATURE_USABLE (SSE2))
 ...
   if (CPU_FEATURE_USABLE (AVX2))
 ...

<sys/platform/x86.h> exports only:

enum
{
  COMMON_CPUID_INDEX_1 = 0,
  COMMON_CPUID_INDEX_7,
  COMMON_CPUID_INDEX_80000001,
  COMMON_CPUID_INDEX_D_ECX_1,
  COMMON_CPUID_INDEX_80000007,
  COMMON_CPUID_INDEX_80000008,
  COMMON_CPUID_INDEX_7_ECX_1,
  /* Keep the following line at the end.  */
  COMMON_CPUID_INDEX_MAX
};

struct cpuid_features
{
  struct cpuid_registers cpuid;
  struct cpuid_registers usable;
};

struct cpu_features
{
  struct cpu_features_basic basic;
  struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
};

/* Get a pointer to the CPU features structure.  */
extern const struct cpu_features *__x86_get_cpu_features
  (unsigned int max) __attribute__ ((const));

Since all feature checks are done through macros, programs compiled with
a newer <sys/platform/x86.h> are compatible with the older glibc binaries
as long as the layout of struct cpu_features is identical.  The features
array can be expanded with backward binary compatibility for both .o and
.so files.  When COMMON_CPUID_INDEX_MAX is increased to support new
processor features, __x86_get_cpu_features in the older glibc binaries
returns NULL and HAS_CPU_FEATURE/CPU_FEATURE_USABLE return false on the
new processor feature.  No new symbol version is neeeded.

Both CPU_FEATURE_USABLE and HAS_CPU_FEATURE are provided.  HAS_CPU_FEATURE
can be used to identify processor features.

Note: Although GCC has __builtin_cpu_supports, it only supports a subset
of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE.  It
doesn't support HAS_CPU_FEATURE.
---
 NEWS                                          |   2 +-
 manual/platform.texi                          | 517 ++++++++++++++++++
 sysdeps/i386/i686/multiarch/Makefile          |   4 -
 sysdeps/i386/i686/multiarch/test-multiarch.c  |   1 -
 sysdeps/unix/sysv/linux/i386/ld.abilist       |   1 +
 sysdeps/unix/sysv/linux/x86_64/64/ld.abilist  |   1 +
 sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |   1 +
 sysdeps/x86/Makefile                          |   4 +-
 sysdeps/x86/Versions                          |   4 +-
 sysdeps/x86/dl-get-cpu-features.c             |   6 +-
 sysdeps/x86/include/cpu-features.h            | 183 +++++++
 .../{cpu-features.h => sys/platform/x86.h}    | 150 +----
 sysdeps/x86/tst-cpu-features-cpuinfo.c        | 250 +++++++++
 sysdeps/x86/tst-cpu-features-supports.c       | 192 +++++++
 sysdeps/x86/tst-get-cpu-features.c            |   6 +-
 sysdeps/x86_64/fpu/math-tests-arch.h          |   2 +-
 sysdeps/x86_64/multiarch/Makefile             |   4 -
 sysdeps/x86_64/multiarch/test-multiarch.c     |  96 ----
 18 files changed, 1176 insertions(+), 248 deletions(-)
 delete mode 100644 sysdeps/i386/i686/multiarch/test-multiarch.c
 create mode 100644 sysdeps/x86/include/cpu-features.h
 rename sysdeps/x86/{cpu-features.h => sys/platform/x86.h} (81%)
 create mode 100644 sysdeps/x86/tst-cpu-features-cpuinfo.c
 create mode 100644 sysdeps/x86/tst-cpu-features-supports.c
 delete mode 100644 sysdeps/x86_64/multiarch/test-multiarch.c

-- 
2.26.2

Comments

On Wed, Aug 5, 2020 at 4:01 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>

> Install <sys/platform/x86.h> so that programmers can do

>

>  #if __has_include(<sys/platform/x86.h>)

>  #include <sys/platform/x86.h>

>  #endif

>  ...

>

>    if (CPU_FEATURE_USABLE (SSE2))

>  ...

>    if (CPU_FEATURE_USABLE (AVX2))

>  ...

>

> <sys/platform/x86.h> exports only:

>

> enum

> {

>   COMMON_CPUID_INDEX_1 = 0,

>   COMMON_CPUID_INDEX_7,

>   COMMON_CPUID_INDEX_80000001,

>   COMMON_CPUID_INDEX_D_ECX_1,

>   COMMON_CPUID_INDEX_80000007,

>   COMMON_CPUID_INDEX_80000008,

>   COMMON_CPUID_INDEX_7_ECX_1,

>   /* Keep the following line at the end.  */

>   COMMON_CPUID_INDEX_MAX

> };

>

> struct cpuid_features

> {

>   struct cpuid_registers cpuid;

>   struct cpuid_registers usable;

> };

>

> struct cpu_features

> {

>   struct cpu_features_basic basic;

>   struct cpuid_features features[COMMON_CPUID_INDEX_MAX];

> };

>

> /* Get a pointer to the CPU features structure.  */

> extern const struct cpu_features *__x86_get_cpu_features

>   (unsigned int max) __attribute__ ((const));

>

> Since all feature checks are done through macros, programs compiled with

> a newer <sys/platform/x86.h> are compatible with the older glibc binaries

> as long as the layout of struct cpu_features is identical.  The features

> array can be expanded with backward binary compatibility for both .o and

> .so files.  When COMMON_CPUID_INDEX_MAX is increased to support new

> processor features, __x86_get_cpu_features in the older glibc binaries

> returns NULL and HAS_CPU_FEATURE/CPU_FEATURE_USABLE return false on the

> new processor feature.  No new symbol version is neeeded.

>

> Both CPU_FEATURE_USABLE and HAS_CPU_FEATURE are provided.  HAS_CPU_FEATURE

> can be used to identify processor features.

>

> Note: Although GCC has __builtin_cpu_supports, it only supports a subset

> of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE.  It

> doesn't support HAS_CPU_FEATURE.

> ---

>  NEWS                                          |   2 +-

>  manual/platform.texi                          | 517 ++++++++++++++++++

>  sysdeps/i386/i686/multiarch/Makefile          |   4 -

>  sysdeps/i386/i686/multiarch/test-multiarch.c  |   1 -

>  sysdeps/unix/sysv/linux/i386/ld.abilist       |   1 +

>  sysdeps/unix/sysv/linux/x86_64/64/ld.abilist  |   1 +

>  sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |   1 +

>  sysdeps/x86/Makefile                          |   4 +-

>  sysdeps/x86/Versions                          |   4 +-

>  sysdeps/x86/dl-get-cpu-features.c             |   6 +-

>  sysdeps/x86/include/cpu-features.h            | 183 +++++++

>  .../{cpu-features.h => sys/platform/x86.h}    | 150 +----

>  sysdeps/x86/tst-cpu-features-cpuinfo.c        | 250 +++++++++

>  sysdeps/x86/tst-cpu-features-supports.c       | 192 +++++++

>  sysdeps/x86/tst-get-cpu-features.c            |   6 +-

>  sysdeps/x86_64/fpu/math-tests-arch.h          |   2 +-

>  sysdeps/x86_64/multiarch/Makefile             |   4 -

>  sysdeps/x86_64/multiarch/test-multiarch.c     |  96 ----

>  18 files changed, 1176 insertions(+), 248 deletions(-)

>  delete mode 100644 sysdeps/i386/i686/multiarch/test-multiarch.c

>  create mode 100644 sysdeps/x86/include/cpu-features.h

>  rename sysdeps/x86/{cpu-features.h => sys/platform/x86.h} (81%)

>  create mode 100644 sysdeps/x86/tst-cpu-features-cpuinfo.c

>  create mode 100644 sysdeps/x86/tst-cpu-features-supports.c

>  delete mode 100644 sysdeps/x86_64/multiarch/test-multiarch.c

>

> diff --git a/NEWS b/NEWS

> index 2937adc3f3..d19551c132 100644

> --- a/NEWS

> +++ b/NEWS

> @@ -9,7 +9,7 @@ Version 2.33

>

>  Major new features:

>

> -  [Add new features here]

> +* Add <sys/platform/x86.h> to provide query macros for x86 CPU features.

>

>  Deprecated and removed features, and other changes affecting compatibility:

>

> diff --git a/manual/platform.texi b/manual/platform.texi

> index 504addc956..2c145acdc3 100644

> --- a/manual/platform.texi

> +++ b/manual/platform.texi

> @@ -7,6 +7,7 @@

>  @menu

>  * PowerPC::           Facilities Specific to the PowerPC Architecture

>  * RISC-V::            Facilities Specific to the RISC-V Architecture

> +* X86::               Facilities Specific to the X86 Architecture

>  @end menu

>

>  @node PowerPC

> @@ -134,3 +135,519 @@ all threads in the current process.  Setting the

>  ordering on only the current thread is necessary.  All other flag bits are

>  reserved.

>  @end deftypefun

> +

> +@node X86

> +@appendixsec X86-specific Facilities

> +

> +Facilities specific to X86 that are not specific to a particular

> +operating system are declared in @file{sys/platform/x86.h}.

> +

> +@deftypefun {const struct cpu_features *} __x86_get_cpu_features (unsigned int @var{max})

> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}

> +Return a pointer to x86 CPU feature structure used by query macros for x86

> +CPU features.  If @var{max} exceeds @code{COMMON_CPUID_INDEX_MAX} which

> +is the limit of the CPUID leaves supported by @Theglibc{}, the function

> +returns @code{NULL}, indicating that the queried processor feature is

> +unsupported by @Theglibc{} run-time.

> +@end deftypefun

> +

> +@deftypefn Macro int HAS_CPU_FEATURE (@var{name})

> +This macro returns a nonzero value (true) if the processor has the feature

> +@var{name}.

> +@end deftypefn

> +

> +@deftypefn Macro int CPU_FEATURE_USABLE (@var{name})

> +This macro returns a nonzero value (true) if the processor has the feature

> +@var{name} and the feature is supported by the operating system.

> +@end deftypefn

> +

> +The supported processor features are:

> +

> +@itemize @bullet

> +

> +@item

> +@code{ACPI} -- Thermal Monitor and Software Controlled Clock Facilities.

> +

> +@item

> +@code{ADX} -- ADX instruction extensions.

> +

> +@item

> +@code{APIC} -- APIC On-Chip.

> +

> +@item

> +@code{AES} -- The AES instruction extensions.

> +

> +@item

> +@code{AMX_BF16} -- Tile computational operations on bfloat16 numbers.

> +

> +@item

> +@code{AMX_INT8} -- Tile computational operations on 8-bit numbers.

> +

> +@item

> +@code{AMX_TILE} -- Tile architecture.

> +

> +@item

> +@code{ARCH_CAPABILITIES} -- IA32_ARCH_CAPABILITIES MSR.

> +

> +@item

> +@code{AVX} -- The AVX instruction extensions.

> +

> +@item

> +@code{AVX2} -- The AVX2 instruction extensions.

> +

> +@item

> +@code{AVX512_4FMAPS} -- The AVX512_4FMAPS instruction extensions.

> +

> +@item

> +@code{AVX512_4VNNIW} -- The AVX512_4VNNIW instruction extensions.

> +

> +@item

> +@code{AVX512_BF16} -- The AVX512_BF16 instruction extensions.

> +

> +@item

> +@code{AVX512_BITALG} -- The AVX512_BITALG instruction extensions.

> +

> +@item

> +@code{AVX512_IFMA} -- The AVX512_IFMA instruction extensions.

> +

> +@item

> +@code{AVX512_VBMI} -- The AVX512_VBMI instruction extensions.

> +

> +@item

> +@code{AVX512_VBMI2} -- The AVX512_VBMI2 instruction extensions.

> +

> +@item

> +@code{AVX512_VNNI} -- The AVX512_VNNI instruction extensions.

> +

> +@item

> +@code{AVX512_VP2INTERSECT} -- The AVX512_VP2INTERSECT instruction

> +extensions.

> +

> +@item

> +@code{AVX512_VPOPCNTDQ} -- The AVX512_VPOPCNTDQ instruction extensions.

> +

> +@item

> +@code{AVX512BW} -- The AVX512BW instruction extensions.

> +

> +@item

> +@code{AVX512CD} -- The AVX512CD instruction extensions.

> +

> +@item

> +@code{AVX512ER} -- The AVX512ER instruction extensions.

> +

> +@item

> +@code{AVX512DQ} -- The AVX512DQ instruction extensions.

> +

> +@item

> +@code{AVX512F} -- The AVX512F instruction extensions.

> +

> +@item

> +@code{AVX512PF} -- The AVX512PF instruction extensions.

> +

> +@item

> +@code{AVX512VL} -- The AVX512VL instruction extensions.

> +

> +@item

> +@code{BMI1} -- BMI1 instructions.

> +

> +@item

> +@code{BMI2} -- BMI2 instructions.

> +

> +@item

> +@code{CLDEMOTE} -- CLDEMOTE instruction.

> +

> +@item

> +@code{CLFLUSHOPT} -- CLFLUSHOPT instruction.

> +

> +@item

> +@code{CLFSH} -- CLFLUSH instruction.

> +

> +@item

> +@code{CLWB} -- CLWB instruction.

> +

> +@item

> +@code{CMOV} -- Conditional Move instructions.

> +

> +@item

> +@code{CMPXCHG16B} -- CMPXCHG16B instruction.

> +

> +@item

> +@code{CNXT_ID} -- L1 Context ID.

> +

> +@item

> +@code{CORE_CAPABILITIES} -- IA32_CORE_CAPABILITIES MSR.

> +

> +@item

> +@code{CX8} -- CMPXCHG8B instruction.

> +

> +@item

> +@code{DCA} -- Data prefetch from a memory mapped device.

> +

> +@item

> +@code{DE} -- Debugging Extensions.

> +

> +@item

> +@code{DEPR_FPU_CS_DS} -- Deprecates FPU CS and FPU DS values.

> +

> +@item

> +@code{DS} -- Debug Store.

> +

> +@item

> +@code{DS_CPL} -- CPL Qualified Debug Store.

> +

> +@item

> +@code{DTES64} -- 64-bit DS Area.

> +

> +@item

> +@code{EIST} -- Enhanced Intel SpeedStep technology.

> +

> +@item

> +@code{ENQCMD} -- Enqueue Stores instructions.

> +

> +@item

> +@code{ERMS} -- Enhanced REP MOVSB/STOSB.

> +

> +@item

> +@code{F16C} -- 16-bit floating-point conversion instructions.

> +

> +@item

> +@code{FMA} -- FMA extensions using YMM state.

> +

> +@item

> +@code{FMA4} -- FMA4 instruction extensions.

> +

> +@item

> +@code{FPU} -- X87 Floating Point Unit On-Chip.

> +

> +@item

> +@code{FSGSBASE} -- RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE instructions.

> +

> +@item

> +@code{FSRM} -- Fast Short REP MOV.

> +

> +@item

> +@code{FXSR} -- FXSAVE and FXRSTOR instructions.

> +

> +@item

> +@code{GFNI} -- GFNI instruction extensions.

> +

> +@item

> +@code{HLE} -- HLE instruction extensions.

> +

> +@item

> +@code{HTT} -- Max APIC IDs reserved field is Valid.

> +

> +@item

> +@code{HYBRID} -- Hybrid processor.

> +

> +@item

> +@code{IBRS_IBPB} -- Indirect branch restricted speculation (IBRS) and

> +the indirect branch predictor barrier (IBPB).

> +

> +@item

> +@code{IBT} -- Intel Indirect Branch Tracking instruction extensions.

> +

> +@item

> +@code{INVARIANT_TSC} -- Invariant TSC.

> +

> +@item

> +@code{INVPCID} -- INVPCID instruction.

> +

> +@item

> +@code{L1D_FLUSH} -- IA32_FLUSH_CMD MSR.

> +

> +@item

> +@code{LAHF64_SAHF64} -- LAHF/SAHF available in 64-bit mode.

> +

> +@item

> +@code{LM} -- Long mode.

> +

> +@item

> +@code{LWP} -- Lightweight profiling.

> +

> +@item

> +@code{LZCNT} -- LZCNT instruction.

> +

> +@item

> +@code{MCA} -- Machine Check Architecture.

> +

> +@item

> +@code{MCE} -- Machine Check Exception.

> +

> +@item

> +@code{MD_CLEAR} -- MD_CLEAR.

> +

> +@item

> +@code{MMX} -- Intel MMX Technology.

> +

> +@item

> +@code{MONITOR} --  MONITOR/MWAIT instructions.

> +

> +@item

> +@code{MOVBE} -- MOVBE instruction.

> +

> +@item

> +@code{MOVDIRI} -- MOVDIRI instruction.

> +

> +@item

> +@code{MOVDIR64B} -- MOVDIR64B instruction.

> +

> +@item

> +@code{MPX} -- Intel Memory Protection Extensions.

> +

> +@item

> +@code{MSR} -- Model Specific Registers RDMSR and WRMSR instructions.

> +

> +@item

> +@code{MTRR} -- Memory Type Range Registers.

> +

> +@item

> +@code{NX} -- No-execute page protection.

> +

> +@item

> +@code{OSPKE} -- OS has set CR4.PKE to enable protection keys.

> +

> +@item

> +@code{OSXSAVE} -- The OS has set CR4.OSXSAVE[bit 18] to enable

> +XSETBV/XGETBV instructions to access XCR0 and to support processor

> +extended state management using XSAVE/XRSTOR.

> +

> +@item

> +@code{PAE} -- Physical Address Extension.

> +

> +@item

> +@code{PAGE1GB} -- 1-GByte page.

> +

> +@item

> +@code{PAT} -- Page Attribute Table.

> +

> +@item

> +@code{PBE} -- Pending Break Enable.

> +

> +@item

> +@code{PCID} -- Process-context identifiers.

> +

> +@item

> +@code{PCLMULQDQ} -- PCLMULQDQ instruction.

> +

> +@item

> +@code{PCONFIG} -- PCONFIG instruction.

> +

> +@item

> +@code{PDCM} -- Perfmon and Debug Capability.

> +

> +@item

> +@code{PGE} -- Page Global Bit.

> +

> +@item

> +@code{PKS} -- Protection keys for supervisor-mode pages.

> +

> +@item

> +@code{PKU} -- Protection keys for user-mode pages.

> +

> +@item

> +@code{POPCNT} -- POPCNT instruction.

> +

> +@item

> +@code{PREFETCHW} -- PREFETCHW instruction.

> +

> +@item

> +@code{PREFETCHWT1} -- PREFETCHWT1 instruction.

> +

> +@item

> +@code{PSE} -- Page Size Extension.

> +

> +@item

> +@code{PSE_36} -- 36-Bit Page Size Extension.

> +

> +@item

> +@code{PSN} -- Processor Serial Number.

> +

> +@item

> +@code{RDPID} -- RDPID instruction.

> +

> +@item

> +@code{RDRAND} -- RDRAND instruction.

> +

> +@item

> +@code{RDSEED} -- RDSEED instruction.

> +

> +@item

> +@code{RDT_A} -- Intel Resource Director Technology (Intel RDT) Allocation

> +capability.

> +

> +@item

> +@code{RDT_M} -- Intel Resource Director Technology (Intel RDT) Monitoring

> +capability.

> +

> +@item

> +@code{RDTSCP} -- RDTSCP instruction.

> +

> +@item

> +@code{RTM} -- RTM instruction extensions.

> +

> +@item

> +@code{SDBG} -- IA32_DEBUG_INTERFACE MSR for silicon debug.

> +

> +@item

> +@code{SEP} -- SYSENTER and SYSEXIT instructions.

> +

> +@item

> +@code{SERIALIZE} -- SERIALIZE instruction.

> +

> +@item

> +@code{SGX} -- Intel Software Guard Extensions.

> +

> +@item

> +@code{SGX_LC} -- SGX Launch Configuration.

> +

> +@item

> +@code{SHA} -- SHA instruction extensions.

> +

> +@item

> +@code{SHSTK} -- Intel Shadow Stack instruction extensions.

> +

> +@item

> +@code{SMAP} -- Supervisor-Mode Access Prevention.

> +

> +@item

> +@code{SMEP} -- Supervisor-Mode Execution Prevention.

> +

> +@item

> +@code{SMX} -- Safer Mode Extensions.

> +

> +@item

> +@code{SS} -- Self Snoop.

> +

> +@item

> +@code{SSBD} -- Speculative Store Bypass Disable (SSBD).

> +

> +@item

> +@code{SSE} -- Streaming SIMD Extensions.

> +

> +@item

> +@code{SSE2} -- Streaming SIMD Extensions 2.

> +

> +@item

> +@code{SSE3} -- Streaming SIMD Extensions 3.

> +

> +@item

> +@code{SSE4_1} -- Streaming SIMD Extensions 4.1.

> +

> +@item

> +@code{SSE4_2} -- Streaming SIMD Extensions 4.2.

> +

> +@item

> +@code{SSE4A} -- SSE4A instruction extensions.

> +

> +@item

> +@code{SSSE3} -- Supplemental Streaming SIMD Extensions 3.

> +

> +@item

> +@code{STIBP} -- Single thread indirect branch predictors (STIBP).

> +

> +@item

> +@code{SVM} -- Secure Virtual Machine.

> +

> +@item

> +@code{SYSCALL_SYSRET} -- SYSCALL/SYSRET instructions.

> +

> +@item

> +@code{TBM} -- Trailing bit manipulation instructions.

> +

> +@item

> +@code{TM} -- Thermal Monitor.

> +

> +@item

> +@code{TM2} -- Thermal Monitor 2.

> +

> +@item

> +@code{TRACE} -- Intel Processor Trace.

> +

> +@item

> +@code{TSC} -- Time Stamp Counter.  RDTSC instruction.

> +

> +@item

> +@code{TSC_ADJUST} -- IA32_TSC_ADJUST MSR.

> +

> +@item

> +@code{TSC_DEADLINE} -- Local APIC timer supports one-shot operation

> +using a TSC deadline value.

> +

> +@item

> +@code{TSXLDTRK} -- TSXLDTRK instructions.

> +

> +@item

> +@code{UMIP} -- User-mode instruction prevention.

> +

> +@item

> +@code{VAES} -- VAES instruction extensions.

> +

> +@item

> +@code{VME} -- Virtual 8086 Mode Enhancements.

> +

> +@item

> +@code{VMX} -- Virtual Machine Extensions.

> +

> +@item

> +@code{VPCLMULQDQ} -- VPCLMULQDQ instruction.

> +

> +@item

> +@code{WAITPKG} -- WAITPKG instruction extensions.

> +

> +@item

> +@code{WBNOINVD} -- WBINVD/WBNOINVD instructions.

> +

> +@item

> +@code{X2APIC} -- x2APIC.

> +

> +@item

> +@code{XFD} -- Extended Feature Disable (XFD).

> +

> +@item

> +@code{XGETBV_ECX_1} -- XGETBV with ECX = 1.

> +

> +@item

> +@code{XOP} -- XOP instruction extensions.

> +

> +@item

> +@code{XSAVE} -- The XSAVE/XRSTOR processor extended states feature, the

> +XSETBV/XGETBV instructions, and XCR0.

> +

> +@item

> +@code{XSAVEC} -- XSAVEC instruction.

> +

> +@item

> +@code{XSAVEOPT} -- XSAVEOPT instruction.

> +

> +@item

> +@code{XSAVES} -- XSAVES/XRSTORS instructions.

> +

> +@item

> +@code{XTPRUPDCTRL} -- xTPR Update Control.

> +

> +@end itemize

> +

> +You could query if a processor supports @code{AVX} with:

> +

> +@smallexample

> +#include <sys/platform/x86.h>

> +

> +int

> +support_avx (void)

> +@{

> +  return HAS_CPU_FEATURE (AVX);

> +@}

> +@end smallexample

> +

> +and if @code{AVX} is usable with:

> +

> +@smallexample

> +#include <sys/platform/x86.h>

> +

> +int

> +usable_avx (void)

> +@{

> +  return CPU_FEATURE_USABLE (AVX);

> +@}

> +@end smallexample

> diff --git a/sysdeps/i386/i686/multiarch/Makefile b/sysdeps/i386/i686/multiarch/Makefile

> index bf75a9947f..c4897922d7 100644

> --- a/sysdeps/i386/i686/multiarch/Makefile

> +++ b/sysdeps/i386/i686/multiarch/Makefile

> @@ -1,7 +1,3 @@

> -ifeq ($(subdir),csu)

> -tests += test-multiarch

> -endif

> -

>  ifeq ($(subdir),string)

>  gen-as-const-headers += locale-defines.sym

>  sysdep_routines += bzero-sse2 memset-sse2 memcpy-ssse3 mempcpy-ssse3 \

> diff --git a/sysdeps/i386/i686/multiarch/test-multiarch.c b/sysdeps/i386/i686/multiarch/test-multiarch.c

> deleted file mode 100644

> index 593cfec273..0000000000

> --- a/sysdeps/i386/i686/multiarch/test-multiarch.c

> +++ /dev/null

> @@ -1 +0,0 @@

> -#include <sysdeps/x86_64/multiarch/test-multiarch.c>

> diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist

> index 0478e22071..04655651b0 100644

> --- a/sysdeps/unix/sysv/linux/i386/ld.abilist

> +++ b/sysdeps/unix/sysv/linux/i386/ld.abilist

> @@ -3,3 +3,4 @@ GLIBC_2.1 __libc_stack_end D 0x4

>  GLIBC_2.1 _dl_mcount F

>  GLIBC_2.3 ___tls_get_addr F

>  GLIBC_2.3 __tls_get_addr F

> +GLIBC_2.33 __x86_get_cpu_features F

> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist

> index d3cdf7611e..e632c6198e 100644

> --- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist

> +++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist

> @@ -2,3 +2,4 @@ GLIBC_2.2.5 __libc_stack_end D 0x8

>  GLIBC_2.2.5 _dl_mcount F

>  GLIBC_2.2.5 _r_debug D 0x28

>  GLIBC_2.3 __tls_get_addr F

> +GLIBC_2.33 __x86_get_cpu_features F

> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist

> index c70bccf782..9d9d0befde 100644

> --- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist

> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist

> @@ -2,3 +2,4 @@ GLIBC_2.16 __libc_stack_end D 0x4

>  GLIBC_2.16 __tls_get_addr F

>  GLIBC_2.16 _dl_mcount F

>  GLIBC_2.16 _r_debug D 0x14

> +GLIBC_2.33 __x86_get_cpu_features F

> diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile

> index a6736aef25..c369faf00d 100644

> --- a/sysdeps/x86/Makefile

> +++ b/sysdeps/x86/Makefile

> @@ -4,8 +4,10 @@ endif

>

>  ifeq ($(subdir),elf)

>  sysdep-dl-routines += dl-get-cpu-features

> +sysdep_headers += sys/platform/x86.h

>

> -tests += tst-get-cpu-features tst-get-cpu-features-static

> +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

>  endif

>

> diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions

> index e02923708e..59db578a9d 100644

> --- a/sysdeps/x86/Versions

> +++ b/sysdeps/x86/Versions

> @@ -1,5 +1,5 @@

>  ld {

> -  GLIBC_PRIVATE {

> -    __get_cpu_features;

> +  GLIBC_2.33 {

> +    __x86_get_cpu_features;

>    }

>  }

> diff --git a/sysdeps/x86/dl-get-cpu-features.c b/sysdeps/x86/dl-get-cpu-features.c

> index 9d61cd56be..5f9e46b0c6 100644

> --- a/sysdeps/x86/dl-get-cpu-features.c

> +++ b/sysdeps/x86/dl-get-cpu-features.c

> @@ -18,10 +18,12 @@

>

>  #include <ldsodefs.h>

>

> -#undef __get_cpu_features

> +#undef __x86_get_cpu_features

>

>  const struct cpu_features *

> -__get_cpu_features (void)

> +__x86_get_cpu_features (unsigned int max)

>  {

> +  if (max > COMMON_CPUID_INDEX_MAX)

> +    return NULL;

>    return &GLRO(dl_x86_cpu_features);

>  }

> diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h

> new file mode 100644

> index 0000000000..dcf29b6fe8

> --- /dev/null

> +++ b/sysdeps/x86/include/cpu-features.h

> @@ -0,0 +1,183 @@

> +/* Data structure for x86 CPU features.

> +   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/>.  */

> +

> +#ifndef        _PRIVATE_CPU_FEATURES_H

> +#define        _PRIVATE_CPU_FEATURES_H 1

> +

> +#ifdef _CPU_FEATURES_H

> +# error this should be impossible

> +#endif

> +

> +#ifndef _ISOMAC

> +/* Get most of the contents from the public header, but we define a

> +   different `struct cpu_features' type for private use.  */

> +# define cpu_features          cpu_features_public

> +# define __x86_get_cpu_features        __x86_get_cpu_features_public

> +#endif

> +

> +#include <sysdeps/x86/sys/platform/x86.h>

> +

> +#ifndef _ISOMAC

> +

> +# undef        cpu_features

> +# undef __x86_get_cpu_features

> +# define __get_cpu_features()  __x86_get_cpu_features (0)

> +

> +enum

> +{

> +  /* The integer bit array index for the first set of preferred feature

> +     bits.  */

> +  PREFERRED_FEATURE_INDEX_1 = 0,

> +  /* The current maximum size of the feature integer bit array.  */

> +  PREFERRED_FEATURE_INDEX_MAX

> +};

> +

> +/* Only used directly in cpu-features.c.  */

> +# define CPU_FEATURE_SET(ptr, name) \

> +  ptr->features[index_cpu_##name].usable.reg_##name |= bit_cpu_##name;

> +# define CPU_FEATURE_UNSET(ptr, name) \

> +  ptr->features[index_cpu_##name].usable.reg_##name &= ~bit_cpu_##name;

> +# define CPU_FEATURE_SET_USABLE(ptr, name) \

> +  ptr->features[index_cpu_##name].usable.reg_##name \

> +     |= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name;

> +# define CPU_FEATURE_PREFERRED_P(ptr, name) \

> +  ((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0)

> +# define CPU_FEATURE_CPU_P(ptr, name) \

> +  CPU_FEATURE_CHECK_P (ptr, name, cpuid)

> +

> +/* HAS_CPU_FEATURE evaluates to true if CPU supports the feature.  */

> +# undef HAS_CPU_FEATURE

> +# define HAS_CPU_FEATURE(name) \

> +  CPU_FEATURE_CPU_P (__x86_get_cpu_features (0), name)

> +/* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */

> +# undef CPU_FEATURE_USABLE

> +# define CPU_FEATURE_USABLE(name) \

> +  CPU_FEATURE_USABLE_P (__x86_get_cpu_features (0), name)

> +/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at

> +   runtime.  */

> +# define CPU_FEATURE_PREFERRED(name) \

> +  CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name)

> +

> +# define CPU_FEATURES_CPU_P(ptr, name) \

> +  CPU_FEATURE_CPU_P (ptr, name)

> +# define CPU_FEATURES_ARCH_P(ptr, name) \

> +  CPU_FEATURE_PREFERRED_P (ptr, name)

> +# define HAS_ARCH_FEATURE(name) \

> +  CPU_FEATURE_PREFERRED (name)

> +

> +/* PREFERRED_FEATURE_INDEX_1.  */

> +# define bit_arch_I586                         (1u << 0)

> +# define bit_arch_I686                         (1u << 1)

> +# define bit_arch_Fast_Rep_String              (1u << 2)

> +# define bit_arch_Fast_Copy_Backward           (1u << 3)

> +# define bit_arch_Fast_Unaligned_Load          (1u << 4)

> +# define bit_arch_Fast_Unaligned_Copy          (1u << 5)

> +# define bit_arch_Slow_BSF                     (1u << 6)

> +# define bit_arch_Slow_SSE4_2                  (1u << 7)

> +# define bit_arch_AVX_Fast_Unaligned_Load      (1u << 8)

> +# define bit_arch_Prefer_MAP_32BIT_EXEC                (1u << 9)

> +# define bit_arch_Prefer_PMINUB_for_stringop   (1u << 10)

> +# define bit_arch_Prefer_No_VZEROUPPER         (1u << 11)

> +# define bit_arch_Prefer_ERMS                  (1u << 12)

> +# define bit_arch_Prefer_FSRM                  (1u << 13)

> +# define bit_arch_Prefer_No_AVX512             (1u << 14)

> +# define bit_arch_MathVec_Prefer_No_AVX512     (1u << 15)

> +

> +# define index_arch_Fast_Rep_String            PREFERRED_FEATURE_INDEX_1

> +# define index_arch_Fast_Copy_Backward         PREFERRED_FEATURE_INDEX_1

> +# define index_arch_Slow_BSF                   PREFERRED_FEATURE_INDEX_1

> +# define index_arch_Fast_Unaligned_Load                PREFERRED_FEATURE_INDEX_1

> +# define index_arch_Prefer_PMINUB_for_stringop         PREFERRED_FEATURE_INDEX_1

> +# define index_arch_Fast_Unaligned_Copy                PREFERRED_FEATURE_INDEX_1

> +# define index_arch_I586                       PREFERRED_FEATURE_INDEX_1

> +# define index_arch_I686                       PREFERRED_FEATURE_INDEX_1

> +# define index_arch_Slow_SSE4_2                        PREFERRED_FEATURE_INDEX_1

> +# define index_arch_AVX_Fast_Unaligned_Load    PREFERRED_FEATURE_INDEX_1

> +# define index_arch_Prefer_MAP_32BIT_EXEC      PREFERRED_FEATURE_INDEX_1

> +# define index_arch_Prefer_No_VZEROUPPER       PREFERRED_FEATURE_INDEX_1

> +# define index_arch_Prefer_ERMS                        PREFERRED_FEATURE_INDEX_1

> +# define index_arch_Prefer_No_AVX512           PREFERRED_FEATURE_INDEX_1

> +# define index_arch_MathVec_Prefer_No_AVX512   PREFERRED_FEATURE_INDEX_1

> +# define index_arch_Prefer_FSRM                        PREFERRED_FEATURE_INDEX_1

> +

> +/* XCR0 Feature flags.  */

> +# define bit_XMM_state         (1u << 1)

> +# define bit_YMM_state         (1u << 2)

> +# define bit_Opmask_state      (1u << 5)

> +# define bit_ZMM0_15_state     (1u << 6)

> +# define bit_ZMM16_31_state    (1u << 7)

> +# define bit_XTILECFG_state    (1u << 17)

> +# define bit_XTILEDATA_state   (1u << 18)

> +

> +struct cpu_features

> +{

> +  struct cpu_features_basic basic;

> +  struct cpuid_features features[COMMON_CPUID_INDEX_MAX];

> +  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];

> +  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long

> +     int so that we use

> +

> +       sub xsave_state_size_offset(%rip) %RSP_LP

> +

> +     in _dl_runtime_resolve.  */

> +  unsigned long int xsave_state_size;

> +  /* The full state size for XSAVE when XSAVEC is disabled by

> +

> +     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC

> +   */

> +  unsigned int xsave_state_full_size;

> +  /* Data cache size for use in memory and string routines, typically

> +     L1 size.  */

> +  unsigned long int data_cache_size;

> +  /* Shared cache size for use in memory and string routines, typically

> +     L2 or L3 size.  */

> +  unsigned long int shared_cache_size;

> +  /* Threshold to use non temporal store.  */

> +  unsigned long int non_temporal_threshold;

> +  /* Threshold to use "rep movsb".  */

> +  unsigned long int rep_movsb_threshold;

> +  /* Threshold to use "rep stosb".  */

> +  unsigned long int rep_stosb_threshold;

> +};

> +

> +# if defined (_LIBC) && !IS_IN (nonlib)

> +/* Unused for x86.  */

> +#  define INIT_ARCH()

> +#  define __x86_get_cpu_features(max) (&GLRO(dl_x86_cpu_features))

> +# endif

> +

> +# ifdef __x86_64__

> +#  define HAS_CPUID 1

> +# elif (defined __i586__ || defined __pentium__        \

> +       || defined __geode__ || defined __k6__)

> +#  define HAS_CPUID 1

> +#  define HAS_I586 1

> +#  define HAS_I686 HAS_ARCH_FEATURE (I686)

> +# elif defined __i486__

> +#  define HAS_CPUID 0

> +#  define HAS_I586 HAS_ARCH_FEATURE (I586)

> +#  define HAS_I686 HAS_ARCH_FEATURE (I686)

> +# else

> +#  define HAS_CPUID 1

> +#  define HAS_I586 1

> +#  define HAS_I686 1

> +# endif

> +

> +#endif /* !_ISOMAC */

> +

> +#endif /* include/cpu-features.h */

> diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/sys/platform/x86.h

> similarity index 81%

> rename from sysdeps/x86/cpu-features.h

> rename to sysdeps/x86/sys/platform/x86.h

> index 78fcec251e..bf3727ebc0 100644

> --- a/sysdeps/x86/cpu-features.h

> +++ b/sysdeps/x86/sys/platform/x86.h

> @@ -1,4 +1,5 @@

> -/* This file is part of the GNU C Library.

> +/* Data structure for x86 CPU features.

> +   This file is part of the GNU C Library.

>     Copyright (C) 2008-2020 Free Software Foundation, Inc.

>

>     The GNU C Library is free software; you can redistribute it and/or

> @@ -15,17 +16,8 @@

>     License along with the GNU C Library; if not, see

>     <https://www.gnu.org/licenses/>.  */

>

> -#ifndef cpu_features_h

> -#define cpu_features_h

> -

> -enum

> -{

> -  /* The integer bit array index for the first set of preferred feature

> -     bits.  */

> -  PREFERRED_FEATURE_INDEX_1 = 0,

> -  /* The current maximum size of the feature integer bit array.  */

> -  PREFERRED_FEATURE_INDEX_MAX

> -};

> +#ifndef _SYS_PLATFORM_X86_H

> +#define _SYS_PLATFORM_X86_H

>

>  enum

>  {

> @@ -76,73 +68,32 @@ struct cpu_features

>  {

>    struct cpu_features_basic basic;

>    struct cpuid_features features[COMMON_CPUID_INDEX_MAX];

> -  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];

> -  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long

> -     int so that we use

> -

> -       sub xsave_state_size_offset(%rip) %RSP_LP

> -

> -     in _dl_runtime_resolve.  */

> -  unsigned long int xsave_state_size;

> -  /* The full state size for XSAVE when XSAVEC is disabled by

> -

> -     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC

> -   */

> -  unsigned int xsave_state_full_size;

> -  /* Data cache size for use in memory and string routines, typically

> -     L1 size.  */

> -  unsigned long int data_cache_size;

> -  /* Shared cache size for use in memory and string routines, typically

> -     L2 or L3 size.  */

> -  unsigned long int shared_cache_size;

> -  /* Threshold to use non temporal store.  */

> -  unsigned long int non_temporal_threshold;

> -  /* Threshold to use "rep movsb".  */

> -  unsigned long int rep_movsb_threshold;

> -  /* Threshold to use "rep stosb".  */

> -  unsigned long int rep_stosb_threshold;

>  };

>

> -/* Used from outside of glibc to get access to the CPU features

> -   structure.  */

> -extern const struct cpu_features *__get_cpu_features (void)

> +/* Get a pointer to the CPU features structure.  */

> +extern const struct cpu_features *__x86_get_cpu_features (unsigned int)

>       __attribute__ ((const));

>

> -/* Only used directly in cpu-features.c.  */

>  #define CPU_FEATURE_CHECK_P(ptr, name, check) \

>    ((ptr->features[index_cpu_##name].check.reg_##name \

>      & bit_cpu_##name) != 0)

> -#define CPU_FEATURE_SET(ptr, name) \

> -  ptr->features[index_cpu_##name].usable.reg_##name |= bit_cpu_##name;

> -#define CPU_FEATURE_UNSET(ptr, name) \

> -  ptr->features[index_cpu_##name].usable.reg_##name &= ~bit_cpu_##name;

> -#define CPU_FEATURE_SET_USABLE(ptr, name) \

> -  ptr->features[index_cpu_##name].usable.reg_##name \

> -     |= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name;

> -#define CPU_FEATURE_PREFERRED_P(ptr, name) \

> -  ((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0)

>  #define CPU_FEATURE_CPU_P(ptr, name) \

>    CPU_FEATURE_CHECK_P (ptr, name, cpuid)

>  #define CPU_FEATURE_USABLE_P(ptr, name) \

>    CPU_FEATURE_CHECK_P (ptr, name, usable)

>

>  /* HAS_CPU_FEATURE evaluates to true if CPU supports the feature.  */

> -#define HAS_CPU_FEATURE(name) \

> -  CPU_FEATURE_CPU_P (__get_cpu_features (), name)

> +#define HAS_CPU_FEATURE(name)                                  \

> +  (__extension__                                               \

> +   ({ const struct cpu_features *__ptr =                       \

> +       __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX);        \

> +      __ptr && CPU_FEATURE_CPU_P (__ptr, name); }))

>  /* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */

> -#define CPU_FEATURE_USABLE(name) \

> -  CPU_FEATURE_USABLE_P (__get_cpu_features (), name)

> -/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at

> -   runtime.  */

> -#define CPU_FEATURE_PREFERRED(name) \

> -  CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name)

> -

> -#define CPU_FEATURES_CPU_P(ptr, name) \

> -  CPU_FEATURE_CPU_P (ptr, name)

> -#define CPU_FEATURES_ARCH_P(ptr, name) \

> -  CPU_FEATURE_PREFERRED_P (ptr, name)

> -#define HAS_ARCH_FEATURE(name) \

> -  CPU_FEATURE_PREFERRED (name)

> +#define CPU_FEATURE_USABLE(name)                               \

> +  (__extension__                                               \

> +   ({ const struct cpu_features *__ptr =                       \

> +       __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX);        \

> +      __ptr && CPU_FEATURE_USABLE_P (__ptr, name); }))

>

>  /* CPU features.  */

>

> @@ -787,71 +738,4 @@ extern const struct cpu_features *__get_cpu_features (void)

>  /* EAX.  */

>  #define reg_AVX512_BF16                eax

>

> -/* FEATURE_INDEX_2.  */

> -#define bit_arch_I586                          (1u << 0)

> -#define bit_arch_I686                          (1u << 1)

> -#define bit_arch_Fast_Rep_String               (1u << 2)

> -#define bit_arch_Fast_Copy_Backward            (1u << 3)

> -#define bit_arch_Fast_Unaligned_Load           (1u << 4)

> -#define bit_arch_Fast_Unaligned_Copy           (1u << 5)

> -#define bit_arch_Slow_BSF                      (1u << 6)

> -#define bit_arch_Slow_SSE4_2                   (1u << 7)

> -#define bit_arch_AVX_Fast_Unaligned_Load       (1u << 8)

> -#define bit_arch_Prefer_MAP_32BIT_EXEC         (1u << 9)

> -#define bit_arch_Prefer_PMINUB_for_stringop    (1u << 10)

> -#define bit_arch_Prefer_No_VZEROUPPER          (1u << 11)

> -#define bit_arch_Prefer_ERMS                   (1u << 12)

> -#define bit_arch_Prefer_FSRM                   (1u << 13)

> -#define bit_arch_Prefer_No_AVX512              (1u << 14)

> -#define bit_arch_MathVec_Prefer_No_AVX512      (1u << 15)

> -

> -#define index_arch_Fast_Rep_String             PREFERRED_FEATURE_INDEX_1

> -#define index_arch_Fast_Copy_Backward          PREFERRED_FEATURE_INDEX_1

> -#define index_arch_Slow_BSF                    PREFERRED_FEATURE_INDEX_1

> -#define index_arch_Fast_Unaligned_Load         PREFERRED_FEATURE_INDEX_1

> -#define index_arch_Prefer_PMINUB_for_stringop  PREFERRED_FEATURE_INDEX_1

> -#define index_arch_Fast_Unaligned_Copy         PREFERRED_FEATURE_INDEX_1

> -#define index_arch_I586                                PREFERRED_FEATURE_INDEX_1

> -#define index_arch_I686                                PREFERRED_FEATURE_INDEX_1

> -#define index_arch_Slow_SSE4_2                 PREFERRED_FEATURE_INDEX_1

> -#define index_arch_AVX_Fast_Unaligned_Load     PREFERRED_FEATURE_INDEX_1

> -#define index_arch_Prefer_MAP_32BIT_EXEC       PREFERRED_FEATURE_INDEX_1

> -#define index_arch_Prefer_No_VZEROUPPER                PREFERRED_FEATURE_INDEX_1

> -#define index_arch_Prefer_ERMS                 PREFERRED_FEATURE_INDEX_1

> -#define index_arch_Prefer_No_AVX512            PREFERRED_FEATURE_INDEX_1

> -#define index_arch_MathVec_Prefer_No_AVX512    PREFERRED_FEATURE_INDEX_1

> -#define index_arch_Prefer_FSRM                 PREFERRED_FEATURE_INDEX_1

> -

> -/* XCR0 Feature flags.  */

> -#define bit_XMM_state          (1u << 1)

> -#define bit_YMM_state          (1u << 2)

> -#define bit_Opmask_state       (1u << 5)

> -#define bit_ZMM0_15_state      (1u << 6)

> -#define bit_ZMM16_31_state     (1u << 7)

> -#define bit_XTILECFG_state     (1u << 17)

> -#define bit_XTILEDATA_state    (1u << 18)

> -

> -# if defined (_LIBC) && !IS_IN (nonlib)

> -/* Unused for x86.  */

> -#  define INIT_ARCH()

> -#  define __get_cpu_features() (&GLRO(dl_x86_cpu_features))

> -# endif

> -

> -#ifdef __x86_64__

> -# define HAS_CPUID 1

> -#elif (defined __i586__ || defined __pentium__ \

> -       || defined __geode__ || defined __k6__)

> -# define HAS_CPUID 1

> -# define HAS_I586 1

> -# define HAS_I686 HAS_ARCH_FEATURE (I686)

> -#elif defined __i486__

> -# define HAS_CPUID 0

> -# define HAS_I586 HAS_ARCH_FEATURE (I586)

> -# define HAS_I686 HAS_ARCH_FEATURE (I686)

> -#else

> -# define HAS_CPUID 1

> -# define HAS_I586 1

> -# define HAS_I686 1

> -#endif

> -

> -#endif  /* cpu_features_h */

> +#endif  /* _SYS_PLATFORM_X86_H */

> diff --git a/sysdeps/x86/tst-cpu-features-cpuinfo.c b/sysdeps/x86/tst-cpu-features-cpuinfo.c

> new file mode 100644

> index 0000000000..96277284d1

> --- /dev/null

> +++ b/sysdeps/x86/tst-cpu-features-cpuinfo.c

> @@ -0,0 +1,250 @@

> +/* Test CPU feature data against /proc/cpuinfo.

> +   This file is part of the GNU C Library.

> +   Copyright (C) 2012-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>

> +#include <stdio.h>

> +#include <stdlib.h>

> +#include <string.h>

> +

> +static char *cpu_flags;

> +

> +/* Search for flags in /proc/cpuinfo and store line

> +   in cpu_flags.  */

> +void

> +get_cpuinfo (void)

> +{

> +  FILE *f;

> +  char *line = NULL;

> +  size_t len = 0;

> +  ssize_t read;

> +

> +  f = fopen ("/proc/cpuinfo", "r");

> +  if (f == NULL)

> +    {

> +      printf ("cannot open /proc/cpuinfo\n");

> +      exit (1);

> +    }

> +

> +  while ((read = getline (&line, &len, f)) != -1)

> +    {

> +      if (strncmp (line, "flags", 5) == 0)

> +       {

> +         cpu_flags = strdup (line);

> +         break;

> +       }

> +    }

> +  fclose (f);

> +  free (line);

> +}

> +

> +int

> +check_proc (const char *proc_name, int flag, int usable, const char *name)

> +{

> +  int found = 0;

> +

> +  printf ("Checking %s:\n", name);

> +  if (!usable)

> +    {

> +      printf ("  %s: insufficient usable info, skipped\n", name);

> +      return 0;

> +    }

> +  printf ("  %s: %d\n", name, flag);

> +  if (strstr (cpu_flags, proc_name) != NULL)

> +    found = 1;

> +  printf ("  cpuinfo (%s): %d\n", proc_name, found);

> +

> +  if (found != flag)

> +    printf (" *** failure ***\n");

> +

> +  return (found != flag);

> +}

> +

> +#define CHECK_PROC(str, name) \

> +  check_proc (#str, HAS_CPU_FEATURE (name), CPU_FEATURE_USABLE (name), \

> +             "HAS_CPU_FEATURE (" #name ")");

> +

> +static int

> +do_test (int argc, char **argv)

> +{

> +  int fails = 0;

> +

> +  get_cpuinfo ();

> +  fails += CHECK_PROC (acpi, ACPI);

> +  fails += CHECK_PROC (adx, ADX);

> +  fails += CHECK_PROC (apic, APIC);

> +  fails += CHECK_PROC (aes, AES);

> +  fails += CHECK_PROC (amx_bf16, AMX_BF16);

> +  fails += CHECK_PROC (amx_int8, AMX_INT8);

> +  fails += CHECK_PROC (amx_tile, AMX_TILE);

> +  fails += CHECK_PROC (arch_capabilities, ARCH_CAPABILITIES);

> +  fails += CHECK_PROC (avx, AVX);

> +  fails += CHECK_PROC (avx2, AVX2);

> +  fails += CHECK_PROC (avx512_4fmaps, AVX512_4FMAPS);

> +  fails += CHECK_PROC (avx512_4vnniw, AVX512_4VNNIW);

> +  fails += CHECK_PROC (avx512_bf16, AVX512_BF16);

> +  fails += CHECK_PROC (avx512_bitalg, AVX512_BITALG);

> +  fails += CHECK_PROC (avx512ifma, AVX512_IFMA);

> +  fails += CHECK_PROC (avx512_vbmi, AVX512_VBMI);

> +  fails += CHECK_PROC (avx512_vbmi2, AVX512_VBMI2);

> +  fails += CHECK_PROC (avx512_vnni, AVX512_VNNI);

> +  fails += CHECK_PROC (avx512_vp2intersect, AVX512_VP2INTERSECT);

> +  fails += CHECK_PROC (avx512_vpopcntdq, AVX512_VPOPCNTDQ);

> +  fails += CHECK_PROC (avx512bw, AVX512BW);

> +  fails += CHECK_PROC (avx512cd, AVX512CD);

> +  fails += CHECK_PROC (avx512er, AVX512ER);

> +  fails += CHECK_PROC (avx512dq, AVX512DQ);

> +  fails += CHECK_PROC (avx512f, AVX512F);

> +  fails += CHECK_PROC (avx512pf, AVX512PF);

> +  fails += CHECK_PROC (avx512vl, AVX512VL);

> +  fails += CHECK_PROC (bmi1, BMI1);

> +  fails += CHECK_PROC (bmi2, BMI2);

> +  fails += CHECK_PROC (cldemote, CLDEMOTE);

> +  fails += CHECK_PROC (clflushopt, CLFLUSHOPT);

> +  fails += CHECK_PROC (clflush, CLFSH);

> +  fails += CHECK_PROC (clwb, CLWB);

> +  fails += CHECK_PROC (cmov, CMOV);

> +  fails += CHECK_PROC (cx16, CMPXCHG16B);

> +  fails += CHECK_PROC (cnxt_id, CNXT_ID);

> +  fails += CHECK_PROC (core_capabilities, CORE_CAPABILITIES);

> +  fails += CHECK_PROC (cx8, CX8);

> +  fails += CHECK_PROC (dca, DCA);

> +  fails += CHECK_PROC (de, DE);

> +  fails += CHECK_PROC (zero_fcs_fds, DEPR_FPU_CS_DS);

> +  fails += CHECK_PROC (ds, DS);

> +  fails += CHECK_PROC (ds_cpl, DS_CPL);

> +  fails += CHECK_PROC (dtes64, DTES64);

> +  fails += CHECK_PROC (est, EIST);

> +  fails += CHECK_PROC (enqcmd, ENQCMD);

> +  fails += CHECK_PROC (erms, ERMS);

> +  fails += CHECK_PROC (f16c, F16C);

> +  fails += CHECK_PROC (fma, FMA);

> +  fails += CHECK_PROC (fma4, FMA4);

> +  fails += CHECK_PROC (fpu, FPU);

> +  fails += CHECK_PROC (fsgsbase, FSGSBASE);

> +  fails += CHECK_PROC (fsrm, FSRM);

> +  fails += CHECK_PROC (fxsr, FXSR);

> +  fails += CHECK_PROC (gfni, GFNI);

> +  fails += CHECK_PROC (hle, HLE);

> +  fails += CHECK_PROC (ht, HTT);

> +  fails += CHECK_PROC (hybrid, HYBRID);

> +  fails += CHECK_PROC (ibrs, IBRS_IBPB);

> +  fails += CHECK_PROC (ibt, IBT);

> +  fails += CHECK_PROC (invariant_tsc, INVARIANT_TSC);

> +  fails += CHECK_PROC (invpcid, INVPCID);

> +  fails += CHECK_PROC (flush_l1d, L1D_FLUSH);

> +  fails += CHECK_PROC (lahf_lm, LAHF64_SAHF64);

> +  fails += CHECK_PROC (lm, LM);

> +  fails += CHECK_PROC (lwp, LWP);

> +  fails += CHECK_PROC (abm, LZCNT);

> +  fails += CHECK_PROC (mca, MCA);

> +  fails += CHECK_PROC (mce, MCE);

> +  fails += CHECK_PROC (md_clear, MD_CLEAR);

> +  fails += CHECK_PROC (mmx, MMX);

> +  fails += CHECK_PROC (monitor, MONITOR);

> +  fails += CHECK_PROC (movbe, MOVBE);

> +  fails += CHECK_PROC (movdiri, MOVDIRI);

> +  fails += CHECK_PROC (movdir64b, MOVDIR64B);

> +  fails += CHECK_PROC (mpx, MPX);

> +  fails += CHECK_PROC (msr, MSR);

> +  fails += CHECK_PROC (mtrr, MTRR);

> +  fails += CHECK_PROC (nx, NX);

> +  fails += CHECK_PROC (ospke, OSPKE);

> +#if 0

> +  /* NB: /proc/cpuinfo doesn't report this feature.  */

> +  fails += CHECK_PROC (osxsave, OSXSAVE);

> +#endif

> +  fails += CHECK_PROC (pae, PAE);

> +  fails += CHECK_PROC (pdpe1gb, PAGE1GB);

> +  fails += CHECK_PROC (pat, PAT);

> +  fails += CHECK_PROC (pbe, PBE);

> +  fails += CHECK_PROC (pcid, PCID);

> +  fails += CHECK_PROC (pclmulqdq, PCLMULQDQ);

> +  fails += CHECK_PROC (pconfig, PCONFIG);

> +  fails += CHECK_PROC (pdcm, PDCM);

> +  fails += CHECK_PROC (pge, PGE);

> +  fails += CHECK_PROC (pks, PKS);

> +  fails += CHECK_PROC (pku, PKU);

> +  fails += CHECK_PROC (popcnt, POPCNT);

> +  fails += CHECK_PROC (3dnowprefetch, PREFETCHW);

> +  fails += CHECK_PROC (prefetchwt1, PREFETCHWT1);

> +  fails += CHECK_PROC (pse, PSE);

> +  fails += CHECK_PROC (pse36, PSE_36);

> +  fails += CHECK_PROC (psn, PSN);

> +  fails += CHECK_PROC (rdpid, RDPID);

> +  fails += CHECK_PROC (rdrand, RDRAND);

> +  fails += CHECK_PROC (rdseed, RDSEED);

> +  fails += CHECK_PROC (rdt_a, RDT_A);

> +  fails += CHECK_PROC (cqm, RDT_M);

> +  fails += CHECK_PROC (rdtscp, RDTSCP);

> +  fails += CHECK_PROC (rtm, RTM);

> +  fails += CHECK_PROC (sdbg, SDBG);

> +  fails += CHECK_PROC (sep, SEP);

> +  fails += CHECK_PROC (serialize, SERIALIZE);

> +  fails += CHECK_PROC (sgx, SGX);

> +  fails += CHECK_PROC (sgx_lc, SGX_LC);

> +  fails += CHECK_PROC (sha_ni, SHA);

> +  fails += CHECK_PROC (shstk, SHSTK);

> +  fails += CHECK_PROC (smap, SMAP);

> +  fails += CHECK_PROC (smep, SMEP);

> +  fails += CHECK_PROC (smx, SMX);

> +  fails += CHECK_PROC (ss, SS);

> +  fails += CHECK_PROC (ssbd, SSBD);

> +  fails += CHECK_PROC (sse, SSE);

> +  fails += CHECK_PROC (sse2, SSE2);

> +  fails += CHECK_PROC (sse3, SSE3);

> +  fails += CHECK_PROC (sse4_1, SSE4_1);

> +  fails += CHECK_PROC (sse4_2, SSE4_2);

> +  fails += CHECK_PROC (sse4a, SSE4A);

> +  fails += CHECK_PROC (ssse3, SSSE3);

> +  fails += CHECK_PROC (stibp, STIBP);

> +  fails += CHECK_PROC (svm, SVM);

> +#ifdef __x86_64__

> +  /* NB: SYSCALL_SYSRET is 64-bit only.  */

> +  fails += CHECK_PROC (syscall, SYSCALL_SYSRET);

> +#endif

> +  fails += CHECK_PROC (tbm, TBM);

> +  fails += CHECK_PROC (tm, TM);

> +  fails += CHECK_PROC (tm2, TM2);

> +  fails += CHECK_PROC (intel_pt, TRACE);

> +  fails += CHECK_PROC (tsc, TSC);

> +  fails += CHECK_PROC (tsc_adjust, TSC_ADJUST);

> +  fails += CHECK_PROC (tsc_deadline, TSC_DEADLINE);

> +  fails += CHECK_PROC (tsxldtrk, TSXLDTRK);

> +  fails += CHECK_PROC (umip, UMIP);

> +  fails += CHECK_PROC (vaes, VAES);

> +  fails += CHECK_PROC (vme, VME);

> +  fails += CHECK_PROC (vmx, VMX);

> +  fails += CHECK_PROC (vpclmulqdq, VPCLMULQDQ);

> +  fails += CHECK_PROC (waitpkg, WAITPKG);

> +  fails += CHECK_PROC (wbnoinvd, WBNOINVD);

> +  fails += CHECK_PROC (x2apic, X2APIC);

> +  fails += CHECK_PROC (xfd, XFD);

> +  fails += CHECK_PROC (xgetbv1, XGETBV_ECX_1);

> +  fails += CHECK_PROC (xop, XOP);

> +  fails += CHECK_PROC (xsave, XSAVE);

> +  fails += CHECK_PROC (xsavec, XSAVEC);

> +  fails += CHECK_PROC (xsaveopt, XSAVEOPT);

> +  fails += CHECK_PROC (xsaves, XSAVES);

> +  fails += CHECK_PROC (xtpr, XTPRUPDCTRL);

> +

> +  printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails);

> +

> +  return (fails != 0);

> +}

> +

> +#include "../../../test-skeleton.c"

> diff --git a/sysdeps/x86/tst-cpu-features-supports.c b/sysdeps/x86/tst-cpu-features-supports.c

> new file mode 100644

> index 0000000000..bf881b531f

> --- /dev/null

> +++ b/sysdeps/x86/tst-cpu-features-supports.c

> @@ -0,0 +1,192 @@

> +/* Test CPU feature data against __builtin_cpu_supports.

> +   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>

> +#include <stdio.h>

> +

> +int

> +check_supports (int supports, int usable, const char *supports_name,

> +               const char *name)

> +{

> +  printf ("Checking %s:\n", name);

> +  printf ("  %s: %d\n", name, usable);

> +  printf ("  __builtin_cpu_supports (%s): %d\n",

> +         supports_name, supports);

> +

> +  if ((supports != 0) != (usable != 0))

> +    {

> +      printf (" *** failure ***\n");

> +      return 1;

> +    }

> +

> +  return 0;

> +}

> +

> +#define CHECK_SUPPORTS(str, name) \

> +  check_supports (__builtin_cpu_supports (#str), \

> +                 CPU_FEATURE_USABLE (name), \

> +                 #str, "HAS_CPU_FEATURE (" #name ")");

> +

> +static int

> +do_test (int argc, char **argv)

> +{

> +  int fails = 0;

> +

> +#if __GNUC_PREREQ (11, 0)

> +  fails += CHECK_SUPPORTS (adx, ADX);

> +#endif

> +#if __GNUC_PREREQ (6, 0)

> +  fails += CHECK_SUPPORTS (aes, AES);

> +#endif

> +#if __GNUC_PREREQ (11, 1)

> +  fails += CHECK_SUPPORTS (amx_bf16, AMX_BF16);

> +  fails += CHECK_SUPPORTS (amx_int8, AMX_INT8);

> +  fails += CHECK_SUPPORTS (amx_tile, AMX_TILE);

> +#endif

> +  fails += CHECK_SUPPORTS (avx, AVX);

> +  fails += CHECK_SUPPORTS (avx2, AVX2);

> +#if __GNUC_PREREQ (7, 0)

> +  fails += CHECK_SUPPORTS (avx5124fmaps, AVX512_4FMAPS);

> +  fails += CHECK_SUPPORTS (avx5124vnniw, AVX512_4VNNIW);

> +#endif

> +#if __GNUC_PREREQ (10, 0)

> +  fails += CHECK_SUPPORTS (avx512bf16, AVX512_BF16);

> +#endif

> +#if __GNUC_PREREQ (8, 0)

> +  fails += CHECK_SUPPORTS (avx512bitalg, AVX512_BITALG);

> +#endif

> +#if __GNUC_PREREQ (6, 0)

> +  fails += CHECK_SUPPORTS (avx512ifma, AVX512_IFMA);

> +  fails += CHECK_SUPPORTS (avx512vbmi, AVX512_VBMI);

> +#endif

> +#if __GNUC_PREREQ (8, 0)

> +  fails += CHECK_SUPPORTS (avx512vbmi2, AVX512_VBMI2);

> +  fails += CHECK_SUPPORTS (avx512vnni, AVX512_VNNI);

> +#endif

> +#if __GNUC_PREREQ (10, 0)

> +  fails += CHECK_SUPPORTS (avx512vp2intersect, AVX512_VP2INTERSECT);

> +#endif

> +#if __GNUC_PREREQ (7, 0)

> +  fails += CHECK_SUPPORTS (avx512vpopcntdq, AVX512_VPOPCNTDQ);

> +#endif

> +#if __GNUC_PREREQ (6, 0)

> +  fails += CHECK_SUPPORTS (avx512bw, AVX512BW);

> +  fails += CHECK_SUPPORTS (avx512cd, AVX512CD);

> +  fails += CHECK_SUPPORTS (avx512er, AVX512ER);

> +  fails += CHECK_SUPPORTS (avx512dq, AVX512DQ);

> +#endif

> +#if __GNUC_PREREQ (5, 0)

> +  fails += CHECK_SUPPORTS (avx512f, AVX512F);

> +#endif

> +#if __GNUC_PREREQ (6, 0)

> +  fails += CHECK_SUPPORTS (avx512pf, AVX512PF);

> +  fails += CHECK_SUPPORTS (avx512vl, AVX512VL);

> +#endif

> +#if __GNUC_PREREQ (5, 0)

> +  fails += CHECK_SUPPORTS (bmi, BMI1);

> +  fails += CHECK_SUPPORTS (bmi2, BMI2);

> +#endif

> +#if __GNUC_PREREQ (11, 0)

> +  fails += CHECK_SUPPORTS (cldemote, CLDEMOTE);

> +  fails += CHECK_SUPPORTS (clflushopt, CLFLUSHOPT);

> +  fails += CHECK_SUPPORTS (clwb, CLWB);

> +#endif

> +  fails += CHECK_SUPPORTS (cmov, CMOV);

> +#if __GNUC_PREREQ (11, 0)

> +  fails += CHECK_SUPPORTS (cmpxchg16b, CMPXCHG16B);

> +  fails += CHECK_SUPPORTS (cmpxchg8b, CX8);

> +  fails += CHECK_SUPPORTS (enqcmd, ENQCMD);

> +  fails += CHECK_SUPPORTS (f16c, F16C);

> +#endif

> +#if __GNUC_PREREQ (4, 9)

> +  fails += CHECK_SUPPORTS (fma, FMA);

> +  fails += CHECK_SUPPORTS (fma4, FMA4);

> +#endif

> +#if __GNUC_PREREQ (11, 0)

> +  fails += CHECK_SUPPORTS (fsgsbase, FSGSBASE);

> +  fails += CHECK_SUPPORTS (fxsave, FXSR);

> +#endif

> +#if __GNUC_PREREQ (8, 0)

> +  fails += CHECK_SUPPORTS (gfni, GFNI);

> +#endif

> +#if __GNUC_PREREQ (11, 0)

> +  fails += CHECK_SUPPORTS (hle, HLE);

> +  fails += CHECK_SUPPORTS (ibt, IBT);

> +  fails += CHECK_SUPPORTS (lahf_lm, LAHF64_SAHF64);

> +  fails += CHECK_SUPPORTS (lm, LM);

> +  fails += CHECK_SUPPORTS (lwp, LWP);

> +  fails += CHECK_SUPPORTS (lzcnt, LZCNT);

> +#endif

> +  fails += CHECK_SUPPORTS (mmx, MMX);

> +#if __GNUC_PREREQ (11, 0)

> +  fails += CHECK_SUPPORTS (movbe, MOVBE);

> +  fails += CHECK_SUPPORTS (movdiri, MOVDIRI);

> +  fails += CHECK_SUPPORTS (movdir64b, MOVDIR64B);

> +  fails += CHECK_SUPPORTS (osxsave, OSXSAVE);

> +  fails += CHECK_SUPPORTS (pconfig, PCONFIG);

> +  fails += CHECK_SUPPORTS (pku, PKU);

> +#endif

> +  fails += CHECK_SUPPORTS (popcnt, POPCNT);

> +#if __GNUC_PREREQ (11, 0)

> +  fails += CHECK_SUPPORTS (prefetchwt1, PREFETCHWT1);

> +  fails += CHECK_SUPPORTS (rdpid, RDPID);

> +  fails += CHECK_SUPPORTS (rdrnd, RDRAND);

> +  fails += CHECK_SUPPORTS (rdseed, RDSEED);

> +  fails += CHECK_SUPPORTS (rtm, RTM);

> +  fails += CHECK_SUPPORTS (serialize, SERIALIZE);

> +  fails += CHECK_SUPPORTS (sha, SHA);

> +  fails += CHECK_SUPPORTS (shstk, SHSTK);

> +#endif

> +  fails += CHECK_SUPPORTS (sse, SSE);

> +  fails += CHECK_SUPPORTS (sse2, SSE2);

> +  fails += CHECK_SUPPORTS (sse3, SSE3);

> +  fails += CHECK_SUPPORTS (sse4.1, SSE4_1);

> +  fails += CHECK_SUPPORTS (sse4.2, SSE4_2);

> +#if __GNUC_PREREQ (4, 9)

> +  fails += CHECK_SUPPORTS (sse4a, SSE4A);

> +#endif

> +  fails += CHECK_SUPPORTS (ssse3, SSSE3);

> +#if __GNUC_PREREQ (11, 0)

> +  fails += CHECK_SUPPORTS (tbm, TBM);

> +  fails += CHECK_SUPPORTS (tsxldtrk, TSXLDTRK);

> +  fails += CHECK_SUPPORTS (vaes, VAES);

> +#endif

> +#if __GNUC_PREREQ (8, 0)

> +  fails += CHECK_SUPPORTS (vpclmulqdq, VPCLMULQDQ);

> +#endif

> +#if __GNUC_PREREQ (11, 0)

> +  fails += CHECK_SUPPORTS (waitpkg, WAITPKG);

> +  fails += CHECK_SUPPORTS (wbnoinvd, WBNOINVD);

> +#endif

> +#if __GNUC_PREREQ (4, 9)

> +  fails += CHECK_SUPPORTS (xop, XOP);

> +#endif

> +#if __GNUC_PREREQ (11, 0)

> +  fails += CHECK_SUPPORTS (xsave, XSAVE);

> +  fails += CHECK_SUPPORTS (xsavec, XSAVEC);

> +  fails += CHECK_SUPPORTS (xsaveopt, XSAVEOPT);

> +  fails += CHECK_SUPPORTS (xsaves, XSAVES);

> +#endif

> +

> +  printf ("%d differences between __builtin_cpu_supports and glibc code.\n",

> +         fails);

> +

> +  return (fails != 0);

> +}

> +

> +#include "../../../test-skeleton.c"

> diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c

> index 6bfdef0829..3447d17e23 100644

> --- a/sysdeps/x86/tst-get-cpu-features.c

> +++ b/sysdeps/x86/tst-get-cpu-features.c

> @@ -1,4 +1,4 @@

> -/* Test case for x86 __get_cpu_features interface

> +/* Test case for __x86_get_cpu_features interface

>     Copyright (C) 2015-2020 Free Software Foundation, Inc.

>     This file is part of the GNU C Library.

>

> @@ -18,7 +18,7 @@

>

>  #include <stdlib.h>

>  #include <stdio.h>

> -#include <cpu-features.h>

> +#include <sys/platform/x86.h>

>  #include <support/check.h>

>

>  #define CHECK_CPU_FEATURE(name)                \

> @@ -45,7 +45,7 @@ static const char * const cpu_kinds[] =

>  static int

>  do_test (void)

>  {

> -  const struct cpu_features *cpu_features = __get_cpu_features ();

> +  const struct cpu_features *cpu_features = __x86_get_cpu_features (0);

>

>    switch (cpu_features->basic.kind)

>      {

> diff --git a/sysdeps/x86_64/fpu/math-tests-arch.h b/sysdeps/x86_64/fpu/math-tests-arch.h

> index 33ea763de2..cc3c2b0c11 100644

> --- a/sysdeps/x86_64/fpu/math-tests-arch.h

> +++ b/sysdeps/x86_64/fpu/math-tests-arch.h

> @@ -16,7 +16,7 @@

>     License along with the GNU C Library; if not, see

>     <https://www.gnu.org/licenses/>.  */

>

> -#include <cpu-features.h>

> +#include <sys/platform/x86.h>

>

>  #if defined REQUIRE_AVX

>

> diff --git a/sysdeps/x86_64/multiarch/Makefile b/sysdeps/x86_64/multiarch/Makefile

> index 395e432c09..9477538af4 100644

> --- a/sysdeps/x86_64/multiarch/Makefile

> +++ b/sysdeps/x86_64/multiarch/Makefile

> @@ -1,7 +1,3 @@

> -ifeq ($(subdir),csu)

> -tests += test-multiarch

> -endif

> -

>  ifeq ($(subdir),string)

>

>  sysdep_routines += strncat-c stpncpy-c strncpy-c \

> diff --git a/sysdeps/x86_64/multiarch/test-multiarch.c b/sysdeps/x86_64/multiarch/test-multiarch.c

> deleted file mode 100644

> index 2782803e73..0000000000

> --- a/sysdeps/x86_64/multiarch/test-multiarch.c

> +++ /dev/null

> @@ -1,96 +0,0 @@

> -/* Test CPU feature data.

> -   This file is part of the GNU C Library.

> -   Copyright (C) 2012-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 <cpu-features.h>

> -#include <stdio.h>

> -#include <stdlib.h>

> -#include <string.h>

> -

> -static char *cpu_flags;

> -

> -/* Search for flags in /proc/cpuinfo and store line

> -   in cpu_flags.  */

> -void

> -get_cpuinfo (void)

> -{

> -  FILE *f;

> -  char *line = NULL;

> -  size_t len = 0;

> -  ssize_t read;

> -

> -  f = fopen ("/proc/cpuinfo", "r");

> -  if (f == NULL)

> -    {

> -      printf ("cannot open /proc/cpuinfo\n");

> -      exit (1);

> -    }

> -

> -  while ((read = getline (&line, &len, f)) != -1)

> -    {

> -      if (strncmp (line, "flags", 5) == 0)

> -       {

> -         cpu_flags = strdup (line);

> -         break;

> -       }

> -    }

> -  fclose (f);

> -  free (line);

> -}

> -

> -int

> -check_proc (const char *proc_name, int flag, const char *name)

> -{

> -  int found = 0;

> -

> -  printf ("Checking %s:\n", name);

> -  printf ("  init-arch %d\n", flag);

> -  if (strstr (cpu_flags, proc_name) != NULL)

> -    found = 1;

> -  printf ("  cpuinfo (%s) %d\n", proc_name, found);

> -

> -  if (found != flag)

> -    printf (" *** failure ***\n");

> -

> -  return (found != flag);

> -}

> -

> -static int

> -do_test (int argc, char **argv)

> -{

> -  int fails;

> -

> -  get_cpuinfo ();

> -  fails = check_proc ("avx", CPU_FEATURE_USABLE (AVX),

> -                     "CPU_FEATURE_USABLE (AVX)");

> -  fails += check_proc ("fma4", CPU_FEATURE_USABLE (FMA4),

> -                      "CPU_FEATURE_USABLE (FMA4)");

> -  fails += check_proc ("sse4_2", CPU_FEATURE_USABLE (SSE4_2),

> -                      "CPU_FEATURE_USABLE (SSE4_2)");

> -  fails += check_proc ("sse4_1", CPU_FEATURE_USABLE (SSE4_1)

> -                      , "CPU_FEATURE_USABLE (SSE4_1)");

> -  fails += check_proc ("ssse3", CPU_FEATURE_USABLE (SSSE3),

> -                      "CPU_FEATURE_USABLE (SSSE3)");

> -  fails += check_proc ("popcnt", CPU_FEATURE_USABLE (POPCNT),

> -                      "CPU_FEATURE_USABLE (POPCNT)");

> -

> -  printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails);

> -

> -  return (fails != 0);

> -}

> -

> -#include "../../../test-skeleton.c"

> --

> 2.26.2

>



-- 
H.J.
Michael Kerrisk \(man-pages\) via Libc-alpha Aug. 19, 2020, 12:52 p.m. | #2
On Wed, Aug 12, 2020 at 7:00 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>

> On Wed, Aug 5, 2020 at 4:01 PM H.J. Lu <hjl.tools@gmail.com> wrote:

> >

> > Install <sys/platform/x86.h> so that programmers can do

> >

> >  #if __has_include(<sys/platform/x86.h>)

> >  #include <sys/platform/x86.h>

> >  #endif

> >  ...

> >

> >    if (CPU_FEATURE_USABLE (SSE2))

> >  ...

> >    if (CPU_FEATURE_USABLE (AVX2))

> >  ...

> >

> > <sys/platform/x86.h> exports only:

> >

> > enum

> > {

> >   COMMON_CPUID_INDEX_1 = 0,

> >   COMMON_CPUID_INDEX_7,

> >   COMMON_CPUID_INDEX_80000001,

> >   COMMON_CPUID_INDEX_D_ECX_1,

> >   COMMON_CPUID_INDEX_80000007,

> >   COMMON_CPUID_INDEX_80000008,

> >   COMMON_CPUID_INDEX_7_ECX_1,

> >   /* Keep the following line at the end.  */

> >   COMMON_CPUID_INDEX_MAX

> > };

> >

> > struct cpuid_features

> > {

> >   struct cpuid_registers cpuid;

> >   struct cpuid_registers usable;

> > };

> >

> > struct cpu_features

> > {

> >   struct cpu_features_basic basic;

> >   struct cpuid_features features[COMMON_CPUID_INDEX_MAX];

> > };

> >

> > /* Get a pointer to the CPU features structure.  */

> > extern const struct cpu_features *__x86_get_cpu_features

> >   (unsigned int max) __attribute__ ((const));

> >

> > Since all feature checks are done through macros, programs compiled with

> > a newer <sys/platform/x86.h> are compatible with the older glibc binaries

> > as long as the layout of struct cpu_features is identical.  The features

> > array can be expanded with backward binary compatibility for both .o and

> > .so files.  When COMMON_CPUID_INDEX_MAX is increased to support new

> > processor features, __x86_get_cpu_features in the older glibc binaries

> > returns NULL and HAS_CPU_FEATURE/CPU_FEATURE_USABLE return false on the

> > new processor feature.  No new symbol version is neeeded.

> >

> > Both CPU_FEATURE_USABLE and HAS_CPU_FEATURE are provided.  HAS_CPU_FEATURE

> > can be used to identify processor features.

> >

> > Note: Although GCC has __builtin_cpu_supports, it only supports a subset

> > of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE.  It

> > doesn't support HAS_CPU_FEATURE.


PING:

https://sourceware.org/pipermail/libc-alpha/2020-August/116865.html


-- 
H.J.
Michael Kerrisk \(man-pages\) via Libc-alpha Sept. 2, 2020, 12:55 p.m. | #3
On Wed, Aug 19, 2020 at 5:52 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>

> On Wed, Aug 12, 2020 at 7:00 AM H.J. Lu <hjl.tools@gmail.com> wrote:

> >

> > On Wed, Aug 5, 2020 at 4:01 PM H.J. Lu <hjl.tools@gmail.com> wrote:

> > >

> > > Install <sys/platform/x86.h> so that programmers can do

> > >

> > >  #if __has_include(<sys/platform/x86.h>)

> > >  #include <sys/platform/x86.h>

> > >  #endif

> > >  ...

> > >

> > >    if (CPU_FEATURE_USABLE (SSE2))

> > >  ...

> > >    if (CPU_FEATURE_USABLE (AVX2))

> > >  ...

> > >

> > > <sys/platform/x86.h> exports only:

> > >

> > > enum

> > > {

> > >   COMMON_CPUID_INDEX_1 = 0,

> > >   COMMON_CPUID_INDEX_7,

> > >   COMMON_CPUID_INDEX_80000001,

> > >   COMMON_CPUID_INDEX_D_ECX_1,

> > >   COMMON_CPUID_INDEX_80000007,

> > >   COMMON_CPUID_INDEX_80000008,

> > >   COMMON_CPUID_INDEX_7_ECX_1,

> > >   /* Keep the following line at the end.  */

> > >   COMMON_CPUID_INDEX_MAX

> > > };

> > >

> > > struct cpuid_features

> > > {

> > >   struct cpuid_registers cpuid;

> > >   struct cpuid_registers usable;

> > > };

> > >

> > > struct cpu_features

> > > {

> > >   struct cpu_features_basic basic;

> > >   struct cpuid_features features[COMMON_CPUID_INDEX_MAX];

> > > };

> > >

> > > /* Get a pointer to the CPU features structure.  */

> > > extern const struct cpu_features *__x86_get_cpu_features

> > >   (unsigned int max) __attribute__ ((const));

> > >

> > > Since all feature checks are done through macros, programs compiled with

> > > a newer <sys/platform/x86.h> are compatible with the older glibc binaries

> > > as long as the layout of struct cpu_features is identical.  The features

> > > array can be expanded with backward binary compatibility for both .o and

> > > .so files.  When COMMON_CPUID_INDEX_MAX is increased to support new

> > > processor features, __x86_get_cpu_features in the older glibc binaries

> > > returns NULL and HAS_CPU_FEATURE/CPU_FEATURE_USABLE return false on the

> > > new processor feature.  No new symbol version is neeeded.

> > >

> > > Both CPU_FEATURE_USABLE and HAS_CPU_FEATURE are provided.  HAS_CPU_FEATURE

> > > can be used to identify processor features.

> > >

> > > Note: Although GCC has __builtin_cpu_supports, it only supports a subset

> > > of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE.  It

> > > doesn't support HAS_CPU_FEATURE.

>

> PING:

>

> https://sourceware.org/pipermail/libc-alpha/2020-August/116865.html

>


If there are no more comments, I will check it next Friday,
Sept 11.


-- 
H.J.
On Wed, Sep 2, 2020 at 5:55 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>

> On Wed, Aug 19, 2020 at 5:52 AM H.J. Lu <hjl.tools@gmail.com> wrote:

> >

> > On Wed, Aug 12, 2020 at 7:00 AM H.J. Lu <hjl.tools@gmail.com> wrote:

> > >

> > > On Wed, Aug 5, 2020 at 4:01 PM H.J. Lu <hjl.tools@gmail.com> wrote:

> > > >

> > > > Install <sys/platform/x86.h> so that programmers can do

> > > >

> > > >  #if __has_include(<sys/platform/x86.h>)

> > > >  #include <sys/platform/x86.h>

> > > >  #endif

> > > >  ...

> > > >

> > > >    if (CPU_FEATURE_USABLE (SSE2))

> > > >  ...

> > > >    if (CPU_FEATURE_USABLE (AVX2))

> > > >  ...

> > > >

> > > > <sys/platform/x86.h> exports only:

> > > >

> > > > enum

> > > > {

> > > >   COMMON_CPUID_INDEX_1 = 0,

> > > >   COMMON_CPUID_INDEX_7,

> > > >   COMMON_CPUID_INDEX_80000001,

> > > >   COMMON_CPUID_INDEX_D_ECX_1,

> > > >   COMMON_CPUID_INDEX_80000007,

> > > >   COMMON_CPUID_INDEX_80000008,

> > > >   COMMON_CPUID_INDEX_7_ECX_1,

> > > >   /* Keep the following line at the end.  */

> > > >   COMMON_CPUID_INDEX_MAX

> > > > };

> > > >

> > > > struct cpuid_features

> > > > {

> > > >   struct cpuid_registers cpuid;

> > > >   struct cpuid_registers usable;

> > > > };

> > > >

> > > > struct cpu_features

> > > > {

> > > >   struct cpu_features_basic basic;

> > > >   struct cpuid_features features[COMMON_CPUID_INDEX_MAX];

> > > > };

> > > >

> > > > /* Get a pointer to the CPU features structure.  */

> > > > extern const struct cpu_features *__x86_get_cpu_features

> > > >   (unsigned int max) __attribute__ ((const));

> > > >

> > > > Since all feature checks are done through macros, programs compiled with

> > > > a newer <sys/platform/x86.h> are compatible with the older glibc binaries

> > > > as long as the layout of struct cpu_features is identical.  The features

> > > > array can be expanded with backward binary compatibility for both .o and

> > > > .so files.  When COMMON_CPUID_INDEX_MAX is increased to support new

> > > > processor features, __x86_get_cpu_features in the older glibc binaries

> > > > returns NULL and HAS_CPU_FEATURE/CPU_FEATURE_USABLE return false on the

> > > > new processor feature.  No new symbol version is neeeded.

> > > >

> > > > Both CPU_FEATURE_USABLE and HAS_CPU_FEATURE are provided.  HAS_CPU_FEATURE

> > > > can be used to identify processor features.

> > > >

> > > > Note: Although GCC has __builtin_cpu_supports, it only supports a subset

> > > > of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE.  It

> > > > doesn't support HAS_CPU_FEATURE.

> >

> > PING:

> >

> > https://sourceware.org/pipermail/libc-alpha/2020-August/116865.html

> >

>

> If there are no more comments, I will check it next Friday,

> Sept 11.

>


I am enclosing the rebased patch I am checking in this Friday.

-- 
H.J.
From 56b14744767e741b498036878d94c7a866a81b6d Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 29 Jun 2020 18:30:54 -0700
Subject: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]

Install <sys/platform/x86.h> so that programmers can do

 #if __has_include(<sys/platform/x86.h>)
 #include <sys/platform/x86.h>
 #endif
 ...

   if (CPU_FEATURE_USABLE (SSE2))
 ...
   if (CPU_FEATURE_USABLE (AVX2))
 ...

<sys/platform/x86.h> exports only:

enum
{
  COMMON_CPUID_INDEX_1 = 0,
  COMMON_CPUID_INDEX_7,
  COMMON_CPUID_INDEX_80000001,
  COMMON_CPUID_INDEX_D_ECX_1,
  COMMON_CPUID_INDEX_80000007,
  COMMON_CPUID_INDEX_80000008,
  COMMON_CPUID_INDEX_7_ECX_1,
  /* Keep the following line at the end.  */
  COMMON_CPUID_INDEX_MAX
};

struct cpuid_features
{
  struct cpuid_registers cpuid;
  struct cpuid_registers usable;
};

struct cpu_features
{
  struct cpu_features_basic basic;
  struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
};

/* Get a pointer to the CPU features structure.  */
extern const struct cpu_features *__x86_get_cpu_features
  (unsigned int max) __attribute__ ((const));

Since all feature checks are done through macros, programs compiled with
a newer <sys/platform/x86.h> are compatible with the older glibc binaries
as long as the layout of struct cpu_features is identical.  The features
array can be expanded with backward binary compatibility for both .o and
.so files.  When COMMON_CPUID_INDEX_MAX is increased to support new
processor features, __x86_get_cpu_features in the older glibc binaries
returns NULL and HAS_CPU_FEATURE/CPU_FEATURE_USABLE return false on the
new processor feature.  No new symbol version is neeeded.

Both CPU_FEATURE_USABLE and HAS_CPU_FEATURE are provided.  HAS_CPU_FEATURE
can be used to identify processor features.

Note: Although GCC has __builtin_cpu_supports, it only supports a subset
of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE.  It
doesn't support HAS_CPU_FEATURE.
---
 NEWS                                          |   1 +
 manual/platform.texi                          | 517 ++++++++++++++++++
 sysdeps/i386/i686/multiarch/Makefile          |   4 -
 sysdeps/i386/i686/multiarch/test-multiarch.c  |   1 -
 sysdeps/unix/sysv/linux/i386/ld.abilist       |   1 +
 sysdeps/unix/sysv/linux/x86_64/64/ld.abilist  |   1 +
 sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |   1 +
 sysdeps/x86/Makefile                          |   4 +-
 sysdeps/x86/Versions                          |   4 +-
 sysdeps/x86/dl-get-cpu-features.c             |   6 +-
 sysdeps/x86/include/cpu-features.h            | 183 +++++++
 .../{cpu-features.h => sys/platform/x86.h}    | 150 +----
 sysdeps/x86/tst-cpu-features-cpuinfo.c        | 250 +++++++++
 sysdeps/x86/tst-cpu-features-supports.c       | 192 +++++++
 sysdeps/x86/tst-get-cpu-features.c            |   6 +-
 sysdeps/x86_64/fpu/math-tests-arch.h          |   2 +-
 sysdeps/x86_64/multiarch/Makefile             |   4 -
 sysdeps/x86_64/multiarch/test-multiarch.c     |  96 ----
 18 files changed, 1176 insertions(+), 247 deletions(-)
 delete mode 100644 sysdeps/i386/i686/multiarch/test-multiarch.c
 create mode 100644 sysdeps/x86/include/cpu-features.h
 rename sysdeps/x86/{cpu-features.h => sys/platform/x86.h} (81%)
 create mode 100644 sysdeps/x86/tst-cpu-features-cpuinfo.c
 create mode 100644 sysdeps/x86/tst-cpu-features-supports.c
 delete mode 100644 sysdeps/x86_64/multiarch/test-multiarch.c

diff --git a/NEWS b/NEWS
index 06e43e0453..878221639b 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,7 @@ Version 2.33
 
 Major new features:
 
+* Add <sys/platform/x86.h> to provide query macros for x86 CPU features.
 
 * Support for the RISC-V ISA running on Linux has been expanded to run on
   32-bit hardware.  This is supported for the following ISA and ABI pairs:
diff --git a/manual/platform.texi b/manual/platform.texi
index 504addc956..2c145acdc3 100644
--- a/manual/platform.texi
+++ b/manual/platform.texi
@@ -7,6 +7,7 @@
 @menu
 * PowerPC::           Facilities Specific to the PowerPC Architecture
 * RISC-V::            Facilities Specific to the RISC-V Architecture
+* X86::               Facilities Specific to the X86 Architecture
 @end menu
 
 @node PowerPC
@@ -134,3 +135,519 @@ all threads in the current process.  Setting the
 ordering on only the current thread is necessary.  All other flag bits are
 reserved.
 @end deftypefun
+
+@node X86
+@appendixsec X86-specific Facilities
+
+Facilities specific to X86 that are not specific to a particular
+operating system are declared in @file{sys/platform/x86.h}.
+
+@deftypefun {const struct cpu_features *} __x86_get_cpu_features (unsigned int @var{max})
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Return a pointer to x86 CPU feature structure used by query macros for x86
+CPU features.  If @var{max} exceeds @code{COMMON_CPUID_INDEX_MAX} which
+is the limit of the CPUID leaves supported by @Theglibc{}, the function
+returns @code{NULL}, indicating that the queried processor feature is
+unsupported by @Theglibc{} run-time.
+@end deftypefun
+
+@deftypefn Macro int HAS_CPU_FEATURE (@var{name})
+This macro returns a nonzero value (true) if the processor has the feature
+@var{name}.
+@end deftypefn
+
+@deftypefn Macro int CPU_FEATURE_USABLE (@var{name})
+This macro returns a nonzero value (true) if the processor has the feature
+@var{name} and the feature is supported by the operating system.
+@end deftypefn
+
+The supported processor features are:
+
+@itemize @bullet
+
+@item
+@code{ACPI} -- Thermal Monitor and Software Controlled Clock Facilities.
+
+@item
+@code{ADX} -- ADX instruction extensions.
+
+@item
+@code{APIC} -- APIC On-Chip.
+
+@item
+@code{AES} -- The AES instruction extensions.
+
+@item
+@code{AMX_BF16} -- Tile computational operations on bfloat16 numbers.
+
+@item
+@code{AMX_INT8} -- Tile computational operations on 8-bit numbers.
+
+@item
+@code{AMX_TILE} -- Tile architecture.
+
+@item
+@code{ARCH_CAPABILITIES} -- IA32_ARCH_CAPABILITIES MSR.
+
+@item
+@code{AVX} -- The AVX instruction extensions.
+
+@item
+@code{AVX2} -- The AVX2 instruction extensions.
+
+@item
+@code{AVX512_4FMAPS} -- The AVX512_4FMAPS instruction extensions.
+
+@item
+@code{AVX512_4VNNIW} -- The AVX512_4VNNIW instruction extensions.
+
+@item
+@code{AVX512_BF16} -- The AVX512_BF16 instruction extensions.
+
+@item
+@code{AVX512_BITALG} -- The AVX512_BITALG instruction extensions.
+
+@item
+@code{AVX512_IFMA} -- The AVX512_IFMA instruction extensions.
+
+@item
+@code{AVX512_VBMI} -- The AVX512_VBMI instruction extensions.
+
+@item
+@code{AVX512_VBMI2} -- The AVX512_VBMI2 instruction extensions.
+
+@item
+@code{AVX512_VNNI} -- The AVX512_VNNI instruction extensions.
+
+@item
+@code{AVX512_VP2INTERSECT} -- The AVX512_VP2INTERSECT instruction
+extensions.
+
+@item
+@code{AVX512_VPOPCNTDQ} -- The AVX512_VPOPCNTDQ instruction extensions.
+
+@item
+@code{AVX512BW} -- The AVX512BW instruction extensions.
+
+@item
+@code{AVX512CD} -- The AVX512CD instruction extensions.
+
+@item
+@code{AVX512ER} -- The AVX512ER instruction extensions.
+
+@item
+@code{AVX512DQ} -- The AVX512DQ instruction extensions.
+
+@item
+@code{AVX512F} -- The AVX512F instruction extensions.
+
+@item
+@code{AVX512PF} -- The AVX512PF instruction extensions.
+
+@item
+@code{AVX512VL} -- The AVX512VL instruction extensions.
+
+@item
+@code{BMI1} -- BMI1 instructions.
+
+@item
+@code{BMI2} -- BMI2 instructions.
+
+@item
+@code{CLDEMOTE} -- CLDEMOTE instruction.
+
+@item
+@code{CLFLUSHOPT} -- CLFLUSHOPT instruction.
+
+@item
+@code{CLFSH} -- CLFLUSH instruction.
+
+@item
+@code{CLWB} -- CLWB instruction.
+
+@item
+@code{CMOV} -- Conditional Move instructions.
+
+@item
+@code{CMPXCHG16B} -- CMPXCHG16B instruction.
+
+@item
+@code{CNXT_ID} -- L1 Context ID.
+
+@item
+@code{CORE_CAPABILITIES} -- IA32_CORE_CAPABILITIES MSR.
+
+@item
+@code{CX8} -- CMPXCHG8B instruction.
+
+@item
+@code{DCA} -- Data prefetch from a memory mapped device.
+
+@item
+@code{DE} -- Debugging Extensions.
+
+@item
+@code{DEPR_FPU_CS_DS} -- Deprecates FPU CS and FPU DS values.
+
+@item
+@code{DS} -- Debug Store.
+
+@item
+@code{DS_CPL} -- CPL Qualified Debug Store.
+
+@item
+@code{DTES64} -- 64-bit DS Area.
+
+@item
+@code{EIST} -- Enhanced Intel SpeedStep technology.
+
+@item
+@code{ENQCMD} -- Enqueue Stores instructions.
+
+@item
+@code{ERMS} -- Enhanced REP MOVSB/STOSB.
+
+@item
+@code{F16C} -- 16-bit floating-point conversion instructions.
+
+@item
+@code{FMA} -- FMA extensions using YMM state.
+
+@item
+@code{FMA4} -- FMA4 instruction extensions.
+
+@item
+@code{FPU} -- X87 Floating Point Unit On-Chip.
+
+@item
+@code{FSGSBASE} -- RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE instructions.
+
+@item
+@code{FSRM} -- Fast Short REP MOV.
+
+@item
+@code{FXSR} -- FXSAVE and FXRSTOR instructions.
+
+@item
+@code{GFNI} -- GFNI instruction extensions.
+
+@item
+@code{HLE} -- HLE instruction extensions.
+
+@item
+@code{HTT} -- Max APIC IDs reserved field is Valid.
+
+@item
+@code{HYBRID} -- Hybrid processor.
+
+@item
+@code{IBRS_IBPB} -- Indirect branch restricted speculation (IBRS) and
+the indirect branch predictor barrier (IBPB).
+
+@item
+@code{IBT} -- Intel Indirect Branch Tracking instruction extensions.
+
+@item
+@code{INVARIANT_TSC} -- Invariant TSC.
+
+@item
+@code{INVPCID} -- INVPCID instruction.
+
+@item
+@code{L1D_FLUSH} -- IA32_FLUSH_CMD MSR.
+
+@item
+@code{LAHF64_SAHF64} -- LAHF/SAHF available in 64-bit mode.
+
+@item
+@code{LM} -- Long mode.
+
+@item
+@code{LWP} -- Lightweight profiling.
+
+@item
+@code{LZCNT} -- LZCNT instruction.
+
+@item
+@code{MCA} -- Machine Check Architecture.
+
+@item
+@code{MCE} -- Machine Check Exception.
+
+@item
+@code{MD_CLEAR} -- MD_CLEAR.
+
+@item
+@code{MMX} -- Intel MMX Technology.
+
+@item
+@code{MONITOR} --  MONITOR/MWAIT instructions.
+
+@item
+@code{MOVBE} -- MOVBE instruction.
+
+@item
+@code{MOVDIRI} -- MOVDIRI instruction.
+
+@item
+@code{MOVDIR64B} -- MOVDIR64B instruction.
+
+@item
+@code{MPX} -- Intel Memory Protection Extensions.
+
+@item
+@code{MSR} -- Model Specific Registers RDMSR and WRMSR instructions.
+
+@item
+@code{MTRR} -- Memory Type Range Registers.
+
+@item
+@code{NX} -- No-execute page protection.
+
+@item
+@code{OSPKE} -- OS has set CR4.PKE to enable protection keys.
+
+@item
+@code{OSXSAVE} -- The OS has set CR4.OSXSAVE[bit 18] to enable
+XSETBV/XGETBV instructions to access XCR0 and to support processor
+extended state management using XSAVE/XRSTOR.
+
+@item
+@code{PAE} -- Physical Address Extension.
+
+@item
+@code{PAGE1GB} -- 1-GByte page.
+
+@item
+@code{PAT} -- Page Attribute Table.
+
+@item
+@code{PBE} -- Pending Break Enable.
+
+@item
+@code{PCID} -- Process-context identifiers.
+
+@item
+@code{PCLMULQDQ} -- PCLMULQDQ instruction.
+
+@item
+@code{PCONFIG} -- PCONFIG instruction.
+
+@item
+@code{PDCM} -- Perfmon and Debug Capability.
+
+@item
+@code{PGE} -- Page Global Bit.
+
+@item
+@code{PKS} -- Protection keys for supervisor-mode pages.
+
+@item
+@code{PKU} -- Protection keys for user-mode pages.
+
+@item
+@code{POPCNT} -- POPCNT instruction.
+
+@item
+@code{PREFETCHW} -- PREFETCHW instruction.
+
+@item
+@code{PREFETCHWT1} -- PREFETCHWT1 instruction.
+
+@item
+@code{PSE} -- Page Size Extension.
+
+@item
+@code{PSE_36} -- 36-Bit Page Size Extension.
+
+@item
+@code{PSN} -- Processor Serial Number.
+
+@item
+@code{RDPID} -- RDPID instruction.
+
+@item
+@code{RDRAND} -- RDRAND instruction.
+
+@item
+@code{RDSEED} -- RDSEED instruction.
+
+@item
+@code{RDT_A} -- Intel Resource Director Technology (Intel RDT) Allocation
+capability.
+
+@item
+@code{RDT_M} -- Intel Resource Director Technology (Intel RDT) Monitoring
+capability.
+
+@item
+@code{RDTSCP} -- RDTSCP instruction.
+
+@item
+@code{RTM} -- RTM instruction extensions.
+
+@item
+@code{SDBG} -- IA32_DEBUG_INTERFACE MSR for silicon debug.
+
+@item
+@code{SEP} -- SYSENTER and SYSEXIT instructions.
+
+@item
+@code{SERIALIZE} -- SERIALIZE instruction.
+
+@item
+@code{SGX} -- Intel Software Guard Extensions.
+
+@item
+@code{SGX_LC} -- SGX Launch Configuration.
+
+@item
+@code{SHA} -- SHA instruction extensions.
+
+@item
+@code{SHSTK} -- Intel Shadow Stack instruction extensions.
+
+@item
+@code{SMAP} -- Supervisor-Mode Access Prevention.
+
+@item
+@code{SMEP} -- Supervisor-Mode Execution Prevention.
+
+@item
+@code{SMX} -- Safer Mode Extensions.
+
+@item
+@code{SS} -- Self Snoop.
+
+@item
+@code{SSBD} -- Speculative Store Bypass Disable (SSBD).
+
+@item
+@code{SSE} -- Streaming SIMD Extensions.
+
+@item
+@code{SSE2} -- Streaming SIMD Extensions 2.
+
+@item
+@code{SSE3} -- Streaming SIMD Extensions 3.
+
+@item
+@code{SSE4_1} -- Streaming SIMD Extensions 4.1.
+
+@item
+@code{SSE4_2} -- Streaming SIMD Extensions 4.2.
+
+@item
+@code{SSE4A} -- SSE4A instruction extensions.
+
+@item
+@code{SSSE3} -- Supplemental Streaming SIMD Extensions 3.
+
+@item
+@code{STIBP} -- Single thread indirect branch predictors (STIBP).
+
+@item
+@code{SVM} -- Secure Virtual Machine.
+
+@item
+@code{SYSCALL_SYSRET} -- SYSCALL/SYSRET instructions.
+
+@item
+@code{TBM} -- Trailing bit manipulation instructions.
+
+@item
+@code{TM} -- Thermal Monitor.
+
+@item
+@code{TM2} -- Thermal Monitor 2.
+
+@item
+@code{TRACE} -- Intel Processor Trace.
+
+@item
+@code{TSC} -- Time Stamp Counter.  RDTSC instruction.
+
+@item
+@code{TSC_ADJUST} -- IA32_TSC_ADJUST MSR.
+
+@item
+@code{TSC_DEADLINE} -- Local APIC timer supports one-shot operation
+using a TSC deadline value.
+
+@item
+@code{TSXLDTRK} -- TSXLDTRK instructions.
+
+@item
+@code{UMIP} -- User-mode instruction prevention.
+
+@item
+@code{VAES} -- VAES instruction extensions.
+
+@item
+@code{VME} -- Virtual 8086 Mode Enhancements.
+
+@item
+@code{VMX} -- Virtual Machine Extensions.
+
+@item
+@code{VPCLMULQDQ} -- VPCLMULQDQ instruction.
+
+@item
+@code{WAITPKG} -- WAITPKG instruction extensions.
+
+@item
+@code{WBNOINVD} -- WBINVD/WBNOINVD instructions.
+
+@item
+@code{X2APIC} -- x2APIC.
+
+@item
+@code{XFD} -- Extended Feature Disable (XFD).
+
+@item
+@code{XGETBV_ECX_1} -- XGETBV with ECX = 1.
+
+@item
+@code{XOP} -- XOP instruction extensions.
+
+@item
+@code{XSAVE} -- The XSAVE/XRSTOR processor extended states feature, the
+XSETBV/XGETBV instructions, and XCR0.
+
+@item
+@code{XSAVEC} -- XSAVEC instruction.
+
+@item
+@code{XSAVEOPT} -- XSAVEOPT instruction.
+
+@item
+@code{XSAVES} -- XSAVES/XRSTORS instructions.
+
+@item
+@code{XTPRUPDCTRL} -- xTPR Update Control.
+
+@end itemize
+
+You could query if a processor supports @code{AVX} with:
+
+@smallexample
+#include <sys/platform/x86.h>
+
+int
+support_avx (void)
+@{
+  return HAS_CPU_FEATURE (AVX);
+@}
+@end smallexample
+
+and if @code{AVX} is usable with:
+
+@smallexample
+#include <sys/platform/x86.h>
+
+int
+usable_avx (void)
+@{
+  return CPU_FEATURE_USABLE (AVX);
+@}
+@end smallexample
diff --git a/sysdeps/i386/i686/multiarch/Makefile b/sysdeps/i386/i686/multiarch/Makefile
index bf75a9947f..c4897922d7 100644
--- a/sysdeps/i386/i686/multiarch/Makefile
+++ b/sysdeps/i386/i686/multiarch/Makefile
@@ -1,7 +1,3 @@
-ifeq ($(subdir),csu)
-tests += test-multiarch
-endif
-
 ifeq ($(subdir),string)
 gen-as-const-headers += locale-defines.sym
 sysdep_routines += bzero-sse2 memset-sse2 memcpy-ssse3 mempcpy-ssse3 \
diff --git a/sysdeps/i386/i686/multiarch/test-multiarch.c b/sysdeps/i386/i686/multiarch/test-multiarch.c
deleted file mode 100644
index 593cfec273..0000000000
--- a/sysdeps/i386/i686/multiarch/test-multiarch.c
+++ /dev/null
@@ -1 +0,0 @@
-#include <sysdeps/x86_64/multiarch/test-multiarch.c>
diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
index 0478e22071..04655651b0 100644
--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
+++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
@@ -3,3 +3,4 @@ GLIBC_2.1 __libc_stack_end D 0x4
 GLIBC_2.1 _dl_mcount F
 GLIBC_2.3 ___tls_get_addr F
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.33 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
index d3cdf7611e..e632c6198e 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.2.5 __libc_stack_end D 0x8
 GLIBC_2.2.5 _dl_mcount F
 GLIBC_2.2.5 _r_debug D 0x28
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.33 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
index c70bccf782..9d9d0befde 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.16 __libc_stack_end D 0x4
 GLIBC_2.16 __tls_get_addr F
 GLIBC_2.16 _dl_mcount F
 GLIBC_2.16 _r_debug D 0x14
+GLIBC_2.33 __x86_get_cpu_features F
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index a6736aef25..c369faf00d 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -4,8 +4,10 @@ endif
 
 ifeq ($(subdir),elf)
 sysdep-dl-routines += dl-get-cpu-features
+sysdep_headers += sys/platform/x86.h
 
-tests += tst-get-cpu-features tst-get-cpu-features-static
+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
 endif
 
diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions
index e02923708e..59db578a9d 100644
--- a/sysdeps/x86/Versions
+++ b/sysdeps/x86/Versions
@@ -1,5 +1,5 @@
 ld {
-  GLIBC_PRIVATE {
-    __get_cpu_features;
+  GLIBC_2.33 {
+    __x86_get_cpu_features;
   }
 }
diff --git a/sysdeps/x86/dl-get-cpu-features.c b/sysdeps/x86/dl-get-cpu-features.c
index 9d61cd56be..5f9e46b0c6 100644
--- a/sysdeps/x86/dl-get-cpu-features.c
+++ b/sysdeps/x86/dl-get-cpu-features.c
@@ -18,10 +18,12 @@
 
 #include <ldsodefs.h>
 
-#undef __get_cpu_features
+#undef __x86_get_cpu_features
 
 const struct cpu_features *
-__get_cpu_features (void)
+__x86_get_cpu_features (unsigned int max)
 {
+  if (max > COMMON_CPUID_INDEX_MAX)
+    return NULL;
   return &GLRO(dl_x86_cpu_features);
 }
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
new file mode 100644
index 0000000000..dcf29b6fe8
--- /dev/null
+++ b/sysdeps/x86/include/cpu-features.h
@@ -0,0 +1,183 @@
+/* Data structure for x86 CPU features.
+   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/>.  */
+
+#ifndef	_PRIVATE_CPU_FEATURES_H
+#define	_PRIVATE_CPU_FEATURES_H	1
+
+#ifdef _CPU_FEATURES_H
+# error this should be impossible
+#endif
+
+#ifndef _ISOMAC
+/* Get most of the contents from the public header, but we define a
+   different `struct cpu_features' type for private use.  */
+# define cpu_features		cpu_features_public
+# define __x86_get_cpu_features	__x86_get_cpu_features_public
+#endif
+
+#include <sysdeps/x86/sys/platform/x86.h>
+
+#ifndef _ISOMAC
+
+# undef	cpu_features
+# undef __x86_get_cpu_features
+# define __get_cpu_features()	__x86_get_cpu_features (0)
+
+enum
+{
+  /* The integer bit array index for the first set of preferred feature
+     bits.  */
+  PREFERRED_FEATURE_INDEX_1 = 0,
+  /* The current maximum size of the feature integer bit array.  */
+  PREFERRED_FEATURE_INDEX_MAX
+};
+
+/* Only used directly in cpu-features.c.  */
+# define CPU_FEATURE_SET(ptr, name) \
+  ptr->features[index_cpu_##name].usable.reg_##name |= bit_cpu_##name;
+# define CPU_FEATURE_UNSET(ptr, name) \
+  ptr->features[index_cpu_##name].usable.reg_##name &= ~bit_cpu_##name;
+# define CPU_FEATURE_SET_USABLE(ptr, name) \
+  ptr->features[index_cpu_##name].usable.reg_##name \
+     |= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name;
+# define CPU_FEATURE_PREFERRED_P(ptr, name) \
+  ((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0)
+# define CPU_FEATURE_CPU_P(ptr, name) \
+  CPU_FEATURE_CHECK_P (ptr, name, cpuid)
+
+/* HAS_CPU_FEATURE evaluates to true if CPU supports the feature.  */
+# undef HAS_CPU_FEATURE
+# define HAS_CPU_FEATURE(name) \
+  CPU_FEATURE_CPU_P (__x86_get_cpu_features (0), name)
+/* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
+# undef CPU_FEATURE_USABLE
+# define CPU_FEATURE_USABLE(name) \
+  CPU_FEATURE_USABLE_P (__x86_get_cpu_features (0), name)
+/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at
+   runtime.  */
+# define CPU_FEATURE_PREFERRED(name) \
+  CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name)
+
+# define CPU_FEATURES_CPU_P(ptr, name) \
+  CPU_FEATURE_CPU_P (ptr, name)
+# define CPU_FEATURES_ARCH_P(ptr, name) \
+  CPU_FEATURE_PREFERRED_P (ptr, name)
+# define HAS_ARCH_FEATURE(name) \
+  CPU_FEATURE_PREFERRED (name)
+
+/* PREFERRED_FEATURE_INDEX_1.  */
+# define bit_arch_I586				(1u << 0)
+# define bit_arch_I686				(1u << 1)
+# define bit_arch_Fast_Rep_String		(1u << 2)
+# define bit_arch_Fast_Copy_Backward		(1u << 3)
+# define bit_arch_Fast_Unaligned_Load		(1u << 4)
+# define bit_arch_Fast_Unaligned_Copy		(1u << 5)
+# define bit_arch_Slow_BSF			(1u << 6)
+# define bit_arch_Slow_SSE4_2			(1u << 7)
+# define bit_arch_AVX_Fast_Unaligned_Load	(1u << 8)
+# define bit_arch_Prefer_MAP_32BIT_EXEC		(1u << 9)
+# define bit_arch_Prefer_PMINUB_for_stringop	(1u << 10)
+# define bit_arch_Prefer_No_VZEROUPPER		(1u << 11)
+# define bit_arch_Prefer_ERMS			(1u << 12)
+# define bit_arch_Prefer_FSRM			(1u << 13)
+# define bit_arch_Prefer_No_AVX512		(1u << 14)
+# define bit_arch_MathVec_Prefer_No_AVX512	(1u << 15)
+
+# define index_arch_Fast_Rep_String		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Copy_Backward		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_BSF			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Load		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_PMINUB_for_stringop 	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Copy		PREFERRED_FEATURE_INDEX_1
+# define index_arch_I586			PREFERRED_FEATURE_INDEX_1
+# define index_arch_I686			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_SSE4_2			PREFERRED_FEATURE_INDEX_1
+# define index_arch_AVX_Fast_Unaligned_Load	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_MAP_32BIT_EXEC	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_VZEROUPPER	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_ERMS			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_AVX512		PREFERRED_FEATURE_INDEX_1
+# define index_arch_MathVec_Prefer_No_AVX512	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_FSRM			PREFERRED_FEATURE_INDEX_1
+
+/* XCR0 Feature flags.  */
+# define bit_XMM_state		(1u << 1)
+# define bit_YMM_state		(1u << 2)
+# define bit_Opmask_state	(1u << 5)
+# define bit_ZMM0_15_state	(1u << 6)
+# define bit_ZMM16_31_state	(1u << 7)
+# define bit_XTILECFG_state	(1u << 17)
+# define bit_XTILEDATA_state	(1u << 18)
+
+struct cpu_features
+{
+  struct cpu_features_basic basic;
+  struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
+  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
+  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
+     int so that we use
+
+	sub xsave_state_size_offset(%rip) %RSP_LP
+
+     in _dl_runtime_resolve.  */
+  unsigned long int xsave_state_size;
+  /* The full state size for XSAVE when XSAVEC is disabled by
+
+     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC
+   */
+  unsigned int xsave_state_full_size;
+  /* Data cache size for use in memory and string routines, typically
+     L1 size.  */
+  unsigned long int data_cache_size;
+  /* Shared cache size for use in memory and string routines, typically
+     L2 or L3 size.  */
+  unsigned long int shared_cache_size;
+  /* Threshold to use non temporal store.  */
+  unsigned long int non_temporal_threshold;
+  /* Threshold to use "rep movsb".  */
+  unsigned long int rep_movsb_threshold;
+  /* Threshold to use "rep stosb".  */
+  unsigned long int rep_stosb_threshold;
+};
+
+# if defined (_LIBC) && !IS_IN (nonlib)
+/* Unused for x86.  */
+#  define INIT_ARCH()
+#  define __x86_get_cpu_features(max) (&GLRO(dl_x86_cpu_features))
+# endif
+
+# ifdef __x86_64__
+#  define HAS_CPUID 1
+# elif (defined __i586__ || defined __pentium__	\
+	|| defined __geode__ || defined __k6__)
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# elif defined __i486__
+#  define HAS_CPUID 0
+#  define HAS_I586 HAS_ARCH_FEATURE (I586)
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# else
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 1
+# endif
+
+#endif /* !_ISOMAC */
+
+#endif /* include/cpu-features.h */
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/sys/platform/x86.h
similarity index 81%
rename from sysdeps/x86/cpu-features.h
rename to sysdeps/x86/sys/platform/x86.h
index 78fcec251e..bf3727ebc0 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/sys/platform/x86.h
@@ -1,4 +1,5 @@
-/* This file is part of the GNU C Library.
+/* Data structure for x86 CPU features.
+   This file is part of the GNU C Library.
    Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,17 +16,8 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#ifndef cpu_features_h
-#define cpu_features_h
-
-enum
-{
-  /* The integer bit array index for the first set of preferred feature
-     bits.  */
-  PREFERRED_FEATURE_INDEX_1 = 0,
-  /* The current maximum size of the feature integer bit array.  */
-  PREFERRED_FEATURE_INDEX_MAX
-};
+#ifndef _SYS_PLATFORM_X86_H
+#define _SYS_PLATFORM_X86_H
 
 enum
 {
@@ -76,73 +68,32 @@ struct cpu_features
 {
   struct cpu_features_basic basic;
   struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
-  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
-  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
-     int so that we use
-
-	sub xsave_state_size_offset(%rip) %RSP_LP
-
-     in _dl_runtime_resolve.  */
-  unsigned long int xsave_state_size;
-  /* The full state size for XSAVE when XSAVEC is disabled by
-
-     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC
-   */
-  unsigned int xsave_state_full_size;
-  /* Data cache size for use in memory and string routines, typically
-     L1 size.  */
-  unsigned long int data_cache_size;
-  /* Shared cache size for use in memory and string routines, typically
-     L2 or L3 size.  */
-  unsigned long int shared_cache_size;
-  /* Threshold to use non temporal store.  */
-  unsigned long int non_temporal_threshold;
-  /* Threshold to use "rep movsb".  */
-  unsigned long int rep_movsb_threshold;
-  /* Threshold to use "rep stosb".  */
-  unsigned long int rep_stosb_threshold;
 };
 
-/* Used from outside of glibc to get access to the CPU features
-   structure.  */
-extern const struct cpu_features *__get_cpu_features (void)
+/* Get a pointer to the CPU features structure.  */
+extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
      __attribute__ ((const));
 
-/* Only used directly in cpu-features.c.  */
 #define CPU_FEATURE_CHECK_P(ptr, name, check) \
   ((ptr->features[index_cpu_##name].check.reg_##name \
     & bit_cpu_##name) != 0)
-#define CPU_FEATURE_SET(ptr, name) \
-  ptr->features[index_cpu_##name].usable.reg_##name |= bit_cpu_##name;
-#define CPU_FEATURE_UNSET(ptr, name) \
-  ptr->features[index_cpu_##name].usable.reg_##name &= ~bit_cpu_##name;
-#define CPU_FEATURE_SET_USABLE(ptr, name) \
-  ptr->features[index_cpu_##name].usable.reg_##name \
-     |= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name;
-#define CPU_FEATURE_PREFERRED_P(ptr, name) \
-  ((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0)
 #define CPU_FEATURE_CPU_P(ptr, name) \
   CPU_FEATURE_CHECK_P (ptr, name, cpuid)
 #define CPU_FEATURE_USABLE_P(ptr, name) \
   CPU_FEATURE_CHECK_P (ptr, name, usable)
 
 /* HAS_CPU_FEATURE evaluates to true if CPU supports the feature.  */
-#define HAS_CPU_FEATURE(name) \
-  CPU_FEATURE_CPU_P (__get_cpu_features (), name)
+#define HAS_CPU_FEATURE(name)					\
+  (__extension__						\
+   ({ const struct cpu_features *__ptr =			\
+	__x86_get_cpu_features (COMMON_CPUID_INDEX_MAX);	\
+      __ptr && CPU_FEATURE_CPU_P (__ptr, name); }))
 /* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
-#define CPU_FEATURE_USABLE(name) \
-  CPU_FEATURE_USABLE_P (__get_cpu_features (), name)
-/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at
-   runtime.  */
-#define CPU_FEATURE_PREFERRED(name) \
-  CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name)
-
-#define CPU_FEATURES_CPU_P(ptr, name) \
-  CPU_FEATURE_CPU_P (ptr, name)
-#define CPU_FEATURES_ARCH_P(ptr, name) \
-  CPU_FEATURE_PREFERRED_P (ptr, name)
-#define HAS_ARCH_FEATURE(name) \
-  CPU_FEATURE_PREFERRED (name)
+#define CPU_FEATURE_USABLE(name)				\
+  (__extension__						\
+   ({ const struct cpu_features *__ptr =			\
+	__x86_get_cpu_features (COMMON_CPUID_INDEX_MAX);	\
+      __ptr && CPU_FEATURE_USABLE_P (__ptr, name); }))
 
 /* CPU features.  */
 
@@ -787,71 +738,4 @@ extern const struct cpu_features *__get_cpu_features (void)
 /* EAX.  */
 #define reg_AVX512_BF16		eax
 
-/* FEATURE_INDEX_2.  */
-#define bit_arch_I586				(1u << 0)
-#define bit_arch_I686				(1u << 1)
-#define bit_arch_Fast_Rep_String		(1u << 2)
-#define bit_arch_Fast_Copy_Backward		(1u << 3)
-#define bit_arch_Fast_Unaligned_Load		(1u << 4)
-#define bit_arch_Fast_Unaligned_Copy		(1u << 5)
-#define bit_arch_Slow_BSF			(1u << 6)
-#define bit_arch_Slow_SSE4_2			(1u << 7)
-#define bit_arch_AVX_Fast_Unaligned_Load	(1u << 8)
-#define bit_arch_Prefer_MAP_32BIT_EXEC		(1u << 9)
-#define bit_arch_Prefer_PMINUB_for_stringop	(1u << 10)
-#define bit_arch_Prefer_No_VZEROUPPER		(1u << 11)
-#define bit_arch_Prefer_ERMS			(1u << 12)
-#define bit_arch_Prefer_FSRM			(1u << 13)
-#define bit_arch_Prefer_No_AVX512		(1u << 14)
-#define bit_arch_MathVec_Prefer_No_AVX512	(1u << 15)
-
-#define index_arch_Fast_Rep_String		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Copy_Backward		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_BSF			PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Load		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_PMINUB_for_stringop 	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Copy		PREFERRED_FEATURE_INDEX_1
-#define index_arch_I586				PREFERRED_FEATURE_INDEX_1
-#define index_arch_I686				PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_SSE4_2			PREFERRED_FEATURE_INDEX_1
-#define index_arch_AVX_Fast_Unaligned_Load	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_MAP_32BIT_EXEC	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_VZEROUPPER		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_ERMS			PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_AVX512		PREFERRED_FEATURE_INDEX_1
-#define index_arch_MathVec_Prefer_No_AVX512	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_FSRM			PREFERRED_FEATURE_INDEX_1
-
-/* XCR0 Feature flags.  */
-#define bit_XMM_state		(1u << 1)
-#define bit_YMM_state		(1u << 2)
-#define bit_Opmask_state	(1u << 5)
-#define bit_ZMM0_15_state	(1u << 6)
-#define bit_ZMM16_31_state	(1u << 7)
-#define bit_XTILECFG_state	(1u << 17)
-#define bit_XTILEDATA_state	(1u << 18)
-
-# if defined (_LIBC) && !IS_IN (nonlib)
-/* Unused for x86.  */
-#  define INIT_ARCH()
-#  define __get_cpu_features()	(&GLRO(dl_x86_cpu_features))
-# endif
-
-#ifdef __x86_64__
-# define HAS_CPUID 1
-#elif (defined __i586__ || defined __pentium__	\
-       || defined __geode__ || defined __k6__)
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#elif defined __i486__
-# define HAS_CPUID 0
-# define HAS_I586 HAS_ARCH_FEATURE (I586)
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#else
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 1
-#endif
-
-#endif  /* cpu_features_h */
+#endif  /* _SYS_PLATFORM_X86_H */
diff --git a/sysdeps/x86/tst-cpu-features-cpuinfo.c b/sysdeps/x86/tst-cpu-features-cpuinfo.c
new file mode 100644
index 0000000000..96277284d1
--- /dev/null
+++ b/sysdeps/x86/tst-cpu-features-cpuinfo.c
@@ -0,0 +1,250 @@
+/* Test CPU feature data against /proc/cpuinfo.
+   This file is part of the GNU C Library.
+   Copyright (C) 2012-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>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char *cpu_flags;
+
+/* Search for flags in /proc/cpuinfo and store line
+   in cpu_flags.  */
+void
+get_cpuinfo (void)
+{
+  FILE *f;
+  char *line = NULL;
+  size_t len = 0;
+  ssize_t read;
+
+  f = fopen ("/proc/cpuinfo", "r");
+  if (f == NULL)
+    {
+      printf ("cannot open /proc/cpuinfo\n");
+      exit (1);
+    }
+
+  while ((read = getline (&line, &len, f)) != -1)
+    {
+      if (strncmp (line, "flags", 5) == 0)
+       {
+         cpu_flags = strdup (line);
+         break;
+       }
+    }
+  fclose (f);
+  free (line);
+}
+
+int
+check_proc (const char *proc_name, int flag, int usable, const char *name)
+{
+  int found = 0;
+
+  printf ("Checking %s:\n", name);
+  if (!usable)
+    {
+      printf ("  %s: insufficient usable info, skipped\n", name);
+      return 0;
+    }
+  printf ("  %s: %d\n", name, flag);
+  if (strstr (cpu_flags, proc_name) != NULL)
+    found = 1;
+  printf ("  cpuinfo (%s): %d\n", proc_name, found);
+
+  if (found != flag)
+    printf (" *** failure ***\n");
+
+  return (found != flag);
+}
+
+#define CHECK_PROC(str, name) \
+  check_proc (#str, HAS_CPU_FEATURE (name), CPU_FEATURE_USABLE (name), \
+	      "HAS_CPU_FEATURE (" #name ")");
+
+static int
+do_test (int argc, char **argv)
+{
+  int fails = 0;
+
+  get_cpuinfo ();
+  fails += CHECK_PROC (acpi, ACPI);
+  fails += CHECK_PROC (adx, ADX);
+  fails += CHECK_PROC (apic, APIC);
+  fails += CHECK_PROC (aes, AES);
+  fails += CHECK_PROC (amx_bf16, AMX_BF16);
+  fails += CHECK_PROC (amx_int8, AMX_INT8);
+  fails += CHECK_PROC (amx_tile, AMX_TILE);
+  fails += CHECK_PROC (arch_capabilities, ARCH_CAPABILITIES);
+  fails += CHECK_PROC (avx, AVX);
+  fails += CHECK_PROC (avx2, AVX2);
+  fails += CHECK_PROC (avx512_4fmaps, AVX512_4FMAPS);
+  fails += CHECK_PROC (avx512_4vnniw, AVX512_4VNNIW);
+  fails += CHECK_PROC (avx512_bf16, AVX512_BF16);
+  fails += CHECK_PROC (avx512_bitalg, AVX512_BITALG);
+  fails += CHECK_PROC (avx512ifma, AVX512_IFMA);
+  fails += CHECK_PROC (avx512_vbmi, AVX512_VBMI);
+  fails += CHECK_PROC (avx512_vbmi2, AVX512_VBMI2);
+  fails += CHECK_PROC (avx512_vnni, AVX512_VNNI);
+  fails += CHECK_PROC (avx512_vp2intersect, AVX512_VP2INTERSECT);
+  fails += CHECK_PROC (avx512_vpopcntdq, AVX512_VPOPCNTDQ);
+  fails += CHECK_PROC (avx512bw, AVX512BW);
+  fails += CHECK_PROC (avx512cd, AVX512CD);
+  fails += CHECK_PROC (avx512er, AVX512ER);
+  fails += CHECK_PROC (avx512dq, AVX512DQ);
+  fails += CHECK_PROC (avx512f, AVX512F);
+  fails += CHECK_PROC (avx512pf, AVX512PF);
+  fails += CHECK_PROC (avx512vl, AVX512VL);
+  fails += CHECK_PROC (bmi1, BMI1);
+  fails += CHECK_PROC (bmi2, BMI2);
+  fails += CHECK_PROC (cldemote, CLDEMOTE);
+  fails += CHECK_PROC (clflushopt, CLFLUSHOPT);
+  fails += CHECK_PROC (clflush, CLFSH);
+  fails += CHECK_PROC (clwb, CLWB);
+  fails += CHECK_PROC (cmov, CMOV);
+  fails += CHECK_PROC (cx16, CMPXCHG16B);
+  fails += CHECK_PROC (cnxt_id, CNXT_ID);
+  fails += CHECK_PROC (core_capabilities, CORE_CAPABILITIES);
+  fails += CHECK_PROC (cx8, CX8);
+  fails += CHECK_PROC (dca, DCA);
+  fails += CHECK_PROC (de, DE);
+  fails += CHECK_PROC (zero_fcs_fds, DEPR_FPU_CS_DS);
+  fails += CHECK_PROC (ds, DS);
+  fails += CHECK_PROC (ds_cpl, DS_CPL);
+  fails += CHECK_PROC (dtes64, DTES64);
+  fails += CHECK_PROC (est, EIST);
+  fails += CHECK_PROC (enqcmd, ENQCMD);
+  fails += CHECK_PROC (erms, ERMS);
+  fails += CHECK_PROC (f16c, F16C);
+  fails += CHECK_PROC (fma, FMA);
+  fails += CHECK_PROC (fma4, FMA4);
+  fails += CHECK_PROC (fpu, FPU);
+  fails += CHECK_PROC (fsgsbase, FSGSBASE);
+  fails += CHECK_PROC (fsrm, FSRM);
+  fails += CHECK_PROC (fxsr, FXSR);
+  fails += CHECK_PROC (gfni, GFNI);
+  fails += CHECK_PROC (hle, HLE);
+  fails += CHECK_PROC (ht, HTT);
+  fails += CHECK_PROC (hybrid, HYBRID);
+  fails += CHECK_PROC (ibrs, IBRS_IBPB);
+  fails += CHECK_PROC (ibt, IBT);
+  fails += CHECK_PROC (invariant_tsc, INVARIANT_TSC);
+  fails += CHECK_PROC (invpcid, INVPCID);
+  fails += CHECK_PROC (flush_l1d, L1D_FLUSH);
+  fails += CHECK_PROC (lahf_lm, LAHF64_SAHF64);
+  fails += CHECK_PROC (lm, LM);
+  fails += CHECK_PROC (lwp, LWP);
+  fails += CHECK_PROC (abm, LZCNT);
+  fails += CHECK_PROC (mca, MCA);
+  fails += CHECK_PROC (mce, MCE);
+  fails += CHECK_PROC (md_clear, MD_CLEAR);
+  fails += CHECK_PROC (mmx, MMX);
+  fails += CHECK_PROC (monitor, MONITOR);
+  fails += CHECK_PROC (movbe, MOVBE);
+  fails += CHECK_PROC (movdiri, MOVDIRI);
+  fails += CHECK_PROC (movdir64b, MOVDIR64B);
+  fails += CHECK_PROC (mpx, MPX);
+  fails += CHECK_PROC (msr, MSR);
+  fails += CHECK_PROC (mtrr, MTRR);
+  fails += CHECK_PROC (nx, NX);
+  fails += CHECK_PROC (ospke, OSPKE);
+#if 0
+  /* NB: /proc/cpuinfo doesn't report this feature.  */
+  fails += CHECK_PROC (osxsave, OSXSAVE);
+#endif
+  fails += CHECK_PROC (pae, PAE);
+  fails += CHECK_PROC (pdpe1gb, PAGE1GB);
+  fails += CHECK_PROC (pat, PAT);
+  fails += CHECK_PROC (pbe, PBE);
+  fails += CHECK_PROC (pcid, PCID);
+  fails += CHECK_PROC (pclmulqdq, PCLMULQDQ);
+  fails += CHECK_PROC (pconfig, PCONFIG);
+  fails += CHECK_PROC (pdcm, PDCM);
+  fails += CHECK_PROC (pge, PGE);
+  fails += CHECK_PROC (pks, PKS);
+  fails += CHECK_PROC (pku, PKU);
+  fails += CHECK_PROC (popcnt, POPCNT);
+  fails += CHECK_PROC (3dnowprefetch, PREFETCHW);
+  fails += CHECK_PROC (prefetchwt1, PREFETCHWT1);
+  fails += CHECK_PROC (pse, PSE);
+  fails += CHECK_PROC (pse36, PSE_36);
+  fails += CHECK_PROC (psn, PSN);
+  fails += CHECK_PROC (rdpid, RDPID);
+  fails += CHECK_PROC (rdrand, RDRAND);
+  fails += CHECK_PROC (rdseed, RDSEED);
+  fails += CHECK_PROC (rdt_a, RDT_A);
+  fails += CHECK_PROC (cqm, RDT_M);
+  fails += CHECK_PROC (rdtscp, RDTSCP);
+  fails += CHECK_PROC (rtm, RTM);
+  fails += CHECK_PROC (sdbg, SDBG);
+  fails += CHECK_PROC (sep, SEP);
+  fails += CHECK_PROC (serialize, SERIALIZE);
+  fails += CHECK_PROC (sgx, SGX);
+  fails += CHECK_PROC (sgx_lc, SGX_LC);
+  fails += CHECK_PROC (sha_ni, SHA);
+  fails += CHECK_PROC (shstk, SHSTK);
+  fails += CHECK_PROC (smap, SMAP);
+  fails += CHECK_PROC (smep, SMEP);
+  fails += CHECK_PROC (smx, SMX);
+  fails += CHECK_PROC (ss, SS);
+  fails += CHECK_PROC (ssbd, SSBD);
+  fails += CHECK_PROC (sse, SSE);
+  fails += CHECK_PROC (sse2, SSE2);
+  fails += CHECK_PROC (sse3, SSE3);
+  fails += CHECK_PROC (sse4_1, SSE4_1);
+  fails += CHECK_PROC (sse4_2, SSE4_2);
+  fails += CHECK_PROC (sse4a, SSE4A);
+  fails += CHECK_PROC (ssse3, SSSE3);
+  fails += CHECK_PROC (stibp, STIBP);
+  fails += CHECK_PROC (svm, SVM);
+#ifdef __x86_64__
+  /* NB: SYSCALL_SYSRET is 64-bit only.  */
+  fails += CHECK_PROC (syscall, SYSCALL_SYSRET);
+#endif
+  fails += CHECK_PROC (tbm, TBM);
+  fails += CHECK_PROC (tm, TM);
+  fails += CHECK_PROC (tm2, TM2);
+  fails += CHECK_PROC (intel_pt, TRACE);
+  fails += CHECK_PROC (tsc, TSC);
+  fails += CHECK_PROC (tsc_adjust, TSC_ADJUST);
+  fails += CHECK_PROC (tsc_deadline, TSC_DEADLINE);
+  fails += CHECK_PROC (tsxldtrk, TSXLDTRK);
+  fails += CHECK_PROC (umip, UMIP);
+  fails += CHECK_PROC (vaes, VAES);
+  fails += CHECK_PROC (vme, VME);
+  fails += CHECK_PROC (vmx, VMX);
+  fails += CHECK_PROC (vpclmulqdq, VPCLMULQDQ);
+  fails += CHECK_PROC (waitpkg, WAITPKG);
+  fails += CHECK_PROC (wbnoinvd, WBNOINVD);
+  fails += CHECK_PROC (x2apic, X2APIC);
+  fails += CHECK_PROC (xfd, XFD);
+  fails += CHECK_PROC (xgetbv1, XGETBV_ECX_1);
+  fails += CHECK_PROC (xop, XOP);
+  fails += CHECK_PROC (xsave, XSAVE);
+  fails += CHECK_PROC (xsavec, XSAVEC);
+  fails += CHECK_PROC (xsaveopt, XSAVEOPT);
+  fails += CHECK_PROC (xsaves, XSAVES);
+  fails += CHECK_PROC (xtpr, XTPRUPDCTRL);
+
+  printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails);
+
+  return (fails != 0);
+}
+
+#include "../../../test-skeleton.c"
diff --git a/sysdeps/x86/tst-cpu-features-supports.c b/sysdeps/x86/tst-cpu-features-supports.c
new file mode 100644
index 0000000000..bf881b531f
--- /dev/null
+++ b/sysdeps/x86/tst-cpu-features-supports.c
@@ -0,0 +1,192 @@
+/* Test CPU feature data against __builtin_cpu_supports.
+   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>
+#include <stdio.h>
+
+int
+check_supports (int supports, int usable, const char *supports_name,
+		const char *name)
+{
+  printf ("Checking %s:\n", name);
+  printf ("  %s: %d\n", name, usable);
+  printf ("  __builtin_cpu_supports (%s): %d\n",
+	  supports_name, supports);
+
+  if ((supports != 0) != (usable != 0))
+    {
+      printf (" *** failure ***\n");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define CHECK_SUPPORTS(str, name) \
+  check_supports (__builtin_cpu_supports (#str), \
+		  CPU_FEATURE_USABLE (name), \
+		  #str, "HAS_CPU_FEATURE (" #name ")");
+
+static int
+do_test (int argc, char **argv)
+{
+  int fails = 0;
+
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (adx, ADX);
+#endif
+#if __GNUC_PREREQ (6, 0)
+  fails += CHECK_SUPPORTS (aes, AES);
+#endif
+#if __GNUC_PREREQ (11, 1)
+  fails += CHECK_SUPPORTS (amx_bf16, AMX_BF16);
+  fails += CHECK_SUPPORTS (amx_int8, AMX_INT8);
+  fails += CHECK_SUPPORTS (amx_tile, AMX_TILE);
+#endif
+  fails += CHECK_SUPPORTS (avx, AVX);
+  fails += CHECK_SUPPORTS (avx2, AVX2);
+#if __GNUC_PREREQ (7, 0)
+  fails += CHECK_SUPPORTS (avx5124fmaps, AVX512_4FMAPS);
+  fails += CHECK_SUPPORTS (avx5124vnniw, AVX512_4VNNIW);
+#endif
+#if __GNUC_PREREQ (10, 0)
+  fails += CHECK_SUPPORTS (avx512bf16, AVX512_BF16);
+#endif
+#if __GNUC_PREREQ (8, 0)
+  fails += CHECK_SUPPORTS (avx512bitalg, AVX512_BITALG);
+#endif
+#if __GNUC_PREREQ (6, 0)
+  fails += CHECK_SUPPORTS (avx512ifma, AVX512_IFMA);
+  fails += CHECK_SUPPORTS (avx512vbmi, AVX512_VBMI);
+#endif
+#if __GNUC_PREREQ (8, 0)
+  fails += CHECK_SUPPORTS (avx512vbmi2, AVX512_VBMI2);
+  fails += CHECK_SUPPORTS (avx512vnni, AVX512_VNNI);
+#endif
+#if __GNUC_PREREQ (10, 0)
+  fails += CHECK_SUPPORTS (avx512vp2intersect, AVX512_VP2INTERSECT);
+#endif
+#if __GNUC_PREREQ (7, 0)
+  fails += CHECK_SUPPORTS (avx512vpopcntdq, AVX512_VPOPCNTDQ);
+#endif
+#if __GNUC_PREREQ (6, 0)
+  fails += CHECK_SUPPORTS (avx512bw, AVX512BW);
+  fails += CHECK_SUPPORTS (avx512cd, AVX512CD);
+  fails += CHECK_SUPPORTS (avx512er, AVX512ER);
+  fails += CHECK_SUPPORTS (avx512dq, AVX512DQ);
+#endif
+#if __GNUC_PREREQ (5, 0)
+  fails += CHECK_SUPPORTS (avx512f, AVX512F);
+#endif
+#if __GNUC_PREREQ (6, 0)
+  fails += CHECK_SUPPORTS (avx512pf, AVX512PF);
+  fails += CHECK_SUPPORTS (avx512vl, AVX512VL);
+#endif
+#if __GNUC_PREREQ (5, 0)
+  fails += CHECK_SUPPORTS (bmi, BMI1);
+  fails += CHECK_SUPPORTS (bmi2, BMI2);
+#endif
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (cldemote, CLDEMOTE);
+  fails += CHECK_SUPPORTS (clflushopt, CLFLUSHOPT);
+  fails += CHECK_SUPPORTS (clwb, CLWB);
+#endif
+  fails += CHECK_SUPPORTS (cmov, CMOV);
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (cmpxchg16b, CMPXCHG16B);
+  fails += CHECK_SUPPORTS (cmpxchg8b, CX8);
+  fails += CHECK_SUPPORTS (enqcmd, ENQCMD);
+  fails += CHECK_SUPPORTS (f16c, F16C);
+#endif
+#if __GNUC_PREREQ (4, 9)
+  fails += CHECK_SUPPORTS (fma, FMA);
+  fails += CHECK_SUPPORTS (fma4, FMA4);
+#endif
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (fsgsbase, FSGSBASE);
+  fails += CHECK_SUPPORTS (fxsave, FXSR);
+#endif
+#if __GNUC_PREREQ (8, 0)
+  fails += CHECK_SUPPORTS (gfni, GFNI);
+#endif
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (hle, HLE);
+  fails += CHECK_SUPPORTS (ibt, IBT);
+  fails += CHECK_SUPPORTS (lahf_lm, LAHF64_SAHF64);
+  fails += CHECK_SUPPORTS (lm, LM);
+  fails += CHECK_SUPPORTS (lwp, LWP);
+  fails += CHECK_SUPPORTS (lzcnt, LZCNT);
+#endif
+  fails += CHECK_SUPPORTS (mmx, MMX);
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (movbe, MOVBE);
+  fails += CHECK_SUPPORTS (movdiri, MOVDIRI);
+  fails += CHECK_SUPPORTS (movdir64b, MOVDIR64B);
+  fails += CHECK_SUPPORTS (osxsave, OSXSAVE);
+  fails += CHECK_SUPPORTS (pconfig, PCONFIG);
+  fails += CHECK_SUPPORTS (pku, PKU);
+#endif
+  fails += CHECK_SUPPORTS (popcnt, POPCNT);
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (prefetchwt1, PREFETCHWT1);
+  fails += CHECK_SUPPORTS (rdpid, RDPID);
+  fails += CHECK_SUPPORTS (rdrnd, RDRAND);
+  fails += CHECK_SUPPORTS (rdseed, RDSEED);
+  fails += CHECK_SUPPORTS (rtm, RTM);
+  fails += CHECK_SUPPORTS (serialize, SERIALIZE);
+  fails += CHECK_SUPPORTS (sha, SHA);
+  fails += CHECK_SUPPORTS (shstk, SHSTK);
+#endif
+  fails += CHECK_SUPPORTS (sse, SSE);
+  fails += CHECK_SUPPORTS (sse2, SSE2);
+  fails += CHECK_SUPPORTS (sse3, SSE3);
+  fails += CHECK_SUPPORTS (sse4.1, SSE4_1);
+  fails += CHECK_SUPPORTS (sse4.2, SSE4_2);
+#if __GNUC_PREREQ (4, 9)
+  fails += CHECK_SUPPORTS (sse4a, SSE4A);
+#endif
+  fails += CHECK_SUPPORTS (ssse3, SSSE3);
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (tbm, TBM);
+  fails += CHECK_SUPPORTS (tsxldtrk, TSXLDTRK);
+  fails += CHECK_SUPPORTS (vaes, VAES);
+#endif
+#if __GNUC_PREREQ (8, 0)
+  fails += CHECK_SUPPORTS (vpclmulqdq, VPCLMULQDQ);
+#endif
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (waitpkg, WAITPKG);
+  fails += CHECK_SUPPORTS (wbnoinvd, WBNOINVD);
+#endif
+#if __GNUC_PREREQ (4, 9)
+  fails += CHECK_SUPPORTS (xop, XOP);
+#endif
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (xsave, XSAVE);
+  fails += CHECK_SUPPORTS (xsavec, XSAVEC);
+  fails += CHECK_SUPPORTS (xsaveopt, XSAVEOPT);
+  fails += CHECK_SUPPORTS (xsaves, XSAVES);
+#endif
+
+  printf ("%d differences between __builtin_cpu_supports and glibc code.\n",
+	  fails);
+
+  return (fails != 0);
+}
+
+#include "../../../test-skeleton.c"
diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
index 6bfdef0829..3447d17e23 100644
--- a/sysdeps/x86/tst-get-cpu-features.c
+++ b/sysdeps/x86/tst-get-cpu-features.c
@@ -1,4 +1,4 @@
-/* Test case for x86 __get_cpu_features interface
+/* Test case for __x86_get_cpu_features interface
    Copyright (C) 2015-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -18,7 +18,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 #include <support/check.h>
 
 #define CHECK_CPU_FEATURE(name)		\
@@ -45,7 +45,7 @@ static const char * const cpu_kinds[] =
 static int
 do_test (void)
 {
-  const struct cpu_features *cpu_features = __get_cpu_features ();
+  const struct cpu_features *cpu_features = __x86_get_cpu_features (0);
 
   switch (cpu_features->basic.kind)
     {
diff --git a/sysdeps/x86_64/fpu/math-tests-arch.h b/sysdeps/x86_64/fpu/math-tests-arch.h
index 33ea763de2..cc3c2b0c11 100644
--- a/sysdeps/x86_64/fpu/math-tests-arch.h
+++ b/sysdeps/x86_64/fpu/math-tests-arch.h
@@ -16,7 +16,7 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 
 #if defined REQUIRE_AVX
 
diff --git a/sysdeps/x86_64/multiarch/Makefile b/sysdeps/x86_64/multiarch/Makefile
index 395e432c09..9477538af4 100644
--- a/sysdeps/x86_64/multiarch/Makefile
+++ b/sysdeps/x86_64/multiarch/Makefile
@@ -1,7 +1,3 @@
-ifeq ($(subdir),csu)
-tests += test-multiarch
-endif
-
 ifeq ($(subdir),string)
 
 sysdep_routines += strncat-c stpncpy-c strncpy-c \
diff --git a/sysdeps/x86_64/multiarch/test-multiarch.c b/sysdeps/x86_64/multiarch/test-multiarch.c
deleted file mode 100644
index 2782803e73..0000000000
--- a/sysdeps/x86_64/multiarch/test-multiarch.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Test CPU feature data.
-   This file is part of the GNU C Library.
-   Copyright (C) 2012-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 <cpu-features.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static char *cpu_flags;
-
-/* Search for flags in /proc/cpuinfo and store line
-   in cpu_flags.  */
-void
-get_cpuinfo (void)
-{
-  FILE *f;
-  char *line = NULL;
-  size_t len = 0;
-  ssize_t read;
-
-  f = fopen ("/proc/cpuinfo", "r");
-  if (f == NULL)
-    {
-      printf ("cannot open /proc/cpuinfo\n");
-      exit (1);
-    }
-
-  while ((read = getline (&line, &len, f)) != -1)
-    {
-      if (strncmp (line, "flags", 5) == 0)
-       {
-         cpu_flags = strdup (line);
-         break;
-       }
-    }
-  fclose (f);
-  free (line);
-}
-
-int
-check_proc (const char *proc_name, int flag, const char *name)
-{
-  int found = 0;
-
-  printf ("Checking %s:\n", name);
-  printf ("  init-arch %d\n", flag);
-  if (strstr (cpu_flags, proc_name) != NULL)
-    found = 1;
-  printf ("  cpuinfo (%s) %d\n", proc_name, found);
-
-  if (found != flag)
-    printf (" *** failure ***\n");
-
-  return (found != flag);
-}
-
-static int
-do_test (int argc, char **argv)
-{
-  int fails;
-
-  get_cpuinfo ();
-  fails = check_proc ("avx", CPU_FEATURE_USABLE (AVX),
-		      "CPU_FEATURE_USABLE (AVX)");
-  fails += check_proc ("fma4", CPU_FEATURE_USABLE (FMA4),
-		       "CPU_FEATURE_USABLE (FMA4)");
-  fails += check_proc ("sse4_2", CPU_FEATURE_USABLE (SSE4_2),
-		       "CPU_FEATURE_USABLE (SSE4_2)");
-  fails += check_proc ("sse4_1", CPU_FEATURE_USABLE (SSE4_1)
-		       , "CPU_FEATURE_USABLE (SSE4_1)");
-  fails += check_proc ("ssse3", CPU_FEATURE_USABLE (SSSE3),
-		       "CPU_FEATURE_USABLE (SSSE3)");
-  fails += check_proc ("popcnt", CPU_FEATURE_USABLE (POPCNT),
-		       "CPU_FEATURE_USABLE (POPCNT)");
-
-  printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails);
-
-  return (fails != 0);
-}
-
-#include "../../../test-skeleton.c"
Michael Kerrisk \(man-pages\) via Libc-alpha Sept. 10, 2020, 2:29 p.m. | #5
On Mon, Sep 7, 2020 at 11:21 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>

> On Wed, Sep 2, 2020 at 5:55 AM H.J. Lu <hjl.tools@gmail.com> wrote:

> >

> > On Wed, Aug 19, 2020 at 5:52 AM H.J. Lu <hjl.tools@gmail.com> wrote:

> > >

> > > On Wed, Aug 12, 2020 at 7:00 AM H.J. Lu <hjl.tools@gmail.com> wrote:

> > > >

> > > > On Wed, Aug 5, 2020 at 4:01 PM H.J. Lu <hjl.tools@gmail.com> wrote:

> > > > >

> > > > > Install <sys/platform/x86.h> so that programmers can do

> > > > >

> > > > >  #if __has_include(<sys/platform/x86.h>)

> > > > >  #include <sys/platform/x86.h>

> > > > >  #endif

> > > > >  ...

> > > > >

> > > > >    if (CPU_FEATURE_USABLE (SSE2))

> > > > >  ...

> > > > >    if (CPU_FEATURE_USABLE (AVX2))

> > > > >  ...

> > > > >

> > > > > <sys/platform/x86.h> exports only:

> > > > >

> > > > > enum

> > > > > {

> > > > >   COMMON_CPUID_INDEX_1 = 0,

> > > > >   COMMON_CPUID_INDEX_7,

> > > > >   COMMON_CPUID_INDEX_80000001,

> > > > >   COMMON_CPUID_INDEX_D_ECX_1,

> > > > >   COMMON_CPUID_INDEX_80000007,

> > > > >   COMMON_CPUID_INDEX_80000008,

> > > > >   COMMON_CPUID_INDEX_7_ECX_1,

> > > > >   /* Keep the following line at the end.  */

> > > > >   COMMON_CPUID_INDEX_MAX

> > > > > };

> > > > >

> > > > > struct cpuid_features

> > > > > {

> > > > >   struct cpuid_registers cpuid;

> > > > >   struct cpuid_registers usable;

> > > > > };

> > > > >

> > > > > struct cpu_features

> > > > > {

> > > > >   struct cpu_features_basic basic;

> > > > >   struct cpuid_features features[COMMON_CPUID_INDEX_MAX];

> > > > > };

> > > > >

> > > > > /* Get a pointer to the CPU features structure.  */

> > > > > extern const struct cpu_features *__x86_get_cpu_features

> > > > >   (unsigned int max) __attribute__ ((const));

> > > > >

> > > > > Since all feature checks are done through macros, programs compiled with

> > > > > a newer <sys/platform/x86.h> are compatible with the older glibc binaries

> > > > > as long as the layout of struct cpu_features is identical.  The features

> > > > > array can be expanded with backward binary compatibility for both .o and

> > > > > .so files.  When COMMON_CPUID_INDEX_MAX is increased to support new

> > > > > processor features, __x86_get_cpu_features in the older glibc binaries

> > > > > returns NULL and HAS_CPU_FEATURE/CPU_FEATURE_USABLE return false on the

> > > > > new processor feature.  No new symbol version is neeeded.

> > > > >

> > > > > Both CPU_FEATURE_USABLE and HAS_CPU_FEATURE are provided.  HAS_CPU_FEATURE

> > > > > can be used to identify processor features.

> > > > >

> > > > > Note: Although GCC has __builtin_cpu_supports, it only supports a subset

> > > > > of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE.  It

> > > > > doesn't support HAS_CPU_FEATURE.

> > >

> > > PING:

> > >

> > > https://sourceware.org/pipermail/libc-alpha/2020-August/116865.html

> > >

> >

> > If there are no more comments, I will check it next Friday,

> > Sept 11.

> >

>

> I am enclosing the rebased patch I am checking in this Friday.

>


I will check this in tomorrow:

https://sourceware.org/pipermail/libc-alpha/2020-September/117466.html

-- 
H.J.

Patch

diff --git a/NEWS b/NEWS
index 2937adc3f3..d19551c132 100644
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,7 @@  Version 2.33
 
 Major new features:
 
-  [Add new features here]
+* Add <sys/platform/x86.h> to provide query macros for x86 CPU features.
 
 Deprecated and removed features, and other changes affecting compatibility:
 
diff --git a/manual/platform.texi b/manual/platform.texi
index 504addc956..2c145acdc3 100644
--- a/manual/platform.texi
+++ b/manual/platform.texi
@@ -7,6 +7,7 @@ 
 @menu
 * PowerPC::           Facilities Specific to the PowerPC Architecture
 * RISC-V::            Facilities Specific to the RISC-V Architecture
+* X86::               Facilities Specific to the X86 Architecture
 @end menu
 
 @node PowerPC
@@ -134,3 +135,519 @@  all threads in the current process.  Setting the
 ordering on only the current thread is necessary.  All other flag bits are
 reserved.
 @end deftypefun
+
+@node X86
+@appendixsec X86-specific Facilities
+
+Facilities specific to X86 that are not specific to a particular
+operating system are declared in @file{sys/platform/x86.h}.
+
+@deftypefun {const struct cpu_features *} __x86_get_cpu_features (unsigned int @var{max})
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Return a pointer to x86 CPU feature structure used by query macros for x86
+CPU features.  If @var{max} exceeds @code{COMMON_CPUID_INDEX_MAX} which
+is the limit of the CPUID leaves supported by @Theglibc{}, the function
+returns @code{NULL}, indicating that the queried processor feature is
+unsupported by @Theglibc{} run-time.
+@end deftypefun
+
+@deftypefn Macro int HAS_CPU_FEATURE (@var{name})
+This macro returns a nonzero value (true) if the processor has the feature
+@var{name}.
+@end deftypefn
+
+@deftypefn Macro int CPU_FEATURE_USABLE (@var{name})
+This macro returns a nonzero value (true) if the processor has the feature
+@var{name} and the feature is supported by the operating system.
+@end deftypefn
+
+The supported processor features are:
+
+@itemize @bullet
+
+@item
+@code{ACPI} -- Thermal Monitor and Software Controlled Clock Facilities.
+
+@item
+@code{ADX} -- ADX instruction extensions.
+
+@item
+@code{APIC} -- APIC On-Chip.
+
+@item
+@code{AES} -- The AES instruction extensions.
+
+@item
+@code{AMX_BF16} -- Tile computational operations on bfloat16 numbers.
+
+@item
+@code{AMX_INT8} -- Tile computational operations on 8-bit numbers.
+
+@item
+@code{AMX_TILE} -- Tile architecture.
+
+@item
+@code{ARCH_CAPABILITIES} -- IA32_ARCH_CAPABILITIES MSR.
+
+@item
+@code{AVX} -- The AVX instruction extensions.
+
+@item
+@code{AVX2} -- The AVX2 instruction extensions.
+
+@item
+@code{AVX512_4FMAPS} -- The AVX512_4FMAPS instruction extensions.
+
+@item
+@code{AVX512_4VNNIW} -- The AVX512_4VNNIW instruction extensions.
+
+@item
+@code{AVX512_BF16} -- The AVX512_BF16 instruction extensions.
+
+@item
+@code{AVX512_BITALG} -- The AVX512_BITALG instruction extensions.
+
+@item
+@code{AVX512_IFMA} -- The AVX512_IFMA instruction extensions.
+
+@item
+@code{AVX512_VBMI} -- The AVX512_VBMI instruction extensions.
+
+@item
+@code{AVX512_VBMI2} -- The AVX512_VBMI2 instruction extensions.
+
+@item
+@code{AVX512_VNNI} -- The AVX512_VNNI instruction extensions.
+
+@item
+@code{AVX512_VP2INTERSECT} -- The AVX512_VP2INTERSECT instruction
+extensions.
+
+@item
+@code{AVX512_VPOPCNTDQ} -- The AVX512_VPOPCNTDQ instruction extensions.
+
+@item
+@code{AVX512BW} -- The AVX512BW instruction extensions.
+
+@item
+@code{AVX512CD} -- The AVX512CD instruction extensions.
+
+@item
+@code{AVX512ER} -- The AVX512ER instruction extensions.
+
+@item
+@code{AVX512DQ} -- The AVX512DQ instruction extensions.
+
+@item
+@code{AVX512F} -- The AVX512F instruction extensions.
+
+@item
+@code{AVX512PF} -- The AVX512PF instruction extensions.
+
+@item
+@code{AVX512VL} -- The AVX512VL instruction extensions.
+
+@item
+@code{BMI1} -- BMI1 instructions.
+
+@item
+@code{BMI2} -- BMI2 instructions.
+
+@item
+@code{CLDEMOTE} -- CLDEMOTE instruction.
+
+@item
+@code{CLFLUSHOPT} -- CLFLUSHOPT instruction.
+
+@item
+@code{CLFSH} -- CLFLUSH instruction.
+
+@item
+@code{CLWB} -- CLWB instruction.
+
+@item
+@code{CMOV} -- Conditional Move instructions.
+
+@item
+@code{CMPXCHG16B} -- CMPXCHG16B instruction.
+
+@item
+@code{CNXT_ID} -- L1 Context ID.
+
+@item
+@code{CORE_CAPABILITIES} -- IA32_CORE_CAPABILITIES MSR.
+
+@item
+@code{CX8} -- CMPXCHG8B instruction.
+
+@item
+@code{DCA} -- Data prefetch from a memory mapped device.
+
+@item
+@code{DE} -- Debugging Extensions.
+
+@item
+@code{DEPR_FPU_CS_DS} -- Deprecates FPU CS and FPU DS values.
+
+@item
+@code{DS} -- Debug Store.
+
+@item
+@code{DS_CPL} -- CPL Qualified Debug Store.
+
+@item
+@code{DTES64} -- 64-bit DS Area.
+
+@item
+@code{EIST} -- Enhanced Intel SpeedStep technology.
+
+@item
+@code{ENQCMD} -- Enqueue Stores instructions.
+
+@item
+@code{ERMS} -- Enhanced REP MOVSB/STOSB.
+
+@item
+@code{F16C} -- 16-bit floating-point conversion instructions.
+
+@item
+@code{FMA} -- FMA extensions using YMM state.
+
+@item
+@code{FMA4} -- FMA4 instruction extensions.
+
+@item
+@code{FPU} -- X87 Floating Point Unit On-Chip.
+
+@item
+@code{FSGSBASE} -- RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE instructions.
+
+@item
+@code{FSRM} -- Fast Short REP MOV.
+
+@item
+@code{FXSR} -- FXSAVE and FXRSTOR instructions.
+
+@item
+@code{GFNI} -- GFNI instruction extensions.
+
+@item
+@code{HLE} -- HLE instruction extensions.
+
+@item
+@code{HTT} -- Max APIC IDs reserved field is Valid.
+
+@item
+@code{HYBRID} -- Hybrid processor.
+
+@item
+@code{IBRS_IBPB} -- Indirect branch restricted speculation (IBRS) and
+the indirect branch predictor barrier (IBPB).
+
+@item
+@code{IBT} -- Intel Indirect Branch Tracking instruction extensions.
+
+@item
+@code{INVARIANT_TSC} -- Invariant TSC.
+
+@item
+@code{INVPCID} -- INVPCID instruction.
+
+@item
+@code{L1D_FLUSH} -- IA32_FLUSH_CMD MSR.
+
+@item
+@code{LAHF64_SAHF64} -- LAHF/SAHF available in 64-bit mode.
+
+@item
+@code{LM} -- Long mode.
+
+@item
+@code{LWP} -- Lightweight profiling.
+
+@item
+@code{LZCNT} -- LZCNT instruction.
+
+@item
+@code{MCA} -- Machine Check Architecture.
+
+@item
+@code{MCE} -- Machine Check Exception.
+
+@item
+@code{MD_CLEAR} -- MD_CLEAR.
+
+@item
+@code{MMX} -- Intel MMX Technology.
+
+@item
+@code{MONITOR} --  MONITOR/MWAIT instructions.
+
+@item
+@code{MOVBE} -- MOVBE instruction.
+
+@item
+@code{MOVDIRI} -- MOVDIRI instruction.
+
+@item
+@code{MOVDIR64B} -- MOVDIR64B instruction.
+
+@item
+@code{MPX} -- Intel Memory Protection Extensions.
+
+@item
+@code{MSR} -- Model Specific Registers RDMSR and WRMSR instructions.
+
+@item
+@code{MTRR} -- Memory Type Range Registers.
+
+@item
+@code{NX} -- No-execute page protection.
+
+@item
+@code{OSPKE} -- OS has set CR4.PKE to enable protection keys.
+
+@item
+@code{OSXSAVE} -- The OS has set CR4.OSXSAVE[bit 18] to enable
+XSETBV/XGETBV instructions to access XCR0 and to support processor
+extended state management using XSAVE/XRSTOR.
+
+@item
+@code{PAE} -- Physical Address Extension.
+
+@item
+@code{PAGE1GB} -- 1-GByte page.
+
+@item
+@code{PAT} -- Page Attribute Table.
+
+@item
+@code{PBE} -- Pending Break Enable.
+
+@item
+@code{PCID} -- Process-context identifiers.
+
+@item
+@code{PCLMULQDQ} -- PCLMULQDQ instruction.
+
+@item
+@code{PCONFIG} -- PCONFIG instruction.
+
+@item
+@code{PDCM} -- Perfmon and Debug Capability.
+
+@item
+@code{PGE} -- Page Global Bit.
+
+@item
+@code{PKS} -- Protection keys for supervisor-mode pages.
+
+@item
+@code{PKU} -- Protection keys for user-mode pages.
+
+@item
+@code{POPCNT} -- POPCNT instruction.
+
+@item
+@code{PREFETCHW} -- PREFETCHW instruction.
+
+@item
+@code{PREFETCHWT1} -- PREFETCHWT1 instruction.
+
+@item
+@code{PSE} -- Page Size Extension.
+
+@item
+@code{PSE_36} -- 36-Bit Page Size Extension.
+
+@item
+@code{PSN} -- Processor Serial Number.
+
+@item
+@code{RDPID} -- RDPID instruction.
+
+@item
+@code{RDRAND} -- RDRAND instruction.
+
+@item
+@code{RDSEED} -- RDSEED instruction.
+
+@item
+@code{RDT_A} -- Intel Resource Director Technology (Intel RDT) Allocation
+capability.
+
+@item
+@code{RDT_M} -- Intel Resource Director Technology (Intel RDT) Monitoring
+capability.
+
+@item
+@code{RDTSCP} -- RDTSCP instruction.
+
+@item
+@code{RTM} -- RTM instruction extensions.
+
+@item
+@code{SDBG} -- IA32_DEBUG_INTERFACE MSR for silicon debug.
+
+@item
+@code{SEP} -- SYSENTER and SYSEXIT instructions.
+
+@item
+@code{SERIALIZE} -- SERIALIZE instruction.
+
+@item
+@code{SGX} -- Intel Software Guard Extensions.
+
+@item
+@code{SGX_LC} -- SGX Launch Configuration.
+
+@item
+@code{SHA} -- SHA instruction extensions.
+
+@item
+@code{SHSTK} -- Intel Shadow Stack instruction extensions.
+
+@item
+@code{SMAP} -- Supervisor-Mode Access Prevention.
+
+@item
+@code{SMEP} -- Supervisor-Mode Execution Prevention.
+
+@item
+@code{SMX} -- Safer Mode Extensions.
+
+@item
+@code{SS} -- Self Snoop.
+
+@item
+@code{SSBD} -- Speculative Store Bypass Disable (SSBD).
+
+@item
+@code{SSE} -- Streaming SIMD Extensions.
+
+@item
+@code{SSE2} -- Streaming SIMD Extensions 2.
+
+@item
+@code{SSE3} -- Streaming SIMD Extensions 3.
+
+@item
+@code{SSE4_1} -- Streaming SIMD Extensions 4.1.
+
+@item
+@code{SSE4_2} -- Streaming SIMD Extensions 4.2.
+
+@item
+@code{SSE4A} -- SSE4A instruction extensions.
+
+@item
+@code{SSSE3} -- Supplemental Streaming SIMD Extensions 3.
+
+@item
+@code{STIBP} -- Single thread indirect branch predictors (STIBP).
+
+@item
+@code{SVM} -- Secure Virtual Machine.
+
+@item
+@code{SYSCALL_SYSRET} -- SYSCALL/SYSRET instructions.
+
+@item
+@code{TBM} -- Trailing bit manipulation instructions.
+
+@item
+@code{TM} -- Thermal Monitor.
+
+@item
+@code{TM2} -- Thermal Monitor 2.
+
+@item
+@code{TRACE} -- Intel Processor Trace.
+
+@item
+@code{TSC} -- Time Stamp Counter.  RDTSC instruction.
+
+@item
+@code{TSC_ADJUST} -- IA32_TSC_ADJUST MSR.
+
+@item
+@code{TSC_DEADLINE} -- Local APIC timer supports one-shot operation
+using a TSC deadline value.
+
+@item
+@code{TSXLDTRK} -- TSXLDTRK instructions.
+
+@item
+@code{UMIP} -- User-mode instruction prevention.
+
+@item
+@code{VAES} -- VAES instruction extensions.
+
+@item
+@code{VME} -- Virtual 8086 Mode Enhancements.
+
+@item
+@code{VMX} -- Virtual Machine Extensions.
+
+@item
+@code{VPCLMULQDQ} -- VPCLMULQDQ instruction.
+
+@item
+@code{WAITPKG} -- WAITPKG instruction extensions.
+
+@item
+@code{WBNOINVD} -- WBINVD/WBNOINVD instructions.
+
+@item
+@code{X2APIC} -- x2APIC.
+
+@item
+@code{XFD} -- Extended Feature Disable (XFD).
+
+@item
+@code{XGETBV_ECX_1} -- XGETBV with ECX = 1.
+
+@item
+@code{XOP} -- XOP instruction extensions.
+
+@item
+@code{XSAVE} -- The XSAVE/XRSTOR processor extended states feature, the
+XSETBV/XGETBV instructions, and XCR0.
+
+@item
+@code{XSAVEC} -- XSAVEC instruction.
+
+@item
+@code{XSAVEOPT} -- XSAVEOPT instruction.
+
+@item
+@code{XSAVES} -- XSAVES/XRSTORS instructions.
+
+@item
+@code{XTPRUPDCTRL} -- xTPR Update Control.
+
+@end itemize
+
+You could query if a processor supports @code{AVX} with:
+
+@smallexample
+#include <sys/platform/x86.h>
+
+int
+support_avx (void)
+@{
+  return HAS_CPU_FEATURE (AVX);
+@}
+@end smallexample
+
+and if @code{AVX} is usable with:
+
+@smallexample
+#include <sys/platform/x86.h>
+
+int
+usable_avx (void)
+@{
+  return CPU_FEATURE_USABLE (AVX);
+@}
+@end smallexample
diff --git a/sysdeps/i386/i686/multiarch/Makefile b/sysdeps/i386/i686/multiarch/Makefile
index bf75a9947f..c4897922d7 100644
--- a/sysdeps/i386/i686/multiarch/Makefile
+++ b/sysdeps/i386/i686/multiarch/Makefile
@@ -1,7 +1,3 @@ 
-ifeq ($(subdir),csu)
-tests += test-multiarch
-endif
-
 ifeq ($(subdir),string)
 gen-as-const-headers += locale-defines.sym
 sysdep_routines += bzero-sse2 memset-sse2 memcpy-ssse3 mempcpy-ssse3 \
diff --git a/sysdeps/i386/i686/multiarch/test-multiarch.c b/sysdeps/i386/i686/multiarch/test-multiarch.c
deleted file mode 100644
index 593cfec273..0000000000
--- a/sysdeps/i386/i686/multiarch/test-multiarch.c
+++ /dev/null
@@ -1 +0,0 @@ 
-#include <sysdeps/x86_64/multiarch/test-multiarch.c>
diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
index 0478e22071..04655651b0 100644
--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
+++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
@@ -3,3 +3,4 @@  GLIBC_2.1 __libc_stack_end D 0x4
 GLIBC_2.1 _dl_mcount F
 GLIBC_2.3 ___tls_get_addr F
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.33 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
index d3cdf7611e..e632c6198e 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
@@ -2,3 +2,4 @@  GLIBC_2.2.5 __libc_stack_end D 0x8
 GLIBC_2.2.5 _dl_mcount F
 GLIBC_2.2.5 _r_debug D 0x28
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.33 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
index c70bccf782..9d9d0befde 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
@@ -2,3 +2,4 @@  GLIBC_2.16 __libc_stack_end D 0x4
 GLIBC_2.16 __tls_get_addr F
 GLIBC_2.16 _dl_mcount F
 GLIBC_2.16 _r_debug D 0x14
+GLIBC_2.33 __x86_get_cpu_features F
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index a6736aef25..c369faf00d 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -4,8 +4,10 @@  endif
 
 ifeq ($(subdir),elf)
 sysdep-dl-routines += dl-get-cpu-features
+sysdep_headers += sys/platform/x86.h
 
-tests += tst-get-cpu-features tst-get-cpu-features-static
+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
 endif
 
diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions
index e02923708e..59db578a9d 100644
--- a/sysdeps/x86/Versions
+++ b/sysdeps/x86/Versions
@@ -1,5 +1,5 @@ 
 ld {
-  GLIBC_PRIVATE {
-    __get_cpu_features;
+  GLIBC_2.33 {
+    __x86_get_cpu_features;
   }
 }
diff --git a/sysdeps/x86/dl-get-cpu-features.c b/sysdeps/x86/dl-get-cpu-features.c
index 9d61cd56be..5f9e46b0c6 100644
--- a/sysdeps/x86/dl-get-cpu-features.c
+++ b/sysdeps/x86/dl-get-cpu-features.c
@@ -18,10 +18,12 @@ 
 
 #include <ldsodefs.h>
 
-#undef __get_cpu_features
+#undef __x86_get_cpu_features
 
 const struct cpu_features *
-__get_cpu_features (void)
+__x86_get_cpu_features (unsigned int max)
 {
+  if (max > COMMON_CPUID_INDEX_MAX)
+    return NULL;
   return &GLRO(dl_x86_cpu_features);
 }
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
new file mode 100644
index 0000000000..dcf29b6fe8
--- /dev/null
+++ b/sysdeps/x86/include/cpu-features.h
@@ -0,0 +1,183 @@ 
+/* Data structure for x86 CPU features.
+   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/>.  */
+
+#ifndef	_PRIVATE_CPU_FEATURES_H
+#define	_PRIVATE_CPU_FEATURES_H	1
+
+#ifdef _CPU_FEATURES_H
+# error this should be impossible
+#endif
+
+#ifndef _ISOMAC
+/* Get most of the contents from the public header, but we define a
+   different `struct cpu_features' type for private use.  */
+# define cpu_features		cpu_features_public
+# define __x86_get_cpu_features	__x86_get_cpu_features_public
+#endif
+
+#include <sysdeps/x86/sys/platform/x86.h>
+
+#ifndef _ISOMAC
+
+# undef	cpu_features
+# undef __x86_get_cpu_features
+# define __get_cpu_features()	__x86_get_cpu_features (0)
+
+enum
+{
+  /* The integer bit array index for the first set of preferred feature
+     bits.  */
+  PREFERRED_FEATURE_INDEX_1 = 0,
+  /* The current maximum size of the feature integer bit array.  */
+  PREFERRED_FEATURE_INDEX_MAX
+};
+
+/* Only used directly in cpu-features.c.  */
+# define CPU_FEATURE_SET(ptr, name) \
+  ptr->features[index_cpu_##name].usable.reg_##name |= bit_cpu_##name;
+# define CPU_FEATURE_UNSET(ptr, name) \
+  ptr->features[index_cpu_##name].usable.reg_##name &= ~bit_cpu_##name;
+# define CPU_FEATURE_SET_USABLE(ptr, name) \
+  ptr->features[index_cpu_##name].usable.reg_##name \
+     |= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name;
+# define CPU_FEATURE_PREFERRED_P(ptr, name) \
+  ((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0)
+# define CPU_FEATURE_CPU_P(ptr, name) \
+  CPU_FEATURE_CHECK_P (ptr, name, cpuid)
+
+/* HAS_CPU_FEATURE evaluates to true if CPU supports the feature.  */
+# undef HAS_CPU_FEATURE
+# define HAS_CPU_FEATURE(name) \
+  CPU_FEATURE_CPU_P (__x86_get_cpu_features (0), name)
+/* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
+# undef CPU_FEATURE_USABLE
+# define CPU_FEATURE_USABLE(name) \
+  CPU_FEATURE_USABLE_P (__x86_get_cpu_features (0), name)
+/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at
+   runtime.  */
+# define CPU_FEATURE_PREFERRED(name) \
+  CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name)
+
+# define CPU_FEATURES_CPU_P(ptr, name) \
+  CPU_FEATURE_CPU_P (ptr, name)
+# define CPU_FEATURES_ARCH_P(ptr, name) \
+  CPU_FEATURE_PREFERRED_P (ptr, name)
+# define HAS_ARCH_FEATURE(name) \
+  CPU_FEATURE_PREFERRED (name)
+
+/* PREFERRED_FEATURE_INDEX_1.  */
+# define bit_arch_I586				(1u << 0)
+# define bit_arch_I686				(1u << 1)
+# define bit_arch_Fast_Rep_String		(1u << 2)
+# define bit_arch_Fast_Copy_Backward		(1u << 3)
+# define bit_arch_Fast_Unaligned_Load		(1u << 4)
+# define bit_arch_Fast_Unaligned_Copy		(1u << 5)
+# define bit_arch_Slow_BSF			(1u << 6)
+# define bit_arch_Slow_SSE4_2			(1u << 7)
+# define bit_arch_AVX_Fast_Unaligned_Load	(1u << 8)
+# define bit_arch_Prefer_MAP_32BIT_EXEC		(1u << 9)
+# define bit_arch_Prefer_PMINUB_for_stringop	(1u << 10)
+# define bit_arch_Prefer_No_VZEROUPPER		(1u << 11)
+# define bit_arch_Prefer_ERMS			(1u << 12)
+# define bit_arch_Prefer_FSRM			(1u << 13)
+# define bit_arch_Prefer_No_AVX512		(1u << 14)
+# define bit_arch_MathVec_Prefer_No_AVX512	(1u << 15)
+
+# define index_arch_Fast_Rep_String		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Copy_Backward		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_BSF			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Load		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_PMINUB_for_stringop 	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Copy		PREFERRED_FEATURE_INDEX_1
+# define index_arch_I586			PREFERRED_FEATURE_INDEX_1
+# define index_arch_I686			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_SSE4_2			PREFERRED_FEATURE_INDEX_1
+# define index_arch_AVX_Fast_Unaligned_Load	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_MAP_32BIT_EXEC	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_VZEROUPPER	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_ERMS			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_AVX512		PREFERRED_FEATURE_INDEX_1
+# define index_arch_MathVec_Prefer_No_AVX512	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_FSRM			PREFERRED_FEATURE_INDEX_1
+
+/* XCR0 Feature flags.  */
+# define bit_XMM_state		(1u << 1)
+# define bit_YMM_state		(1u << 2)
+# define bit_Opmask_state	(1u << 5)
+# define bit_ZMM0_15_state	(1u << 6)
+# define bit_ZMM16_31_state	(1u << 7)
+# define bit_XTILECFG_state	(1u << 17)
+# define bit_XTILEDATA_state	(1u << 18)
+
+struct cpu_features
+{
+  struct cpu_features_basic basic;
+  struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
+  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
+  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
+     int so that we use
+
+	sub xsave_state_size_offset(%rip) %RSP_LP
+
+     in _dl_runtime_resolve.  */
+  unsigned long int xsave_state_size;
+  /* The full state size for XSAVE when XSAVEC is disabled by
+
+     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC
+   */
+  unsigned int xsave_state_full_size;
+  /* Data cache size for use in memory and string routines, typically
+     L1 size.  */
+  unsigned long int data_cache_size;
+  /* Shared cache size for use in memory and string routines, typically
+     L2 or L3 size.  */
+  unsigned long int shared_cache_size;
+  /* Threshold to use non temporal store.  */
+  unsigned long int non_temporal_threshold;
+  /* Threshold to use "rep movsb".  */
+  unsigned long int rep_movsb_threshold;
+  /* Threshold to use "rep stosb".  */
+  unsigned long int rep_stosb_threshold;
+};
+
+# if defined (_LIBC) && !IS_IN (nonlib)
+/* Unused for x86.  */
+#  define INIT_ARCH()
+#  define __x86_get_cpu_features(max) (&GLRO(dl_x86_cpu_features))
+# endif
+
+# ifdef __x86_64__
+#  define HAS_CPUID 1
+# elif (defined __i586__ || defined __pentium__	\
+	|| defined __geode__ || defined __k6__)
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# elif defined __i486__
+#  define HAS_CPUID 0
+#  define HAS_I586 HAS_ARCH_FEATURE (I586)
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# else
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 1
+# endif
+
+#endif /* !_ISOMAC */
+
+#endif /* include/cpu-features.h */
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/sys/platform/x86.h
similarity index 81%
rename from sysdeps/x86/cpu-features.h
rename to sysdeps/x86/sys/platform/x86.h
index 78fcec251e..bf3727ebc0 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/sys/platform/x86.h
@@ -1,4 +1,5 @@ 
-/* This file is part of the GNU C Library.
+/* Data structure for x86 CPU features.
+   This file is part of the GNU C Library.
    Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,17 +16,8 @@ 
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#ifndef cpu_features_h
-#define cpu_features_h
-
-enum
-{
-  /* The integer bit array index for the first set of preferred feature
-     bits.  */
-  PREFERRED_FEATURE_INDEX_1 = 0,
-  /* The current maximum size of the feature integer bit array.  */
-  PREFERRED_FEATURE_INDEX_MAX
-};
+#ifndef _SYS_PLATFORM_X86_H
+#define _SYS_PLATFORM_X86_H
 
 enum
 {
@@ -76,73 +68,32 @@  struct cpu_features
 {
   struct cpu_features_basic basic;
   struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
-  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
-  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
-     int so that we use
-
-	sub xsave_state_size_offset(%rip) %RSP_LP
-
-     in _dl_runtime_resolve.  */
-  unsigned long int xsave_state_size;
-  /* The full state size for XSAVE when XSAVEC is disabled by
-
-     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC
-   */
-  unsigned int xsave_state_full_size;
-  /* Data cache size for use in memory and string routines, typically
-     L1 size.  */
-  unsigned long int data_cache_size;
-  /* Shared cache size for use in memory and string routines, typically
-     L2 or L3 size.  */
-  unsigned long int shared_cache_size;
-  /* Threshold to use non temporal store.  */
-  unsigned long int non_temporal_threshold;
-  /* Threshold to use "rep movsb".  */
-  unsigned long int rep_movsb_threshold;
-  /* Threshold to use "rep stosb".  */
-  unsigned long int rep_stosb_threshold;
 };
 
-/* Used from outside of glibc to get access to the CPU features
-   structure.  */
-extern const struct cpu_features *__get_cpu_features (void)
+/* Get a pointer to the CPU features structure.  */
+extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
      __attribute__ ((const));
 
-/* Only used directly in cpu-features.c.  */
 #define CPU_FEATURE_CHECK_P(ptr, name, check) \
   ((ptr->features[index_cpu_##name].check.reg_##name \
     & bit_cpu_##name) != 0)
-#define CPU_FEATURE_SET(ptr, name) \
-  ptr->features[index_cpu_##name].usable.reg_##name |= bit_cpu_##name;
-#define CPU_FEATURE_UNSET(ptr, name) \
-  ptr->features[index_cpu_##name].usable.reg_##name &= ~bit_cpu_##name;
-#define CPU_FEATURE_SET_USABLE(ptr, name) \
-  ptr->features[index_cpu_##name].usable.reg_##name \
-     |= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name;
-#define CPU_FEATURE_PREFERRED_P(ptr, name) \
-  ((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0)
 #define CPU_FEATURE_CPU_P(ptr, name) \
   CPU_FEATURE_CHECK_P (ptr, name, cpuid)
 #define CPU_FEATURE_USABLE_P(ptr, name) \
   CPU_FEATURE_CHECK_P (ptr, name, usable)
 
 /* HAS_CPU_FEATURE evaluates to true if CPU supports the feature.  */
-#define HAS_CPU_FEATURE(name) \
-  CPU_FEATURE_CPU_P (__get_cpu_features (), name)
+#define HAS_CPU_FEATURE(name)					\
+  (__extension__						\
+   ({ const struct cpu_features *__ptr =			\
+	__x86_get_cpu_features (COMMON_CPUID_INDEX_MAX);	\
+      __ptr && CPU_FEATURE_CPU_P (__ptr, name); }))
 /* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
-#define CPU_FEATURE_USABLE(name) \
-  CPU_FEATURE_USABLE_P (__get_cpu_features (), name)
-/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at
-   runtime.  */
-#define CPU_FEATURE_PREFERRED(name) \
-  CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name)
-
-#define CPU_FEATURES_CPU_P(ptr, name) \
-  CPU_FEATURE_CPU_P (ptr, name)
-#define CPU_FEATURES_ARCH_P(ptr, name) \
-  CPU_FEATURE_PREFERRED_P (ptr, name)
-#define HAS_ARCH_FEATURE(name) \
-  CPU_FEATURE_PREFERRED (name)
+#define CPU_FEATURE_USABLE(name)				\
+  (__extension__						\
+   ({ const struct cpu_features *__ptr =			\
+	__x86_get_cpu_features (COMMON_CPUID_INDEX_MAX);	\
+      __ptr && CPU_FEATURE_USABLE_P (__ptr, name); }))
 
 /* CPU features.  */
 
@@ -787,71 +738,4 @@  extern const struct cpu_features *__get_cpu_features (void)
 /* EAX.  */
 #define reg_AVX512_BF16		eax
 
-/* FEATURE_INDEX_2.  */
-#define bit_arch_I586				(1u << 0)
-#define bit_arch_I686				(1u << 1)
-#define bit_arch_Fast_Rep_String		(1u << 2)
-#define bit_arch_Fast_Copy_Backward		(1u << 3)
-#define bit_arch_Fast_Unaligned_Load		(1u << 4)
-#define bit_arch_Fast_Unaligned_Copy		(1u << 5)
-#define bit_arch_Slow_BSF			(1u << 6)
-#define bit_arch_Slow_SSE4_2			(1u << 7)
-#define bit_arch_AVX_Fast_Unaligned_Load	(1u << 8)
-#define bit_arch_Prefer_MAP_32BIT_EXEC		(1u << 9)
-#define bit_arch_Prefer_PMINUB_for_stringop	(1u << 10)
-#define bit_arch_Prefer_No_VZEROUPPER		(1u << 11)
-#define bit_arch_Prefer_ERMS			(1u << 12)
-#define bit_arch_Prefer_FSRM			(1u << 13)
-#define bit_arch_Prefer_No_AVX512		(1u << 14)
-#define bit_arch_MathVec_Prefer_No_AVX512	(1u << 15)
-
-#define index_arch_Fast_Rep_String		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Copy_Backward		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_BSF			PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Load		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_PMINUB_for_stringop 	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Copy		PREFERRED_FEATURE_INDEX_1
-#define index_arch_I586				PREFERRED_FEATURE_INDEX_1
-#define index_arch_I686				PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_SSE4_2			PREFERRED_FEATURE_INDEX_1
-#define index_arch_AVX_Fast_Unaligned_Load	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_MAP_32BIT_EXEC	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_VZEROUPPER		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_ERMS			PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_AVX512		PREFERRED_FEATURE_INDEX_1
-#define index_arch_MathVec_Prefer_No_AVX512	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_FSRM			PREFERRED_FEATURE_INDEX_1
-
-/* XCR0 Feature flags.  */
-#define bit_XMM_state		(1u << 1)
-#define bit_YMM_state		(1u << 2)
-#define bit_Opmask_state	(1u << 5)
-#define bit_ZMM0_15_state	(1u << 6)
-#define bit_ZMM16_31_state	(1u << 7)
-#define bit_XTILECFG_state	(1u << 17)
-#define bit_XTILEDATA_state	(1u << 18)
-
-# if defined (_LIBC) && !IS_IN (nonlib)
-/* Unused for x86.  */
-#  define INIT_ARCH()
-#  define __get_cpu_features()	(&GLRO(dl_x86_cpu_features))
-# endif
-
-#ifdef __x86_64__
-# define HAS_CPUID 1
-#elif (defined __i586__ || defined __pentium__	\
-       || defined __geode__ || defined __k6__)
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#elif defined __i486__
-# define HAS_CPUID 0
-# define HAS_I586 HAS_ARCH_FEATURE (I586)
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#else
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 1
-#endif
-
-#endif  /* cpu_features_h */
+#endif  /* _SYS_PLATFORM_X86_H */
diff --git a/sysdeps/x86/tst-cpu-features-cpuinfo.c b/sysdeps/x86/tst-cpu-features-cpuinfo.c
new file mode 100644
index 0000000000..96277284d1
--- /dev/null
+++ b/sysdeps/x86/tst-cpu-features-cpuinfo.c
@@ -0,0 +1,250 @@ 
+/* Test CPU feature data against /proc/cpuinfo.
+   This file is part of the GNU C Library.
+   Copyright (C) 2012-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>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char *cpu_flags;
+
+/* Search for flags in /proc/cpuinfo and store line
+   in cpu_flags.  */
+void
+get_cpuinfo (void)
+{
+  FILE *f;
+  char *line = NULL;
+  size_t len = 0;
+  ssize_t read;
+
+  f = fopen ("/proc/cpuinfo", "r");
+  if (f == NULL)
+    {
+      printf ("cannot open /proc/cpuinfo\n");
+      exit (1);
+    }
+
+  while ((read = getline (&line, &len, f)) != -1)
+    {
+      if (strncmp (line, "flags", 5) == 0)
+       {
+         cpu_flags = strdup (line);
+         break;
+       }
+    }
+  fclose (f);
+  free (line);
+}
+
+int
+check_proc (const char *proc_name, int flag, int usable, const char *name)
+{
+  int found = 0;
+
+  printf ("Checking %s:\n", name);
+  if (!usable)
+    {
+      printf ("  %s: insufficient usable info, skipped\n", name);
+      return 0;
+    }
+  printf ("  %s: %d\n", name, flag);
+  if (strstr (cpu_flags, proc_name) != NULL)
+    found = 1;
+  printf ("  cpuinfo (%s): %d\n", proc_name, found);
+
+  if (found != flag)
+    printf (" *** failure ***\n");
+
+  return (found != flag);
+}
+
+#define CHECK_PROC(str, name) \
+  check_proc (#str, HAS_CPU_FEATURE (name), CPU_FEATURE_USABLE (name), \
+	      "HAS_CPU_FEATURE (" #name ")");
+
+static int
+do_test (int argc, char **argv)
+{
+  int fails = 0;
+
+  get_cpuinfo ();
+  fails += CHECK_PROC (acpi, ACPI);
+  fails += CHECK_PROC (adx, ADX);
+  fails += CHECK_PROC (apic, APIC);
+  fails += CHECK_PROC (aes, AES);
+  fails += CHECK_PROC (amx_bf16, AMX_BF16);
+  fails += CHECK_PROC (amx_int8, AMX_INT8);
+  fails += CHECK_PROC (amx_tile, AMX_TILE);
+  fails += CHECK_PROC (arch_capabilities, ARCH_CAPABILITIES);
+  fails += CHECK_PROC (avx, AVX);
+  fails += CHECK_PROC (avx2, AVX2);
+  fails += CHECK_PROC (avx512_4fmaps, AVX512_4FMAPS);
+  fails += CHECK_PROC (avx512_4vnniw, AVX512_4VNNIW);
+  fails += CHECK_PROC (avx512_bf16, AVX512_BF16);
+  fails += CHECK_PROC (avx512_bitalg, AVX512_BITALG);
+  fails += CHECK_PROC (avx512ifma, AVX512_IFMA);
+  fails += CHECK_PROC (avx512_vbmi, AVX512_VBMI);
+  fails += CHECK_PROC (avx512_vbmi2, AVX512_VBMI2);
+  fails += CHECK_PROC (avx512_vnni, AVX512_VNNI);
+  fails += CHECK_PROC (avx512_vp2intersect, AVX512_VP2INTERSECT);
+  fails += CHECK_PROC (avx512_vpopcntdq, AVX512_VPOPCNTDQ);
+  fails += CHECK_PROC (avx512bw, AVX512BW);
+  fails += CHECK_PROC (avx512cd, AVX512CD);
+  fails += CHECK_PROC (avx512er, AVX512ER);
+  fails += CHECK_PROC (avx512dq, AVX512DQ);
+  fails += CHECK_PROC (avx512f, AVX512F);
+  fails += CHECK_PROC (avx512pf, AVX512PF);
+  fails += CHECK_PROC (avx512vl, AVX512VL);
+  fails += CHECK_PROC (bmi1, BMI1);
+  fails += CHECK_PROC (bmi2, BMI2);
+  fails += CHECK_PROC (cldemote, CLDEMOTE);
+  fails += CHECK_PROC (clflushopt, CLFLUSHOPT);
+  fails += CHECK_PROC (clflush, CLFSH);
+  fails += CHECK_PROC (clwb, CLWB);
+  fails += CHECK_PROC (cmov, CMOV);
+  fails += CHECK_PROC (cx16, CMPXCHG16B);
+  fails += CHECK_PROC (cnxt_id, CNXT_ID);
+  fails += CHECK_PROC (core_capabilities, CORE_CAPABILITIES);
+  fails += CHECK_PROC (cx8, CX8);
+  fails += CHECK_PROC (dca, DCA);
+  fails += CHECK_PROC (de, DE);
+  fails += CHECK_PROC (zero_fcs_fds, DEPR_FPU_CS_DS);
+  fails += CHECK_PROC (ds, DS);
+  fails += CHECK_PROC (ds_cpl, DS_CPL);
+  fails += CHECK_PROC (dtes64, DTES64);
+  fails += CHECK_PROC (est, EIST);
+  fails += CHECK_PROC (enqcmd, ENQCMD);
+  fails += CHECK_PROC (erms, ERMS);
+  fails += CHECK_PROC (f16c, F16C);
+  fails += CHECK_PROC (fma, FMA);
+  fails += CHECK_PROC (fma4, FMA4);
+  fails += CHECK_PROC (fpu, FPU);
+  fails += CHECK_PROC (fsgsbase, FSGSBASE);
+  fails += CHECK_PROC (fsrm, FSRM);
+  fails += CHECK_PROC (fxsr, FXSR);
+  fails += CHECK_PROC (gfni, GFNI);
+  fails += CHECK_PROC (hle, HLE);
+  fails += CHECK_PROC (ht, HTT);
+  fails += CHECK_PROC (hybrid, HYBRID);
+  fails += CHECK_PROC (ibrs, IBRS_IBPB);
+  fails += CHECK_PROC (ibt, IBT);
+  fails += CHECK_PROC (invariant_tsc, INVARIANT_TSC);
+  fails += CHECK_PROC (invpcid, INVPCID);
+  fails += CHECK_PROC (flush_l1d, L1D_FLUSH);
+  fails += CHECK_PROC (lahf_lm, LAHF64_SAHF64);
+  fails += CHECK_PROC (lm, LM);
+  fails += CHECK_PROC (lwp, LWP);
+  fails += CHECK_PROC (abm, LZCNT);
+  fails += CHECK_PROC (mca, MCA);
+  fails += CHECK_PROC (mce, MCE);
+  fails += CHECK_PROC (md_clear, MD_CLEAR);
+  fails += CHECK_PROC (mmx, MMX);
+  fails += CHECK_PROC (monitor, MONITOR);
+  fails += CHECK_PROC (movbe, MOVBE);
+  fails += CHECK_PROC (movdiri, MOVDIRI);
+  fails += CHECK_PROC (movdir64b, MOVDIR64B);
+  fails += CHECK_PROC (mpx, MPX);
+  fails += CHECK_PROC (msr, MSR);
+  fails += CHECK_PROC (mtrr, MTRR);
+  fails += CHECK_PROC (nx, NX);
+  fails += CHECK_PROC (ospke, OSPKE);
+#if 0
+  /* NB: /proc/cpuinfo doesn't report this feature.  */
+  fails += CHECK_PROC (osxsave, OSXSAVE);
+#endif
+  fails += CHECK_PROC (pae, PAE);
+  fails += CHECK_PROC (pdpe1gb, PAGE1GB);
+  fails += CHECK_PROC (pat, PAT);
+  fails += CHECK_PROC (pbe, PBE);
+  fails += CHECK_PROC (pcid, PCID);
+  fails += CHECK_PROC (pclmulqdq, PCLMULQDQ);
+  fails += CHECK_PROC (pconfig, PCONFIG);
+  fails += CHECK_PROC (pdcm, PDCM);
+  fails += CHECK_PROC (pge, PGE);
+  fails += CHECK_PROC (pks, PKS);
+  fails += CHECK_PROC (pku, PKU);
+  fails += CHECK_PROC (popcnt, POPCNT);
+  fails += CHECK_PROC (3dnowprefetch, PREFETCHW);
+  fails += CHECK_PROC (prefetchwt1, PREFETCHWT1);
+  fails += CHECK_PROC (pse, PSE);
+  fails += CHECK_PROC (pse36, PSE_36);
+  fails += CHECK_PROC (psn, PSN);
+  fails += CHECK_PROC (rdpid, RDPID);
+  fails += CHECK_PROC (rdrand, RDRAND);
+  fails += CHECK_PROC (rdseed, RDSEED);
+  fails += CHECK_PROC (rdt_a, RDT_A);
+  fails += CHECK_PROC (cqm, RDT_M);
+  fails += CHECK_PROC (rdtscp, RDTSCP);
+  fails += CHECK_PROC (rtm, RTM);
+  fails += CHECK_PROC (sdbg, SDBG);
+  fails += CHECK_PROC (sep, SEP);
+  fails += CHECK_PROC (serialize, SERIALIZE);
+  fails += CHECK_PROC (sgx, SGX);
+  fails += CHECK_PROC (sgx_lc, SGX_LC);
+  fails += CHECK_PROC (sha_ni, SHA);
+  fails += CHECK_PROC (shstk, SHSTK);
+  fails += CHECK_PROC (smap, SMAP);
+  fails += CHECK_PROC (smep, SMEP);
+  fails += CHECK_PROC (smx, SMX);
+  fails += CHECK_PROC (ss, SS);
+  fails += CHECK_PROC (ssbd, SSBD);
+  fails += CHECK_PROC (sse, SSE);
+  fails += CHECK_PROC (sse2, SSE2);
+  fails += CHECK_PROC (sse3, SSE3);
+  fails += CHECK_PROC (sse4_1, SSE4_1);
+  fails += CHECK_PROC (sse4_2, SSE4_2);
+  fails += CHECK_PROC (sse4a, SSE4A);
+  fails += CHECK_PROC (ssse3, SSSE3);
+  fails += CHECK_PROC (stibp, STIBP);
+  fails += CHECK_PROC (svm, SVM);
+#ifdef __x86_64__
+  /* NB: SYSCALL_SYSRET is 64-bit only.  */
+  fails += CHECK_PROC (syscall, SYSCALL_SYSRET);
+#endif
+  fails += CHECK_PROC (tbm, TBM);
+  fails += CHECK_PROC (tm, TM);
+  fails += CHECK_PROC (tm2, TM2);
+  fails += CHECK_PROC (intel_pt, TRACE);
+  fails += CHECK_PROC (tsc, TSC);
+  fails += CHECK_PROC (tsc_adjust, TSC_ADJUST);
+  fails += CHECK_PROC (tsc_deadline, TSC_DEADLINE);
+  fails += CHECK_PROC (tsxldtrk, TSXLDTRK);
+  fails += CHECK_PROC (umip, UMIP);
+  fails += CHECK_PROC (vaes, VAES);
+  fails += CHECK_PROC (vme, VME);
+  fails += CHECK_PROC (vmx, VMX);
+  fails += CHECK_PROC (vpclmulqdq, VPCLMULQDQ);
+  fails += CHECK_PROC (waitpkg, WAITPKG);
+  fails += CHECK_PROC (wbnoinvd, WBNOINVD);
+  fails += CHECK_PROC (x2apic, X2APIC);
+  fails += CHECK_PROC (xfd, XFD);
+  fails += CHECK_PROC (xgetbv1, XGETBV_ECX_1);
+  fails += CHECK_PROC (xop, XOP);
+  fails += CHECK_PROC (xsave, XSAVE);
+  fails += CHECK_PROC (xsavec, XSAVEC);
+  fails += CHECK_PROC (xsaveopt, XSAVEOPT);
+  fails += CHECK_PROC (xsaves, XSAVES);
+  fails += CHECK_PROC (xtpr, XTPRUPDCTRL);
+
+  printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails);
+
+  return (fails != 0);
+}
+
+#include "../../../test-skeleton.c"
diff --git a/sysdeps/x86/tst-cpu-features-supports.c b/sysdeps/x86/tst-cpu-features-supports.c
new file mode 100644
index 0000000000..bf881b531f
--- /dev/null
+++ b/sysdeps/x86/tst-cpu-features-supports.c
@@ -0,0 +1,192 @@ 
+/* Test CPU feature data against __builtin_cpu_supports.
+   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>
+#include <stdio.h>
+
+int
+check_supports (int supports, int usable, const char *supports_name,
+		const char *name)
+{
+  printf ("Checking %s:\n", name);
+  printf ("  %s: %d\n", name, usable);
+  printf ("  __builtin_cpu_supports (%s): %d\n",
+	  supports_name, supports);
+
+  if ((supports != 0) != (usable != 0))
+    {
+      printf (" *** failure ***\n");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define CHECK_SUPPORTS(str, name) \
+  check_supports (__builtin_cpu_supports (#str), \
+		  CPU_FEATURE_USABLE (name), \
+		  #str, "HAS_CPU_FEATURE (" #name ")");
+
+static int
+do_test (int argc, char **argv)
+{
+  int fails = 0;
+
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (adx, ADX);
+#endif
+#if __GNUC_PREREQ (6, 0)
+  fails += CHECK_SUPPORTS (aes, AES);
+#endif
+#if __GNUC_PREREQ (11, 1)
+  fails += CHECK_SUPPORTS (amx_bf16, AMX_BF16);
+  fails += CHECK_SUPPORTS (amx_int8, AMX_INT8);
+  fails += CHECK_SUPPORTS (amx_tile, AMX_TILE);
+#endif
+  fails += CHECK_SUPPORTS (avx, AVX);
+  fails += CHECK_SUPPORTS (avx2, AVX2);
+#if __GNUC_PREREQ (7, 0)
+  fails += CHECK_SUPPORTS (avx5124fmaps, AVX512_4FMAPS);
+  fails += CHECK_SUPPORTS (avx5124vnniw, AVX512_4VNNIW);
+#endif
+#if __GNUC_PREREQ (10, 0)
+  fails += CHECK_SUPPORTS (avx512bf16, AVX512_BF16);
+#endif
+#if __GNUC_PREREQ (8, 0)
+  fails += CHECK_SUPPORTS (avx512bitalg, AVX512_BITALG);
+#endif
+#if __GNUC_PREREQ (6, 0)
+  fails += CHECK_SUPPORTS (avx512ifma, AVX512_IFMA);
+  fails += CHECK_SUPPORTS (avx512vbmi, AVX512_VBMI);
+#endif
+#if __GNUC_PREREQ (8, 0)
+  fails += CHECK_SUPPORTS (avx512vbmi2, AVX512_VBMI2);
+  fails += CHECK_SUPPORTS (avx512vnni, AVX512_VNNI);
+#endif
+#if __GNUC_PREREQ (10, 0)
+  fails += CHECK_SUPPORTS (avx512vp2intersect, AVX512_VP2INTERSECT);
+#endif
+#if __GNUC_PREREQ (7, 0)
+  fails += CHECK_SUPPORTS (avx512vpopcntdq, AVX512_VPOPCNTDQ);
+#endif
+#if __GNUC_PREREQ (6, 0)
+  fails += CHECK_SUPPORTS (avx512bw, AVX512BW);
+  fails += CHECK_SUPPORTS (avx512cd, AVX512CD);
+  fails += CHECK_SUPPORTS (avx512er, AVX512ER);
+  fails += CHECK_SUPPORTS (avx512dq, AVX512DQ);
+#endif
+#if __GNUC_PREREQ (5, 0)
+  fails += CHECK_SUPPORTS (avx512f, AVX512F);
+#endif
+#if __GNUC_PREREQ (6, 0)
+  fails += CHECK_SUPPORTS (avx512pf, AVX512PF);
+  fails += CHECK_SUPPORTS (avx512vl, AVX512VL);
+#endif
+#if __GNUC_PREREQ (5, 0)
+  fails += CHECK_SUPPORTS (bmi, BMI1);
+  fails += CHECK_SUPPORTS (bmi2, BMI2);
+#endif
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (cldemote, CLDEMOTE);
+  fails += CHECK_SUPPORTS (clflushopt, CLFLUSHOPT);
+  fails += CHECK_SUPPORTS (clwb, CLWB);
+#endif
+  fails += CHECK_SUPPORTS (cmov, CMOV);
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (cmpxchg16b, CMPXCHG16B);
+  fails += CHECK_SUPPORTS (cmpxchg8b, CX8);
+  fails += CHECK_SUPPORTS (enqcmd, ENQCMD);
+  fails += CHECK_SUPPORTS (f16c, F16C);
+#endif
+#if __GNUC_PREREQ (4, 9)
+  fails += CHECK_SUPPORTS (fma, FMA);
+  fails += CHECK_SUPPORTS (fma4, FMA4);
+#endif
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (fsgsbase, FSGSBASE);
+  fails += CHECK_SUPPORTS (fxsave, FXSR);
+#endif
+#if __GNUC_PREREQ (8, 0)
+  fails += CHECK_SUPPORTS (gfni, GFNI);
+#endif
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (hle, HLE);
+  fails += CHECK_SUPPORTS (ibt, IBT);
+  fails += CHECK_SUPPORTS (lahf_lm, LAHF64_SAHF64);
+  fails += CHECK_SUPPORTS (lm, LM);
+  fails += CHECK_SUPPORTS (lwp, LWP);
+  fails += CHECK_SUPPORTS (lzcnt, LZCNT);
+#endif
+  fails += CHECK_SUPPORTS (mmx, MMX);
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (movbe, MOVBE);
+  fails += CHECK_SUPPORTS (movdiri, MOVDIRI);
+  fails += CHECK_SUPPORTS (movdir64b, MOVDIR64B);
+  fails += CHECK_SUPPORTS (osxsave, OSXSAVE);
+  fails += CHECK_SUPPORTS (pconfig, PCONFIG);
+  fails += CHECK_SUPPORTS (pku, PKU);
+#endif
+  fails += CHECK_SUPPORTS (popcnt, POPCNT);
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (prefetchwt1, PREFETCHWT1);
+  fails += CHECK_SUPPORTS (rdpid, RDPID);
+  fails += CHECK_SUPPORTS (rdrnd, RDRAND);
+  fails += CHECK_SUPPORTS (rdseed, RDSEED);
+  fails += CHECK_SUPPORTS (rtm, RTM);
+  fails += CHECK_SUPPORTS (serialize, SERIALIZE);
+  fails += CHECK_SUPPORTS (sha, SHA);
+  fails += CHECK_SUPPORTS (shstk, SHSTK);
+#endif
+  fails += CHECK_SUPPORTS (sse, SSE);
+  fails += CHECK_SUPPORTS (sse2, SSE2);
+  fails += CHECK_SUPPORTS (sse3, SSE3);
+  fails += CHECK_SUPPORTS (sse4.1, SSE4_1);
+  fails += CHECK_SUPPORTS (sse4.2, SSE4_2);
+#if __GNUC_PREREQ (4, 9)
+  fails += CHECK_SUPPORTS (sse4a, SSE4A);
+#endif
+  fails += CHECK_SUPPORTS (ssse3, SSSE3);
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (tbm, TBM);
+  fails += CHECK_SUPPORTS (tsxldtrk, TSXLDTRK);
+  fails += CHECK_SUPPORTS (vaes, VAES);
+#endif
+#if __GNUC_PREREQ (8, 0)
+  fails += CHECK_SUPPORTS (vpclmulqdq, VPCLMULQDQ);
+#endif
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (waitpkg, WAITPKG);
+  fails += CHECK_SUPPORTS (wbnoinvd, WBNOINVD);
+#endif
+#if __GNUC_PREREQ (4, 9)
+  fails += CHECK_SUPPORTS (xop, XOP);
+#endif
+#if __GNUC_PREREQ (11, 0)
+  fails += CHECK_SUPPORTS (xsave, XSAVE);
+  fails += CHECK_SUPPORTS (xsavec, XSAVEC);
+  fails += CHECK_SUPPORTS (xsaveopt, XSAVEOPT);
+  fails += CHECK_SUPPORTS (xsaves, XSAVES);
+#endif
+
+  printf ("%d differences between __builtin_cpu_supports and glibc code.\n",
+	  fails);
+
+  return (fails != 0);
+}
+
+#include "../../../test-skeleton.c"
diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
index 6bfdef0829..3447d17e23 100644
--- a/sysdeps/x86/tst-get-cpu-features.c
+++ b/sysdeps/x86/tst-get-cpu-features.c
@@ -1,4 +1,4 @@ 
-/* Test case for x86 __get_cpu_features interface
+/* Test case for __x86_get_cpu_features interface
    Copyright (C) 2015-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -18,7 +18,7 @@ 
 
 #include <stdlib.h>
 #include <stdio.h>
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 #include <support/check.h>
 
 #define CHECK_CPU_FEATURE(name)		\
@@ -45,7 +45,7 @@  static const char * const cpu_kinds[] =
 static int
 do_test (void)
 {
-  const struct cpu_features *cpu_features = __get_cpu_features ();
+  const struct cpu_features *cpu_features = __x86_get_cpu_features (0);
 
   switch (cpu_features->basic.kind)
     {
diff --git a/sysdeps/x86_64/fpu/math-tests-arch.h b/sysdeps/x86_64/fpu/math-tests-arch.h
index 33ea763de2..cc3c2b0c11 100644
--- a/sysdeps/x86_64/fpu/math-tests-arch.h
+++ b/sysdeps/x86_64/fpu/math-tests-arch.h
@@ -16,7 +16,7 @@ 
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 
 #if defined REQUIRE_AVX
 
diff --git a/sysdeps/x86_64/multiarch/Makefile b/sysdeps/x86_64/multiarch/Makefile
index 395e432c09..9477538af4 100644
--- a/sysdeps/x86_64/multiarch/Makefile
+++ b/sysdeps/x86_64/multiarch/Makefile
@@ -1,7 +1,3 @@ 
-ifeq ($(subdir),csu)
-tests += test-multiarch
-endif
-
 ifeq ($(subdir),string)
 
 sysdep_routines += strncat-c stpncpy-c strncpy-c \
diff --git a/sysdeps/x86_64/multiarch/test-multiarch.c b/sysdeps/x86_64/multiarch/test-multiarch.c
deleted file mode 100644
index 2782803e73..0000000000
--- a/sysdeps/x86_64/multiarch/test-multiarch.c
+++ /dev/null
@@ -1,96 +0,0 @@ 
-/* Test CPU feature data.
-   This file is part of the GNU C Library.
-   Copyright (C) 2012-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 <cpu-features.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static char *cpu_flags;
-
-/* Search for flags in /proc/cpuinfo and store line
-   in cpu_flags.  */
-void
-get_cpuinfo (void)
-{
-  FILE *f;
-  char *line = NULL;
-  size_t len = 0;
-  ssize_t read;
-
-  f = fopen ("/proc/cpuinfo", "r");
-  if (f == NULL)
-    {
-      printf ("cannot open /proc/cpuinfo\n");
-      exit (1);
-    }
-
-  while ((read = getline (&line, &len, f)) != -1)
-    {
-      if (strncmp (line, "flags", 5) == 0)
-       {
-         cpu_flags = strdup (line);
-         break;
-       }
-    }
-  fclose (f);
-  free (line);
-}
-
-int
-check_proc (const char *proc_name, int flag, const char *name)
-{
-  int found = 0;
-
-  printf ("Checking %s:\n", name);
-  printf ("  init-arch %d\n", flag);
-  if (strstr (cpu_flags, proc_name) != NULL)
-    found = 1;
-  printf ("  cpuinfo (%s) %d\n", proc_name, found);
-
-  if (found != flag)
-    printf (" *** failure ***\n");
-
-  return (found != flag);
-}
-
-static int
-do_test (int argc, char **argv)
-{
-  int fails;
-
-  get_cpuinfo ();
-  fails = check_proc ("avx", CPU_FEATURE_USABLE (AVX),
-		      "CPU_FEATURE_USABLE (AVX)");
-  fails += check_proc ("fma4", CPU_FEATURE_USABLE (FMA4),
-		       "CPU_FEATURE_USABLE (FMA4)");
-  fails += check_proc ("sse4_2", CPU_FEATURE_USABLE (SSE4_2),
-		       "CPU_FEATURE_USABLE (SSE4_2)");
-  fails += check_proc ("sse4_1", CPU_FEATURE_USABLE (SSE4_1)
-		       , "CPU_FEATURE_USABLE (SSE4_1)");
-  fails += check_proc ("ssse3", CPU_FEATURE_USABLE (SSSE3),
-		       "CPU_FEATURE_USABLE (SSSE3)");
-  fails += check_proc ("popcnt", CPU_FEATURE_USABLE (POPCNT),
-		       "CPU_FEATURE_USABLE (POPCNT)");
-
-  printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails);
-
-  return (fails != 0);
-}
-
-#include "../../../test-skeleton.c"