V4 [PATCH] x86: Add <sys/platform/x86.h>

Message ID 20180919131313.GA7503@intel.com
State New, archived
Headers

Commit Message

Lu, Hongjiu Sept. 19, 2018, 1:13 p.m. UTC
  This version removed x86_get_cpu_kind.  OK for master?


H.J.
---
Add <sys/platform/x86.h> to provide an API to access x86 specific platform
features.  It makes raw and derived CPUID information available to
applications so that programmers can avoid complicated steps to retrieve
the same information with CPUID instructions.

enum
  {
    /* The integer bit array index for the first set of internal feature
       bits.  */
    FEATURE_INDEX_1 = 0,
    FEATURE_INDEX_2,
    /* The current maximum size of the feature integer bit array.  */
    FEATURE_INDEX_MAX
  };

FEATURE_INDEX_1 is used by the public API and FEATURE_INDEX_2 is for
glibc internal use.

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

struct cpuid_registers
  {
    unsigned int eax;
    unsigned int ebx;
    unsigned int ecx;
    unsigned int edx;
  };

extern const struct cpuid_registers *x86_get_cpuid_registers
     (unsigned int) __attribute__ ((const));

extern unsigned int x86_get_arch_feature (unsigned int)
     __attribute__ ((const));

/* HAS_* evaluates to true if we may use the feature at runtime.  */
 #define HAS_CPU_FEATURE(name) \
   ((x86_get_cpuid_registers (index_cpu_##name)->reg_##name \
     & (bit_cpu_##name)) != 0)
 #define HAS_ARCH_FEATURE(name) \
   ((x86_get_arch_feature (index_arch_##name) & (bit_arch_##name)) != 0)

Users can use <sys/platform/x86.h> to detect if a CPU feature is supported
at run-time with "HAS_CPU_FEATURE (AVX)" which evaluates true if glibc
detects that AVX is available.  Before AVX can be used, he/she should check
"HAS_ARCH_FEATURE (AVX_Usable)" which evaluates true if glibc detects that
AVX is available and usable.

Note: "HAS_CPU_FEATURE (XXX)" and "HAS_ARCH_FEATURE (YYY)" evaluate false
if the feature isn't available or the run-time glibc, which is older than
the compile-time glibc, doesn't support this feature check.

CPUID instruction takes EAX and optionally ECX as input,  It writes to
EAX, EBX, ECD and EDX.  Each CPU feature is determined by CPUID with
specific input values and a bit in EAX, EBX, ECX or EDX.  HAS_CPU_FEATURE
and HAS_ARCH_FEATURE macros generate very decent code.  There are many
reserved bits in EAX, EBX, ECX and EDX, which may be changed to new CPU
features for future processors.  It is easy to add these features to x86.h
with macros without recompiling glibc.  All CPU and architecture feature
macros should be tested by sysdeps/x86/tst-get-cpu-features.c.

Backward binary compatibility is provided by:

1. x86_get_cpuid_registers returns a pointer to an element of struct
cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX], the cached output of CPUID.
If cpuid index >= COMMON_CPUID_INDEX_MAX, we return a pointer to struct
cpuid_registers with all zeros.  This happens when the run-time glibc
doesn't support the newly added cpuid index.
2. x86_get_arch_feature returns 0 if architecture index >=
FEATURE_INDEX_MAX.  This happens when the run-time glibc doesn't support
the newly added feature index.

Applications linked against the new x86_get_cpuid_registers and
x86_get_arch_feature will run with the older libc.so.  But new
CPU and architecture features won't be detected by the older libc.so.

Add more CPU features for COMMON_CPUID_INDEX_1, COMMON_CPUID_INDEX_7
and COMMON_CPUID_INDEX_80000001.  Update tst-get-cpu-features.c to
test all bit_cpu_XXX and bit_arch_XXX bits.

	* NEWS: Mention <sys/platform/x86.h>.
	* manual/platform.texi: Add entries for <sys/platform/x86.h>.
	* sysdeps/mach/hurd/i386/ld.abilist (GLIBC_2.29): Add
	x86_get_arch_feature and x86_get_cpuid_registers.
	* sysdeps/unix/sysv/linux/i386/ld.abilist (GLIBC_2.29): Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/ld.abilist (GLIBC_2.29):
	Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist (GLIBC_2.29):
	Likewise.
	* sysdeps/x86/Makefile (tests): Add tst-x86-platform-1,
	tst-x86-platform-1-static, tst-x86-platform-2 and
	tst-x86-platform-3.
	(tests-static): Add tst-x86-platform-1-static.
	(modules-names): Add tst-x86-platform-mod-2 and
	tst-x86-platform-mod-3.
	($(objpfx)tst-x86-platform-mod-2.so): New.
	($(objpfx)tst-x86-platform-2): Likewise.
	(LDFLAGS-tst-x86-platform-mod-3.so): Likewise.
	($(objpfx)tst-x86-platform-mod-3.so): Likewise.
	($(objpfx)tst-x86-platform-3): Likewise.
	(sysdep_headers): Add sys/platform/x86.h.
	* sysdeps/x86/Versions (ld): Add x86_get_cpuid_registers and
	x86_get_arch_feature to GLIBC_2.29.
	* sysdeps/x86/cpu-features.c (init_cpu_features): Use
	_Static_assert on index_arch_Fast_Unaligned_Load.
	__get_cpuid_registers and  __get_arch_feature.
	* sysdeps/x86/cpu-features.h: Include <sys/platform/x86.h>.
	(FEATURE_INDEX_1): Removed.
	(FEATURE_INDEX_MAX): Likewise.
	(HAS_CPU_FEATURE): Likewise.
	(HAS_ARCH_FEATURE): Likewise.
	(COMMON_CPUID_INDEX_XXX): Likewise.
	(cpuid_registers): Likewise.
	(bit_arch_XXX): Move most to <sys/platform/x86.h>.
	(bit_cpu_XXX): Likewise.
	(index_cpu_XXX): Likewise.
	(reg_XXX): Likewise.
	(index_arch_XXX): Move most to <sys/platform/x86.h>.  Define
	rest to FEATURE_INDEX_2.
	* sysdeps/x86/dl-get-cpu-features.c (x86_get_cpuid_registers):
	Undef.
	(x86_get_arch_feature): Likewise.
	(x86_get_cpuid_registers): New function.
	(x86_get_arch_feature): Likewise.
	* sysdeps/x86/sys/platform/x86.h: New file.
	* sysdeps/x86/tst-get-cpu-features.c: Include <stdio.h> and
	<support/check.h>.
	(cpu_kinds): New.
	(CHECK_CPU_FEATURE): Likewise.
	(CHECK_ARCH_FEATURE): Likewise.
	(do_test): Check SSE2 at run-time.  Print vendor and all
	bit_cpu_XXX and bit_arch_XXX bits.
	(TEST_FUNCTION): Removed.
	Include <support/test-driver.c> instead of
	"../../test-skeleton.c".
	* sysdeps/x86/tst-x86-platform-1-static.c: New file.
	* sysdeps/x86/tst-x86-platform-1.c: Likewise.
	* sysdeps/x86/tst-x86-platform-2.c: Likewise.
	* sysdeps/x86/tst-x86-platform-3.c: Likewise.
	* sysdeps/x86/tst-x86-platform-mod-2.c: Likewise.
	* sysdeps/x86/tst-x86-platform-mod-3.c: Likewise.
	* sysdeps/x86_64/multiarch/sched_cpucount.c (__sched_cpucount):
	Check POPCNT instead of POPCOUNT.
	* sysdeps/x86_64/multiarch/test-multiarch.c (do_test): Likewise.
---
 NEWS                                          |   3 +
 manual/platform.texi                          | 489 +++++++++++++++
 sysdeps/mach/hurd/i386/ld.abilist             |   2 +
 sysdeps/unix/sysv/linux/i386/ld.abilist       |   2 +
 sysdeps/unix/sysv/linux/x86_64/64/ld.abilist  |   2 +
 sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |   2 +
 sysdeps/x86/Makefile                          |  17 +-
 sysdeps/x86/Versions                          |   3 +
 sysdeps/x86/cpu-features.c                    |  93 ++-
 sysdeps/x86/cpu-features.h                    | 248 ++------
 sysdeps/x86/dl-get-cpu-features.c             |  19 +
 sysdeps/x86/sys/platform/x86.h                | 557 ++++++++++++++++++
 sysdeps/x86/tst-get-cpu-features.c            | 214 ++++++-
 sysdeps/x86/tst-x86-platform-1-static.c       |   1 +
 sysdeps/x86/tst-x86-platform-1.c              | 205 +++++++
 sysdeps/x86/tst-x86-platform-2.c              |  27 +
 sysdeps/x86/tst-x86-platform-3.c              |  27 +
 sysdeps/x86/tst-x86-platform-mod-2.c          |   2 +
 sysdeps/x86/tst-x86-platform-mod-3.c          |   2 +
 sysdeps/x86_64/multiarch/sched_cpucount.c     |   2 +-
 sysdeps/x86_64/multiarch/test-multiarch.c     |   4 +-
 21 files changed, 1700 insertions(+), 221 deletions(-)
 create mode 100644 sysdeps/x86/sys/platform/x86.h
 create mode 100644 sysdeps/x86/tst-x86-platform-1-static.c
 create mode 100644 sysdeps/x86/tst-x86-platform-1.c
 create mode 100644 sysdeps/x86/tst-x86-platform-2.c
 create mode 100644 sysdeps/x86/tst-x86-platform-3.c
 create mode 100644 sysdeps/x86/tst-x86-platform-mod-2.c
 create mode 100644 sysdeps/x86/tst-x86-platform-mod-3.c
  

Comments

Florian Weimer Sept. 20, 2018, 11:41 a.m. UTC | #1
* H. J. Lu:

> Add <sys/platform/x86.h> to provide an API to access x86 specific platform
> features.  It makes raw and derived CPUID information available to
> applications so that programmers can avoid complicated steps to retrieve
> the same information with CPUID instructions.

Sorry, I still think that this patch semantically depends on delayed
IFUNC processing.

Furthermore, I strongly prefer a simplified interface, like:

  enum {
    X86_FEATURE_MMX,
    X86_FEATURE_SSE,
    X86_FEATURE_SSE2,
    …
    X86_FEATURE_AVX512F,
    …
  };

  _Bool x86_feature_usable (int index) __attribute__ ((pure));

Applications could then do something like this:

  if (x86_feature_usable (X86_FEATURE_AVX512F))
    return &__matmul_avx512f;

I don't think there is value in exposing the CPUID data directly.  If
programmers need it, they can use <cpuid.h> from GCC instead, without
needing to worry how glibc populates its data structures.

Thanks,
Florian
  
H.J. Lu Sept. 20, 2018, 12:39 p.m. UTC | #2
On Thu, Sep 20, 2018 at 4:41 AM, Florian Weimer <fweimer@redhat.com> wrote:
> * H. J. Lu:
>
>> Add <sys/platform/x86.h> to provide an API to access x86 specific platform
>> features.  It makes raw and derived CPUID information available to
>> applications so that programmers can avoid complicated steps to retrieve
>> the same information with CPUID instructions.
>
> Sorry, I still think that this patch semantically depends on delayed
> IFUNC processing.
>
> Furthermore, I strongly prefer a simplified interface, like:
>
>   enum {
>     X86_FEATURE_MMX,
>     X86_FEATURE_SSE,
>     X86_FEATURE_SSE2,
>     …
>     X86_FEATURE_AVX512F,
>     …
>   };
>
>   _Bool x86_feature_usable (int index) __attribute__ ((pure));
>
> Applications could then do something like this:
>
>   if (x86_feature_usable (X86_FEATURE_AVX512F))
>     return &__matmul_avx512f;
>
> I don't think there is value in exposing the CPUID data directly.  If
> programmers need it, they can use <cpuid.h> from GCC instead, without
> needing to worry how glibc populates its data structures.
>

You have 2 concerns.  Which one is the primary concern?  Or
are both blockers for you?
  
Florian Weimer Sept. 20, 2018, 12:43 p.m. UTC | #3
* H. J. Lu:

> On Thu, Sep 20, 2018 at 4:41 AM, Florian Weimer <fweimer@redhat.com> wrote:
>> * H. J. Lu:
>>
>>> Add <sys/platform/x86.h> to provide an API to access x86 specific platform
>>> features.  It makes raw and derived CPUID information available to
>>> applications so that programmers can avoid complicated steps to retrieve
>>> the same information with CPUID instructions.
>>
>> Sorry, I still think that this patch semantically depends on delayed
>> IFUNC processing.
>>
>> Furthermore, I strongly prefer a simplified interface, like:
>>
>>   enum {
>>     X86_FEATURE_MMX,
>>     X86_FEATURE_SSE,
>>     X86_FEATURE_SSE2,
>>     …
>>     X86_FEATURE_AVX512F,
>>     …
>>   };
>>
>>   _Bool x86_feature_usable (int index) __attribute__ ((pure));
>>
>> Applications could then do something like this:
>>
>>   if (x86_feature_usable (X86_FEATURE_AVX512F))
>>     return &__matmul_avx512f;
>>
>> I don't think there is value in exposing the CPUID data directly.  If
>> programmers need it, they can use <cpuid.h> from GCC instead, without
>> needing to worry how glibc populates its data structures.
>>
>
> You have 2 concerns.  Which one is the primary concern?  Or
> are both blockers for you?

The design of the API is more important.

We can implement delayed IFUNC processing later to support this feature
(and others).

Thanks,
Florian
  
H.J. Lu Sept. 20, 2018, 12:57 p.m. UTC | #4
On Thu, Sep 20, 2018 at 5:43 AM, Florian Weimer <fweimer@redhat.com> wrote:
> * H. J. Lu:
>
>> On Thu, Sep 20, 2018 at 4:41 AM, Florian Weimer <fweimer@redhat.com> wrote:
>>> * H. J. Lu:
>>>
>>>> Add <sys/platform/x86.h> to provide an API to access x86 specific platform
>>>> features.  It makes raw and derived CPUID information available to
>>>> applications so that programmers can avoid complicated steps to retrieve
>>>> the same information with CPUID instructions.
>>>
>>> Sorry, I still think that this patch semantically depends on delayed
>>> IFUNC processing.

I don't believe this is an issue at all since new functions are in
ld.so.  Can you show this is a real issue with a testcase? I can
add it to my test.

>>> Furthermore, I strongly prefer a simplified interface, like:
>>>
>>>   enum {
>>>     X86_FEATURE_MMX,
>>>     X86_FEATURE_SSE,
>>>     X86_FEATURE_SSE2,
>>>     …
>>>     X86_FEATURE_AVX512F,
>>>     …
>>>   };
>>>
>>>   _Bool x86_feature_usable (int index) __attribute__ ((pure));
>>>
>>> Applications could then do something like this:
>>>
>>>   if (x86_feature_usable (X86_FEATURE_AVX512F))
>>>     return &__matmul_avx512f;
>>>
>>> I don't think there is value in exposing the CPUID data directly.  If
>>> programmers need it, they can use <cpuid.h> from GCC instead, without
>>> needing to worry how glibc populates its data structures.

There are several advantages of my approach:

1. When a new feature is added to previously reserved bit, the
program using the new feature will work with the older libc.so
whose CPUID data has the reserved bit.
2. We only need to add 2 small functions:

(gdb) disass x86_get_arch_feature
Dump of assembler code for function x86_get_arch_feature:
   0x0000000000017100 <+0>: xor    %eax,%eax
   0x0000000000017102 <+2>: cmp    $0x2,%edi
   0x0000000000017105 <+5>: ja     0x17117 <x86_get_arch_feature+23>
   0x0000000000017107 <+7>: mov    %edi,%edi
   0x0000000000017109 <+9>: lea    0x105f0(%rip),%rax        # 0x27700
<_rtld_local_ro>
   0x0000000000017110 <+16>: mov    0xb4(%rax,%rdi,4),%eax
   0x0000000000017117 <+23>: retq
End of assembler dump.
(gdb) disass x86_get_cpuid_registers
Dump of assembler code for function x86_get_cpuid_registers:
   0x00000000000170d0 <+0>: lea    0xc479(%rip),%rax        # 0x23550
<zero_cpuid_registers.8564>
   0x00000000000170d7 <+7>: cmp    $0x2,%edi
   0x00000000000170da <+10>: ja     0x170f0 <x86_get_cpuid_registers+32>
   0x00000000000170dc <+12>: mov    %edi,%edi
   0x00000000000170de <+14>: lea    0x1061b(%rip),%rax        #
0x27700 <_rtld_local_ro>
   0x00000000000170e5 <+21>: add    $0x7,%rdi
   0x00000000000170e9 <+25>: shl    $0x4,%rdi
   0x00000000000170ed <+29>: add    %rdi,%rax
   0x00000000000170f0 <+32>: retq
End of assembler dump.
(gdb)
3. Write CPUID program isn't easy.   You can try to write a program
to detect a CPUID feature to see what it takes.  I can't remember it
exactly without looking at glibc sources which I wrote.

>>
>> You have 2 concerns.  Which one is the primary concern?  Or
>> are both blockers for you?
>
> The design of the API is more important.
>
> We can implement delayed IFUNC processing later to support this feature
> (and others).
  
Florian Weimer Sept. 20, 2018, 1:14 p.m. UTC | #5
* H. J. Lu:

> On Thu, Sep 20, 2018 at 5:43 AM, Florian Weimer <fweimer@redhat.com> wrote:
>> * H. J. Lu:
>>
>>> On Thu, Sep 20, 2018 at 4:41 AM, Florian Weimer <fweimer@redhat.com> wrote:
>>>> * H. J. Lu:
>>>>
>>>>> Add <sys/platform/x86.h> to provide an API to access x86 specific platform
>>>>> features.  It makes raw and derived CPUID information available to
>>>>> applications so that programmers can avoid complicated steps to retrieve
>>>>> the same information with CPUID instructions.
>>>>
>>>> Sorry, I still think that this patch semantically depends on delayed
>>>> IFUNC processing.
>
> I don't believe this is an issue at all since new functions are in
> ld.so.  Can you show this is a real issue with a testcase? I can
> add it to my test.

It's the relocation for x86_get_arch_feature in the IFUNC resolver I'm
worried about.  Without delayed processing, the IFUNC resolver may be
called at any time, and the relocation for x86_get_arch_feature may not
have been processed yet.  So it's not about calling into an unrelocated
or uninitialized ld.so (which I agree would not happen), but the call
itself going wrong because it's not been properly relocated yet.

Usually, dependency order as established by DT_NEEDED entries will
ensure that IFUNC resolvers are only called in already-relocated
objects, but LD_PRELOAD, symbol interposition, or missing DT_NEEDED
entries can invalidate that assumption and make the dependency ordering
insufficient.

I hope this makes it clear what I think will break when this feature is
used from IFUNC resolvers.

>>>> Furthermore, I strongly prefer a simplified interface, like:
>>>>
>>>>   enum {
>>>>     X86_FEATURE_MMX,
>>>>     X86_FEATURE_SSE,
>>>>     X86_FEATURE_SSE2,
>>>>     …
>>>>     X86_FEATURE_AVX512F,
>>>>     …
>>>>   };
>>>>
>>>>   _Bool x86_feature_usable (int index) __attribute__ ((pure));
>>>>
>>>> Applications could then do something like this:
>>>>
>>>>   if (x86_feature_usable (X86_FEATURE_AVX512F))
>>>>     return &__matmul_avx512f;
>>>>
>>>> I don't think there is value in exposing the CPUID data directly.  If
>>>> programmers need it, they can use <cpuid.h> from GCC instead, without
>>>> needing to worry how glibc populates its data structures.
>
> There are several advantages of my approach:
>
> 1. When a new feature is added to previously reserved bit, the
> program using the new feature will work with the older libc.so
> whose CPUID data has the reserved bit.

It depends on the CPUID feature bit whether that's a good idea.  For the
AVX512F, that would be wrong because it the CPUID data does not tell you
whether the feature is actually usable.

There is no ABI impact for future feature flags, so we can backport them
easily enough.

> 2. We only need to add 2 small functions:
>
> (gdb) disass x86_get_arch_feature
> Dump of assembler code for function x86_get_arch_feature:
>    0x0000000000017100 <+0>: xor    %eax,%eax
>    0x0000000000017102 <+2>: cmp    $0x2,%edi
>    0x0000000000017105 <+5>: ja     0x17117 <x86_get_arch_feature+23>
>    0x0000000000017107 <+7>: mov    %edi,%edi
>    0x0000000000017109 <+9>: lea    0x105f0(%rip),%rax        # 0x27700
> <_rtld_local_ro>
>    0x0000000000017110 <+16>: mov    0xb4(%rax,%rdi,4),%eax
>    0x0000000000017117 <+23>: retq
> End of assembler dump.
> (gdb) disass x86_get_cpuid_registers
> Dump of assembler code for function x86_get_cpuid_registers:
>    0x00000000000170d0 <+0>: lea    0xc479(%rip),%rax        # 0x23550
> <zero_cpuid_registers.8564>
>    0x00000000000170d7 <+7>: cmp    $0x2,%edi
>    0x00000000000170da <+10>: ja     0x170f0 <x86_get_cpuid_registers+32>
>    0x00000000000170dc <+12>: mov    %edi,%edi
>    0x00000000000170de <+14>: lea    0x1061b(%rip),%rax        #
> 0x27700 <_rtld_local_ro>
>    0x00000000000170e5 <+21>: add    $0x7,%rdi
>    0x00000000000170e9 <+25>: shl    $0x4,%rdi
>    0x00000000000170ed <+29>: add    %rdi,%rax
>    0x00000000000170f0 <+32>: retq
> End of assembler dump.
> (gdb)

The implementation of x86_feature_usable would be quite similar, but it
would be necessary to readjust the way the usable bits are stored in
ld.so.  That is true.

> 3. Write CPUID program isn't easy.   You can try to write a program
> to detect a CPUID feature to see what it takes.  I can't remember it
> exactly without looking at glibc sources which I wrote.

I completely agree, which is why I think we should *not* expose CPUID
data, but higher-level information about which features are available.
In some cases, it may be possible to use CPUID bits directly (for CMOV
on i386, for example), but in many other cases, it will be necessary to
take environmental factors into account, e.g. how the kernel has set up
XCR0 when it created the process.

As far as I know, it's the latter aspect that is not known in advance:
Future CPUID bits might well have dependencies on XCR0 (or other CPU
state) as well.  An application which tries to do detection with older
glibcs without the corresponding *_Usable support would necessarily go
wrong.  My API proposal avoids that because it just cannot happen with
this interface, at the cost that you need to upgrade glibc first before
you can use any previously-unknown bits.

Thanks,
Florian
  
H.J. Lu Sept. 22, 2018, 4:21 p.m. UTC | #6
On Thu, Sep 20, 2018 at 6:14 AM, Florian Weimer <fweimer@redhat.com> wrote:
> * H. J. Lu:
>
>> On Thu, Sep 20, 2018 at 5:43 AM, Florian Weimer <fweimer@redhat.com> wrote:
>>> * H. J. Lu:
>>>
>>>> On Thu, Sep 20, 2018 at 4:41 AM, Florian Weimer <fweimer@redhat.com> wrote:
>>>>> * H. J. Lu:
>>>>>
>>>>>> Add <sys/platform/x86.h> to provide an API to access x86 specific platform
>>>>>> features.  It makes raw and derived CPUID information available to
>>>>>> applications so that programmers can avoid complicated steps to retrieve
>>>>>> the same information with CPUID instructions.
>>>>>
>>>>> Sorry, I still think that this patch semantically depends on delayed
>>>>> IFUNC processing.
>>
>> I don't believe this is an issue at all since new functions are in
>> ld.so.  Can you show this is a real issue with a testcase? I can
>> add it to my test.
>
> It's the relocation for x86_get_arch_feature in the IFUNC resolver I'm
> worried about.  Without delayed processing, the IFUNC resolver may be
> called at any time, and the relocation for x86_get_arch_feature may not
> have been processed yet.  So it's not about calling into an unrelocated
> or uninitialized ld.so (which I agree would not happen), but the call
> itself going wrong because it's not been properly relocated yet.
>
> Usually, dependency order as established by DT_NEEDED entries will
> ensure that IFUNC resolvers are only called in already-relocated
> objects, but LD_PRELOAD, symbol interposition, or missing DT_NEEDED
> entries can invalidate that assumption and make the dependency ordering
> insufficient.
>
> I hope this makes it clear what I think will break when this feature is
> used from IFUNC resolvers.

I don't think this is an issue.  I wrote a testcase to use <sys/platform/x86.h>
macros in IFUNC resolver in a LD_PRELOAD library:

https://github.com/hjl-tools/glibc/commit/94c992985919cfd5f5f7db431a6149376ab3d587

Is that what you have in mind?  If not, can you show me with a testcase?

>>>>> Furthermore, I strongly prefer a simplified interface, like:
>>>>>
>>>>>   enum {
>>>>>     X86_FEATURE_MMX,
>>>>>     X86_FEATURE_SSE,
>>>>>     X86_FEATURE_SSE2,
>>>>>     …
>>>>>     X86_FEATURE_AVX512F,
>>>>>     …
>>>>>   };
>>>>>
>>>>>   _Bool x86_feature_usable (int index) __attribute__ ((pure));
>>>>>
>>>>> Applications could then do something like this:
>>>>>
>>>>>   if (x86_feature_usable (X86_FEATURE_AVX512F))
>>>>>     return &__matmul_avx512f;
>>>>>
>>>>> I don't think there is value in exposing the CPUID data directly.  If
>>>>> programmers need it, they can use <cpuid.h> from GCC instead, without
>>>>> needing to worry how glibc populates its data structures.
>>
>> There are several advantages of my approach:
>>
>> 1. When a new feature is added to previously reserved bit, the
>> program using the new feature will work with the older libc.so
>> whose CPUID data has the reserved bit.
>
> It depends on the CPUID feature bit whether that's a good idea.  For the
> AVX512F, that would be wrong because it the CPUID data does not tell you
> whether the feature is actually usable.
>
> There is no ABI impact for future feature flags, so we can backport them
> easily enough.
>
>> 2. We only need to add 2 small functions:
>>
>> (gdb) disass x86_get_arch_feature
>> Dump of assembler code for function x86_get_arch_feature:
>>    0x0000000000017100 <+0>: xor    %eax,%eax
>>    0x0000000000017102 <+2>: cmp    $0x2,%edi
>>    0x0000000000017105 <+5>: ja     0x17117 <x86_get_arch_feature+23>
>>    0x0000000000017107 <+7>: mov    %edi,%edi
>>    0x0000000000017109 <+9>: lea    0x105f0(%rip),%rax        # 0x27700
>> <_rtld_local_ro>
>>    0x0000000000017110 <+16>: mov    0xb4(%rax,%rdi,4),%eax
>>    0x0000000000017117 <+23>: retq
>> End of assembler dump.
>> (gdb) disass x86_get_cpuid_registers
>> Dump of assembler code for function x86_get_cpuid_registers:
>>    0x00000000000170d0 <+0>: lea    0xc479(%rip),%rax        # 0x23550
>> <zero_cpuid_registers.8564>
>>    0x00000000000170d7 <+7>: cmp    $0x2,%edi
>>    0x00000000000170da <+10>: ja     0x170f0 <x86_get_cpuid_registers+32>
>>    0x00000000000170dc <+12>: mov    %edi,%edi
>>    0x00000000000170de <+14>: lea    0x1061b(%rip),%rax        #
>> 0x27700 <_rtld_local_ro>
>>    0x00000000000170e5 <+21>: add    $0x7,%rdi
>>    0x00000000000170e9 <+25>: shl    $0x4,%rdi
>>    0x00000000000170ed <+29>: add    %rdi,%rax
>>    0x00000000000170f0 <+32>: retq
>> End of assembler dump.
>> (gdb)
>
> The implementation of x86_feature_usable would be quite similar, but it
> would be necessary to readjust the way the usable bits are stored in
> ld.so.  That is true.
>
>> 3. Write CPUID program isn't easy.   You can try to write a program
>> to detect a CPUID feature to see what it takes.  I can't remember it
>> exactly without looking at glibc sources which I wrote.
>
> I completely agree, which is why I think we should *not* expose CPUID
> data, but higher-level information about which features are available.
> In some cases, it may be possible to use CPUID bits directly (for CMOV
> on i386, for example), but in many other cases, it will be necessary to
> take environmental factors into account, e.g. how the kernel has set up
> XCR0 when it created the process.
>
> As far as I know, it's the latter aspect that is not known in advance:
> Future CPUID bits might well have dependencies on XCR0 (or other CPU
> state) as well.  An application which tries to do detection with older
> glibcs without the corresponding *_Usable support would necessarily go
> wrong.  My API proposal avoids that because it just cannot happen with
> this interface, at the cost that you need to upgrade glibc first before
> you can use any previously-unknown bits.
>

I redesigned my interface:

/* HAS_CPU_FEATURE  evaluates to true if CPU supports the feature.  */
#define HAS_CPU_FEATURE(name) \
 ((x86_get_cpuid_registers (index_cpu_##name)->reg_##name \
   & (bit_cpu_##name)) != 0)
/* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
#define CPU_FEATURE_USABLE(name) \
  ((need_arch_feature_##name \
    && (x86_get_arch_feature (index_arch_##name##_Usable) \
& (bit_arch_##name##_Usable)) != 0) \
   || (!need_arch_feature_##name && HAS_CPU_FEATURE(name)))

 -- Macro: CPU_FEATURE_USABLE(name)

     Evaluate to true if the architecture feature ‘name’ is usable.  The
     supported features are:

     ‘ADX’             ‘AES’             ‘AVX’             ‘AVX2’
     ‘AVX512_4FMAPS’   ‘AVX512_4VNNIW’   ‘AVX512_BITALG’   ‘AVX512_IFMA’
     ‘AVX512_VBMI’     ‘AVX512_VBMI2’    ‘AVX512_VNNI’     ‘AVX512_VPOPCNTDQ’
     ‘AVX512BW’        ‘AVX512CD’        ‘AVX512ER’        ‘AVX512DQ’
     ‘AVX512F’         ‘AVX512PF’        ‘AVX512VL’        ‘BMI1’
     ‘BMI2’            ‘CLDEMOTE’        ‘CLFLUSHOPT’      ‘CLFSH’
     ‘CLWB’            ‘CMOV’            ‘CMPXCHG16B’      ‘CX8’
     ‘ERMS’            ‘F16C’            ‘FMA’             ‘FMA4’
     ‘FPU’             ‘FSGSBASE’        ‘FSRM’            ‘FXSR’
     ‘GFNI’            ‘HLE’             ‘LAHF64_SAHF64’   ‘LZCNT’
     ‘MOVBE’           ‘MOVDIRI’         ‘MOVDIR64B’       ‘MSR’
     ‘OSXSAVE’         ‘PCLMULQDQ’       ‘POPCNT’          ‘PREFETCHW’
     ‘PREFETCHWT1’     ‘RDPID’           ‘RDRAND’          ‘RDSEED’
     ‘RDTSCP’          ‘RTM’             ‘SEP’             ‘SHA’
     ‘SSE’             ‘SSE2’            ‘SSE3’            ‘SSE4_1’
     ‘SSE4_2’          ‘SSE4A’           ‘SSSE3’           ‘SYSCALL_SYSRET’
     ‘TBM’             ‘TSC’             ‘VAES’            ‘VPCLMULQDQ’
     ‘XOP’             ‘XSAVE’

If CPU_FEATURE_USABLE(XXX) is true, XXX can be used.

HAS_CPU_FEATURE is defined since it provides useful information.
  

Patch

diff --git a/NEWS b/NEWS
index 53d7bd09b3..5673425f26 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,9 @@  Version 2.29
 
 Major new features:
 
+* Add <sys/platform/x86.h> to provide an API to access x86 specific
+  platform features.
+
 * A new convenience target has been added for distribution maintainers
   to build and install all locales as directories with files.  The new
   target is run by issuing the following command in your build tree:
diff --git a/manual/platform.texi b/manual/platform.texi
index 504addc956..1e690ee707 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,491 @@  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 are declared in @file{<sys/platform/x86.h>}.
+
+@deftypefun {const struct cpuid_registers *} x86_get_cpuid_registers (unsigned int)
+
+Internal function used by @code{HAS_CPU_FEATURE}.
+@end deftypefun
+
+@deftypefun {unsigned int} x86_get_arch_feature (unsigned int)
+
+Internal function used by @code{HAS_ARCH_FEATURE}.
+@end deftypefun
+
+@defmac HAS_CPU_FEATURE(name)
+
+Evaluate to true if the CPU feature @code{name} is supported as indicated
+by @code{CPUID} instruction.  The available 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{AESNI} -- The AESNI instruction extensions.
+
+@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_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_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{CX8} -- CMPXCHG8B instruction.
+
+@item
+@code{DCA} -- Data prefetch from a memory mapped device.
+
+@item
+@code{DE} -- Debugging Extensions.
+
+@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{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{IBT} -- Intel Indirect Branch Tracking instruction extensions.
+
+@item
+@code{INVPCID} -- INVPCID instruction.
+
+@item
+@code{LAHF64_SAHF64} -- LAHF/SAHF available in 64-bit mode.
+
+@item
+@code{LZCNT} -- LZCNT instruction.
+
+@item
+@code{LM} -- Long mode.
+
+@item
+@code{LWP} -- Lightweight profiling.
+
+@item
+@code{MCA} -- Machine Check Architecture.
+
+@item
+@code{MCE} -- Machine Check Exception.
+
+@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{PKU} -- Protection keys for user-mode pages.
+
+@item
+@code{POPCNT} -- POPCNT instruction.
+
+@item
+@code{PQM} -- Platform Quality of Service Monitoring.
+
+@item
+@code{PQE} -- Platform Quality of Service Enforcement.
+
+@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{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{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{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{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{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{X2APIC} -- x2APIC.
+
+@item
+@code{XOP} -- XOP instruction extensions.
+
+@item
+@code{XSAVE} -- The XSAVE/XRSTOR processor extended states feature, the
+XSETBV/XGETBV instructions, and XCR0.
+
+@item
+@code{XTPRUPDCTRL} -- xTPR Update Control.
+
+@end itemize
+@end defmac
+
+Please note that some CPU features require kernel support.
+@code{HAS_ARCH_FEATURE} should be used to determine if a feature is
+usable.
+
+@defmac HAS_ARCH_FEATURE(name)
+
+Evaluate to true if the architecture feature @code{name} is supported.
+The available features are:
+
+@itemize @bullet
+
+@item
+@code{AVX_Usable} -- AVX is usable.
+
+@item
+@code{AVX2_Usable} --  AVX2 is usable.
+
+@item
+@code{AVX512F_Usable} -- AVX512F is usable.
+
+@item
+@code{AVX512CD_Usable} -- AVX512CD is usable.
+
+@item
+@code{AVX512ER_Usable} -- AVX512ER is usable.
+
+@item
+@code{AVX512PF_Usable} -- AVX512PF is usable.
+
+@item
+@code{AVX512VL_Usable} -- AVX512VL is usable.
+
+@item
+@code{AVX512DQ_Usable} -- AVX512DQ is usable.
+
+@item
+@code{AVX512BW_Usable} -- AVX512BW is usable.
+
+@item
+@code{AVX512_4FMAPS_Usable} -- AVX512_4FMAPS is usable.
+
+@item
+@code{AVX512_4VNNIW_Usable} -- AVX512_4VNNIW is usable.
+
+@item
+@code{AVX512_BITALG_Usable} -- AVX512_BITALG is usable.
+
+@item
+@code{AVX512_IFMA_Usable} -- AVX512_IFMA is usable.
+
+@item
+@code{AVX512_VBMI_Usable} -- AVX512_VBMI is usable.
+
+@item
+@code{AVX512_VBMI2_Usable} -- AVX512_VBMI2 is usable.
+
+@item
+@code{AVX512_VNNI_Usable} -- AVX512_VNNI is usable.
+
+@item
+@code{FMA_Usable} -- FMA is usable.
+
+@item
+@code{FMA4_Usable} -- FMA4 is usable.
+
+@item
+@code{GFNI_Usable} -- GFNI is usable.
+
+@item
+@code{VAES_Usable} -- VAES is usable.
+
+@item
+@code{VPCLMULQDQ_Usable} -- VPCLMULQDQ is usable.
+
+@item
+@code{XSAVEC_Usable} -- XSAVEC is usable.
+
+@end itemize
+
+@end defmac
diff --git a/sysdeps/mach/hurd/i386/ld.abilist b/sysdeps/mach/hurd/i386/ld.abilist
index c76b913486..7dcd88f057 100644
--- a/sysdeps/mach/hurd/i386/ld.abilist
+++ b/sysdeps/mach/hurd/i386/ld.abilist
@@ -20,6 +20,8 @@  GLIBC_2.2.6 calloc F
 GLIBC_2.2.6 free F
 GLIBC_2.2.6 malloc F
 GLIBC_2.2.6 realloc F
+GLIBC_2.29 x86_get_arch_feature F
+GLIBC_2.29 x86_get_cpuid_registers F
 GLIBC_2.3 ___tls_get_addr F
 GLIBC_2.3 __tls_get_addr F
 GLIBC_2.4 __stack_chk_guard D 0x4
diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
index edb7307228..2fe33d2b79 100644
--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
+++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
@@ -5,5 +5,7 @@  GLIBC_2.0 malloc F
 GLIBC_2.0 realloc F
 GLIBC_2.1 __libc_stack_end D 0x4
 GLIBC_2.1 _dl_mcount F
+GLIBC_2.29 x86_get_arch_feature F
+GLIBC_2.29 x86_get_cpuid_registers F
 GLIBC_2.3 ___tls_get_addr F
 GLIBC_2.3 __tls_get_addr F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
index 0dc9430611..123041c02d 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
@@ -5,4 +5,6 @@  GLIBC_2.2.5 calloc F
 GLIBC_2.2.5 free F
 GLIBC_2.2.5 malloc F
 GLIBC_2.2.5 realloc F
+GLIBC_2.29 x86_get_arch_feature F
+GLIBC_2.29 x86_get_cpuid_registers F
 GLIBC_2.3 __tls_get_addr F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
index 80f3161586..f0292a199d 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
@@ -6,3 +6,5 @@  GLIBC_2.16 calloc F
 GLIBC_2.16 free F
 GLIBC_2.16 malloc F
 GLIBC_2.16 realloc F
+GLIBC_2.29 x86_get_arch_feature F
+GLIBC_2.29 x86_get_cpuid_registers F
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index f2fd031ac7..272d8f0b89 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -5,8 +5,21 @@  endif
 ifeq ($(subdir),elf)
 sysdep-dl-routines += dl-get-cpu-features
 
-tests += tst-get-cpu-features tst-get-cpu-features-static
-tests-static += tst-get-cpu-features-static
+tests += tst-get-cpu-features tst-get-cpu-features-static \
+	 tst-x86-platform-1 tst-x86-platform-1-static \
+	 tst-x86-platform-2 tst-x86-platform-3
+modules-names += tst-x86-platform-mod-2 tst-x86-platform-mod-3
+tests-static += tst-get-cpu-features-static tst-x86-platform-1-static
+
+$(objpfx)tst-x86-platform-mod-2.so: $(libsupport)
+$(objpfx)tst-x86-platform-2: $(objpfx)tst-x86-platform-mod-2.so
+LDFLAGS-tst-x86-platform-mod-3.so = -Wl,-z,now
+$(objpfx)tst-x86-platform-mod-3.so: $(libsupport)
+$(objpfx)tst-x86-platform-3: $(objpfx)tst-x86-platform-mod-3.so
+endif
+
+ifeq ($(subdir),misc)
+sysdep_headers += sys/platform/x86.h
 endif
 
 ifeq ($(subdir),setjmp)
diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions
index e02923708e..92ab4d93a3 100644
--- a/sysdeps/x86/Versions
+++ b/sysdeps/x86/Versions
@@ -1,4 +1,7 @@ 
 ld {
+  GLIBC_2.29 {
+    x86_get_cpuid_registers; x86_get_arch_feature;
+  }
   GLIBC_PRIVATE {
     __get_cpu_features;
   }
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
index f4e0f5a2ed..9af0560de1 100644
--- a/sysdeps/x86/cpu-features.c
+++ b/sysdeps/x86/cpu-features.c
@@ -130,10 +130,70 @@  get_common_indices (struct cpu_features *cpu_features,
 		{
 		  cpu_features->feature[index_arch_AVX512F_Usable]
 		    |= bit_arch_AVX512F_Usable;
+		  /* Determine if AVX512CD is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512CD))
+		    cpu_features->feature[index_arch_AVX512CD_Usable]
+		      |= bit_arch_AVX512CD_Usable;
+		  /* Determine if AVX512ER is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512ER))
+		    cpu_features->feature[index_arch_AVX512ER_Usable]
+		      |= bit_arch_AVX512ER_Usable;
+		  /* Determine if AVX512PF is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512PF))
+		    cpu_features->feature[index_arch_AVX512PF_Usable]
+		      |= bit_arch_AVX512PF_Usable;
+		  /* Determine if AVX512VL is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512VL))
+		    cpu_features->feature[index_arch_AVX512VL_Usable]
+		      |= bit_arch_AVX512VL_Usable;
 		  /* Determine if AVX512DQ is usable.  */
 		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512DQ))
 		    cpu_features->feature[index_arch_AVX512DQ_Usable]
 		      |= bit_arch_AVX512DQ_Usable;
+		  /* Determine if AVX512BW is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512BW))
+		    cpu_features->feature[index_arch_AVX512BW_Usable]
+		      |= bit_arch_AVX512BW_Usable;
+		  /* Determine if AVX512_4FMAPS is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_4FMAPS))
+		    cpu_features->feature[index_arch_AVX512_4FMAPS_Usable]
+		      |= bit_arch_AVX512_4FMAPS_Usable;
+		  /* Determine if AVX512_4VNNIW is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_4VNNIW))
+		    cpu_features->feature[index_arch_AVX512_4VNNIW_Usable]
+		      |= bit_arch_AVX512_4VNNIW_Usable;
+		  /* Determine if AVX512_BITALG is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_BITALG))
+		    cpu_features->feature[index_arch_AVX512_BITALG_Usable]
+		      |= bit_arch_AVX512_BITALG_Usable;
+		  /* Determine if AVX512_IFMA is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_IFMA))
+		    cpu_features->feature[index_arch_AVX512_IFMA_Usable]
+		      |= bit_arch_AVX512_IFMA_Usable;
+		  /* Determine if AVX512_VBMI is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VBMI))
+		    cpu_features->feature[index_arch_AVX512_VBMI_Usable]
+		      |= bit_arch_AVX512_VBMI_Usable;
+		  /* Determine if AVX512_VBMI2 is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VBMI2))
+		    cpu_features->feature[index_arch_AVX512_VBMI2_Usable]
+		      |= bit_arch_AVX512_VBMI2_Usable;
+		  /* Determine if is AVX512_VNNI usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VNNI))
+		    cpu_features->feature[index_arch_AVX512_VNNI_Usable]
+		      |= bit_arch_AVX512_VNNI_Usable;
+		  /* Determine if is GFNI is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, GFNI))
+		    cpu_features->feature[index_arch_GFNI_Usable]
+		      |= bit_arch_GFNI_Usable;
+		  /* Determine if VAES is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, VAES))
+		    cpu_features->feature[index_arch_VAES_Usable]
+		      |= bit_arch_VAES_Usable;
+		  /* Determine if VPCLMULQDQ is usable.  */
+		  if (CPU_FEATURES_CPU_P (cpu_features, VPCLMULQDQ))
+		    cpu_features->feature[index_arch_VPCLMULQDQ_Usable]
+		      |= bit_arch_VPCLMULQDQ_Usable;
 		}
 	    }
 	}
@@ -210,6 +270,18 @@  get_common_indices (struct cpu_features *cpu_features,
     }
 }
 
+_Static_assert (((index_arch_Fast_Unaligned_Load
+		  == index_arch_Fast_Unaligned_Copy)
+		 && (index_arch_Fast_Unaligned_Load
+		     == index_arch_Prefer_PMINUB_for_stringop)
+		 && (index_arch_Fast_Unaligned_Load
+		     == index_arch_Slow_SSE4_2)
+		 && (index_arch_Fast_Unaligned_Load
+		     == index_arch_Fast_Rep_String)
+		 && (index_arch_Fast_Unaligned_Load
+		     == index_arch_Fast_Copy_Backward)),
+		"Incorrect index_arch_Fast_Unaligned_Load");
+
 static inline void
 init_cpu_features (struct cpu_features *cpu_features)
 {
@@ -270,15 +342,6 @@  init_cpu_features (struct cpu_features *cpu_features)
 	    case 0x5d:
 	      /* Unaligned load versions are faster than SSSE3
 		 on Silvermont.  */
-#if index_arch_Fast_Unaligned_Load != index_arch_Prefer_PMINUB_for_stringop
-# error index_arch_Fast_Unaligned_Load != index_arch_Prefer_PMINUB_for_stringop
-#endif
-#if index_arch_Fast_Unaligned_Load != index_arch_Slow_SSE4_2
-# error index_arch_Fast_Unaligned_Load != index_arch_Slow_SSE4_2
-#endif
-#if index_arch_Fast_Unaligned_Load != index_arch_Fast_Unaligned_Copy
-# error index_arch_Fast_Unaligned_Load != index_arch_Fast_Unaligned_Copy
-#endif
 	      cpu_features->feature[index_arch_Fast_Unaligned_Load]
 		|= (bit_arch_Fast_Unaligned_Load
 		    | bit_arch_Fast_Unaligned_Copy
@@ -301,15 +364,6 @@  init_cpu_features (struct cpu_features *cpu_features)
 	    case 0x2f:
 	      /* Rep string instructions, unaligned load, unaligned copy,
 		 and pminub are fast on Intel Core i3, i5 and i7.  */
-#if index_arch_Fast_Rep_String != index_arch_Fast_Unaligned_Load
-# error index_arch_Fast_Rep_String != index_arch_Fast_Unaligned_Load
-#endif
-#if index_arch_Fast_Rep_String != index_arch_Prefer_PMINUB_for_stringop
-# error index_arch_Fast_Rep_String != index_arch_Prefer_PMINUB_for_stringop
-#endif
-#if index_arch_Fast_Rep_String != index_arch_Fast_Unaligned_Copy
-# error index_arch_Fast_Rep_String != index_arch_Fast_Unaligned_Copy
-#endif
 	      cpu_features->feature[index_arch_Fast_Rep_String]
 		|= (bit_arch_Fast_Rep_String
 		    | bit_arch_Fast_Unaligned_Load
@@ -369,9 +423,6 @@  init_cpu_features (struct cpu_features *cpu_features)
 
       if (family == 0x15)
 	{
-#if index_arch_Fast_Unaligned_Load != index_arch_Fast_Copy_Backward
-# error index_arch_Fast_Unaligned_Load != index_arch_Fast_Copy_Backward
-#endif
 	  /* "Excavator"   */
 	  if (model >= 0x60 && model <= 0x7f)
 	  {
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h
index d342664c64..8c0876c518 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/cpu-features.h
@@ -18,106 +18,63 @@ 
 #ifndef cpu_features_h
 #define cpu_features_h
 
-#define bit_arch_Fast_Rep_String		(1 << 0)
-#define bit_arch_Fast_Copy_Backward		(1 << 1)
-#define bit_arch_Slow_BSF			(1 << 2)
-#define bit_arch_Fast_Unaligned_Load		(1 << 4)
-#define bit_arch_Prefer_PMINUB_for_stringop	(1 << 5)
-#define bit_arch_AVX_Usable			(1 << 6)
-#define bit_arch_FMA_Usable			(1 << 7)
-#define bit_arch_FMA4_Usable			(1 << 8)
-#define bit_arch_Slow_SSE4_2			(1 << 9)
-#define bit_arch_AVX2_Usable			(1 << 10)
-#define bit_arch_AVX_Fast_Unaligned_Load	(1 << 11)
-#define bit_arch_AVX512F_Usable			(1 << 12)
-#define bit_arch_AVX512DQ_Usable		(1 << 13)
-#define bit_arch_I586				(1 << 14)
-#define bit_arch_I686				(1 << 15)
-#define bit_arch_Prefer_MAP_32BIT_EXEC		(1 << 16)
-#define bit_arch_Prefer_No_VZEROUPPER		(1 << 17)
-#define bit_arch_Fast_Unaligned_Copy		(1 << 18)
-#define bit_arch_Prefer_ERMS			(1 << 19)
-#define bit_arch_Prefer_No_AVX512		(1 << 20)
-#define bit_arch_MathVec_Prefer_No_AVX512	(1 << 21)
-#define bit_arch_XSAVEC_Usable			(1 << 22)
-#define bit_arch_Prefer_FSRM			(1 << 23)
-
-/* CPUID Feature flags.  */
-
-/* COMMON_CPUID_INDEX_1.  */
-#define bit_cpu_CX8		(1 << 8)
-#define bit_cpu_CMOV		(1 << 15)
-#define bit_cpu_SSE		(1 << 25)
-#define bit_cpu_SSE2		(1 << 26)
-#define bit_cpu_SSSE3		(1 << 9)
-#define bit_cpu_SSE4_1		(1 << 19)
-#define bit_cpu_SSE4_2		(1 << 20)
-#define bit_cpu_OSXSAVE		(1 << 27)
-#define bit_cpu_AVX		(1 << 28)
-#define bit_cpu_POPCOUNT	(1 << 23)
-#define bit_cpu_FMA		(1 << 12)
-#define bit_cpu_FMA4		(1 << 16)
-#define bit_cpu_HTT		(1 << 28)
-#define bit_cpu_LZCNT		(1 << 5)
-#define bit_cpu_MOVBE		(1 << 22)
-#define bit_cpu_POPCNT		(1 << 23)
-
-/* COMMON_CPUID_INDEX_7.  */
-#define bit_cpu_BMI1		(1 << 3)
-#define bit_cpu_BMI2		(1 << 8)
-#define bit_cpu_ERMS		(1 << 9)
-#define bit_cpu_RTM		(1 << 11)
-#define bit_cpu_AVX2		(1 << 5)
-#define bit_cpu_AVX512F		(1 << 16)
-#define bit_cpu_AVX512DQ	(1 << 17)
-#define bit_cpu_AVX512PF	(1 << 26)
-#define bit_cpu_AVX512ER	(1 << 27)
-#define bit_cpu_AVX512CD	(1 << 28)
-#define bit_cpu_AVX512BW	(1 << 30)
-#define bit_cpu_AVX512VL	(1u << 31)
-#define bit_cpu_IBT		(1u << 20)
-#define bit_cpu_SHSTK		(1u << 7)
-#define bit_cpu_FSRM		(1 << 4)
+#include <sys/platform/x86.h>
+
+/* 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		FEATURE_INDEX_2
+#define index_arch_Fast_Copy_Backward		FEATURE_INDEX_2
+#define index_arch_Slow_BSF			FEATURE_INDEX_2
+#define index_arch_Fast_Unaligned_Load		FEATURE_INDEX_2
+#define index_arch_Prefer_PMINUB_for_stringop 	FEATURE_INDEX_2
+#define index_arch_Fast_Unaligned_Copy		FEATURE_INDEX_2
+#define index_arch_I586				FEATURE_INDEX_2
+#define index_arch_I686				FEATURE_INDEX_2
+#define index_arch_Slow_SSE4_2			FEATURE_INDEX_2
+#define index_arch_AVX_Fast_Unaligned_Load	FEATURE_INDEX_2
+#define index_arch_Prefer_MAP_32BIT_EXEC	FEATURE_INDEX_2
+#define index_arch_Prefer_No_VZEROUPPER		FEATURE_INDEX_2
+#define index_arch_Prefer_ERMS			FEATURE_INDEX_2
+#define index_arch_Prefer_No_AVX512		FEATURE_INDEX_2
+#define index_arch_MathVec_Prefer_No_AVX512	FEATURE_INDEX_2
+#define index_arch_Prefer_FSRM			FEATURE_INDEX_2
 
 /* XCR0 Feature flags.  */
-#define bit_XMM_state		(1 << 1)
-#define bit_YMM_state		(1 << 2)
-#define bit_Opmask_state	(1 << 5)
-#define bit_ZMM0_15_state	(1 << 6)
-#define bit_ZMM16_31_state	(1 << 7)
+#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)
 
-/* The integer bit array index for the first set of internal feature bits.  */
-#define FEATURE_INDEX_1 0
-
-/* The current maximum size of the feature integer bit array.  */
-#define FEATURE_INDEX_MAX 1
-
-enum
+enum cpu_features_kind
   {
-    COMMON_CPUID_INDEX_1 = 0,
-    COMMON_CPUID_INDEX_7,
-    COMMON_CPUID_INDEX_80000001,
-    /* Keep the following line at the end.  */
-    COMMON_CPUID_INDEX_MAX
+    arch_kind_unknown = 0,
+    arch_kind_intel,
+    arch_kind_amd,
+    arch_kind_other
   };
 
 struct cpu_features
 {
-  enum cpu_features_kind
-    {
-      arch_kind_unknown = 0,
-      arch_kind_intel,
-      arch_kind_amd,
-      arch_kind_other
-    } kind;
+  enum cpu_features_kind kind;
   int max_cpuid;
-  struct cpuid_registers
-  {
-    unsigned int eax;
-    unsigned int ebx;
-    unsigned int ecx;
-    unsigned int edx;
-  } cpuid[COMMON_CPUID_INDEX_MAX];
+  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
   unsigned int family;
   unsigned int model;
   /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
@@ -148,112 +105,21 @@  struct cpu_features
 extern const struct cpu_features *__get_cpu_features (void)
      __attribute__ ((const));
 
-# if defined (_LIBC) && !IS_IN (nonlib)
-/* Unused for x86.  */
-#  define INIT_ARCH()
-#  define __get_cpu_features()	(&GLRO(dl_x86_cpu_features))
-# endif
-
-
 /* Only used directly in cpu-features.c.  */
 # define CPU_FEATURES_CPU_P(ptr, name) \
   ((ptr->cpuid[index_cpu_##name].reg_##name & (bit_cpu_##name)) != 0)
 # define CPU_FEATURES_ARCH_P(ptr, name) \
   ((ptr->feature[index_arch_##name] & (bit_arch_##name)) != 0)
 
-/* HAS_* evaluates to true if we may use the feature at runtime.  */
-# define HAS_CPU_FEATURE(name) \
-   CPU_FEATURES_CPU_P (__get_cpu_features (), name)
-# define HAS_ARCH_FEATURE(name) \
-   CPU_FEATURES_ARCH_P (__get_cpu_features (), name)
-
-# define index_cpu_CX8		COMMON_CPUID_INDEX_1
-# define index_cpu_CMOV		COMMON_CPUID_INDEX_1
-# define index_cpu_SSE		COMMON_CPUID_INDEX_1
-# define index_cpu_SSE2		COMMON_CPUID_INDEX_1
-# define index_cpu_SSSE3	COMMON_CPUID_INDEX_1
-# define index_cpu_SSE4_1	COMMON_CPUID_INDEX_1
-# define index_cpu_SSE4_2	COMMON_CPUID_INDEX_1
-# define index_cpu_AVX		COMMON_CPUID_INDEX_1
-# define index_cpu_AVX2		COMMON_CPUID_INDEX_7
-# define index_cpu_AVX512F	COMMON_CPUID_INDEX_7
-# define index_cpu_AVX512DQ	COMMON_CPUID_INDEX_7
-# define index_cpu_AVX512PF	COMMON_CPUID_INDEX_7
-# define index_cpu_AVX512ER	COMMON_CPUID_INDEX_7
-# define index_cpu_AVX512CD	COMMON_CPUID_INDEX_7
-# define index_cpu_AVX512BW	COMMON_CPUID_INDEX_7
-# define index_cpu_AVX512VL	COMMON_CPUID_INDEX_7
-# define index_cpu_ERMS		COMMON_CPUID_INDEX_7
-# define index_cpu_RTM		COMMON_CPUID_INDEX_7
-# define index_cpu_FMA		COMMON_CPUID_INDEX_1
-# define index_cpu_FMA4		COMMON_CPUID_INDEX_80000001
-# define index_cpu_POPCOUNT	COMMON_CPUID_INDEX_1
-# define index_cpu_OSXSAVE	COMMON_CPUID_INDEX_1
-# define index_cpu_HTT		COMMON_CPUID_INDEX_1
-# define index_cpu_BMI1		COMMON_CPUID_INDEX_7
-# define index_cpu_BMI2		COMMON_CPUID_INDEX_7
-# define index_cpu_LZCNT	COMMON_CPUID_INDEX_80000001
-# define index_cpu_MOVBE	COMMON_CPUID_INDEX_1
-# define index_cpu_POPCNT	COMMON_CPUID_INDEX_1
-# define index_cpu_IBT		COMMON_CPUID_INDEX_7
-# define index_cpu_SHSTK	COMMON_CPUID_INDEX_7
-# define index_cpu_FSRM		COMMON_CPUID_INDEX_7
-
-# define reg_CX8		edx
-# define reg_CMOV		edx
-# define reg_SSE		edx
-# define reg_SSE2		edx
-# define reg_SSSE3		ecx
-# define reg_SSE4_1		ecx
-# define reg_SSE4_2		ecx
-# define reg_AVX		ecx
-# define reg_AVX2		ebx
-# define reg_AVX512F		ebx
-# define reg_AVX512DQ		ebx
-# define reg_AVX512PF		ebx
-# define reg_AVX512ER		ebx
-# define reg_AVX512CD		ebx
-# define reg_AVX512BW		ebx
-# define reg_AVX512VL		ebx
-# define reg_ERMS		ebx
-# define reg_RTM		ebx
-# define reg_FMA		ecx
-# define reg_FMA4		ecx
-# define reg_POPCOUNT		ecx
-# define reg_OSXSAVE		ecx
-# define reg_HTT		edx
-# define reg_BMI1		ebx
-# define reg_BMI2		ebx
-# define reg_LZCNT		ecx
-# define reg_MOVBE		ecx
-# define reg_POPCNT		ecx
-# define reg_IBT		edx
-# define reg_SHSTK		ecx
-# define reg_FSRM		edx
-
-# define index_arch_Fast_Rep_String	FEATURE_INDEX_1
-# define index_arch_Fast_Copy_Backward	FEATURE_INDEX_1
-# define index_arch_Slow_BSF		FEATURE_INDEX_1
-# define index_arch_Fast_Unaligned_Load	FEATURE_INDEX_1
-# define index_arch_Prefer_PMINUB_for_stringop FEATURE_INDEX_1
-# define index_arch_AVX_Usable		FEATURE_INDEX_1
-# define index_arch_FMA_Usable		FEATURE_INDEX_1
-# define index_arch_FMA4_Usable		FEATURE_INDEX_1
-# define index_arch_Slow_SSE4_2		FEATURE_INDEX_1
-# define index_arch_AVX2_Usable		FEATURE_INDEX_1
-# define index_arch_AVX_Fast_Unaligned_Load FEATURE_INDEX_1
-# define index_arch_AVX512F_Usable	FEATURE_INDEX_1
-# define index_arch_AVX512DQ_Usable	FEATURE_INDEX_1
-# define index_arch_I586		FEATURE_INDEX_1
-# define index_arch_I686		FEATURE_INDEX_1
-# define index_arch_Prefer_MAP_32BIT_EXEC FEATURE_INDEX_1
-# define index_arch_Prefer_No_VZEROUPPER FEATURE_INDEX_1
-# define index_arch_Fast_Unaligned_Copy	FEATURE_INDEX_1
-# define index_arch_Prefer_ERMS		FEATURE_INDEX_1
-# define index_arch_Prefer_No_AVX512	FEATURE_INDEX_1
-# define index_arch_MathVec_Prefer_No_AVX512 FEATURE_INDEX_1
-# define index_arch_XSAVEC_Usable	FEATURE_INDEX_1
-# define index_arch_Prefer_FSRM		FEATURE_INDEX_1
+# if defined (_LIBC) && !IS_IN (nonlib)
+/* Unused for x86.  */
+#  define INIT_ARCH()
+#  define __get_cpu_features()	(&GLRO(dl_x86_cpu_features))
+#  define x86_get_cpuid_registers(i) \
+       (&(GLRO(dl_x86_cpu_features).cpuid[i]))
+#  define x86_get_arch_feature(i) \
+       GLRO(dl_x86_cpu_features).feature[i]
+# endif
 
 #ifdef __x86_64__
 # define HAS_CPUID 1
diff --git a/sysdeps/x86/dl-get-cpu-features.c b/sysdeps/x86/dl-get-cpu-features.c
index 49593f19c6..9421376d6c 100644
--- a/sysdeps/x86/dl-get-cpu-features.c
+++ b/sysdeps/x86/dl-get-cpu-features.c
@@ -19,9 +19,28 @@ 
 #include <ldsodefs.h>
 
 #undef __get_cpu_features
+#undef x86_get_cpuid_registers
+#undef x86_get_arch_feature
 
 const struct cpu_features *
 __get_cpu_features (void)
 {
   return &GLRO(dl_x86_cpu_features);
 }
+
+const struct cpuid_registers *
+x86_get_cpuid_registers (unsigned int i)
+{
+  const static struct cpuid_registers zero_cpuid_registers = { 0 };
+  if (i >= COMMON_CPUID_INDEX_MAX)
+    return &zero_cpuid_registers;
+  return &GLRO(dl_x86_cpu_features).cpuid[i];
+}
+
+unsigned int
+x86_get_arch_feature (unsigned int i)
+{
+  if (i >= COMMON_CPUID_INDEX_MAX)
+    return 0;
+  return GLRO(dl_x86_cpu_features).feature[i];
+}
diff --git a/sysdeps/x86/sys/platform/x86.h b/sysdeps/x86/sys/platform/x86.h
new file mode 100644
index 0000000000..d03a367cae
--- /dev/null
+++ b/sysdeps/x86/sys/platform/x86.h
@@ -0,0 +1,557 @@ 
+/* Facilities specific to the x86 architecture.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_PLATFORM_X86_H
+#define _SYS_PLATFORM_X86_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+enum
+  {
+    /* The integer bit array index for the first set of internal feature
+       bits.  */
+    FEATURE_INDEX_1 = 0,
+    FEATURE_INDEX_2,
+    /* The current maximum size of the feature integer bit array.  */
+    FEATURE_INDEX_MAX
+  };
+
+enum
+  {
+    COMMON_CPUID_INDEX_1 = 0,
+    COMMON_CPUID_INDEX_7,
+    COMMON_CPUID_INDEX_80000001,
+    /* Keep the following line at the end.  */
+    COMMON_CPUID_INDEX_MAX
+  };
+
+struct cpuid_registers
+  {
+    unsigned int eax;
+    unsigned int ebx;
+    unsigned int ecx;
+    unsigned int edx;
+  };
+
+extern const struct cpuid_registers *x86_get_cpuid_registers
+     (unsigned int) __attribute__ ((const));
+
+extern unsigned int x86_get_arch_feature (unsigned int)
+     __attribute__ ((const));
+
+/* HAS_* evaluates to true if CPU supports the feature.  */
+#define HAS_CPU_FEATURE(name) \
+   ((x86_get_cpuid_registers (index_cpu_##name)->reg_##name \
+     & (bit_cpu_##name)) != 0)
+#define HAS_ARCH_FEATURE(name) \
+   ((x86_get_arch_feature (index_arch_##name) & (bit_arch_##name)) != 0)
+
+/* Architecture features.  */
+
+/* FEATURE_INDEX_1.  */
+#define bit_arch_AVX_Usable			(1u << 0)
+#define bit_arch_AVX2_Usable			(1u << 1)
+#define bit_arch_AVX512F_Usable			(1u << 2)
+#define bit_arch_AVX512CD_Usable		(1u << 3)
+#define bit_arch_AVX512ER_Usable		(1u << 4)
+#define bit_arch_AVX512PF_Usable		(1u << 5)
+#define bit_arch_AVX512VL_Usable		(1u << 6)
+#define bit_arch_AVX512DQ_Usable		(1u << 7)
+#define bit_arch_AVX512BW_Usable		(1u << 8)
+#define bit_arch_AVX512_4FMAPS_Usable		(1u << 9)
+#define bit_arch_AVX512_4VNNIW_Usable		(1u << 10)
+#define bit_arch_AVX512_BITALG_Usable		(1u << 11)
+#define bit_arch_AVX512_IFMA_Usable		(1u << 12)
+#define bit_arch_AVX512_VBMI_Usable		(1u << 13)
+#define bit_arch_AVX512_VBMI2_Usable		(1u << 14)
+#define bit_arch_AVX512_VNNI_Usable		(1u << 15)
+#define bit_arch_FMA_Usable			(1u << 16)
+#define bit_arch_FMA4_Usable			(1u << 17)
+#define bit_arch_GFNI_Usable			(1u << 18)
+#define bit_arch_VAES_Usable			(1u << 19)
+#define bit_arch_VPCLMULQDQ_Usable		(1u << 20)
+#define bit_arch_XSAVEC_Usable			(1u << 21)
+
+#define index_arch_AVX_Usable			FEATURE_INDEX_1
+#define index_arch_AVX2_Usable			FEATURE_INDEX_1
+#define index_arch_AVX512F_Usable		FEATURE_INDEX_1
+#define index_arch_AVX512CD_Usable		FEATURE_INDEX_1
+#define index_arch_AVX512ER_Usable		FEATURE_INDEX_1
+#define index_arch_AVX512PF_Usable		FEATURE_INDEX_1
+#define index_arch_AVX512VL_Usable		FEATURE_INDEX_1
+#define index_arch_AVX512BW_Usable		FEATURE_INDEX_1
+#define index_arch_AVX512DQ_Usable		FEATURE_INDEX_1
+#define index_arch_AVX512_4FMAPS_Usable		FEATURE_INDEX_1
+#define index_arch_AVX512_4VNNIW_Usable		FEATURE_INDEX_1
+#define index_arch_AVX512_BITALG_Usable		FEATURE_INDEX_1
+#define index_arch_AVX512_IFMA_Usable		FEATURE_INDEX_1
+#define index_arch_AVX512_VBMI_Usable		FEATURE_INDEX_1
+#define index_arch_AVX512_VBMI2_Usable		FEATURE_INDEX_1
+#define index_arch_AVX512_VNNI_Usable		FEATURE_INDEX_1
+#define index_arch_FMA_Usable			FEATURE_INDEX_1
+#define index_arch_FMA4_Usable			FEATURE_INDEX_1
+#define index_arch_GFNI_Usable			FEATURE_INDEX_1
+#define index_arch_VAES_Usable			FEATURE_INDEX_1
+#define index_arch_VPCLMULQDQ_Usable		FEATURE_INDEX_1
+#define index_arch_XSAVEC_Usable		FEATURE_INDEX_1
+
+/* CPU features.  */
+
+/* COMMON_CPUID_INDEX_1.  */
+
+/* ECX.  */
+#define bit_cpu_SSE3		(1u << 0)
+#define bit_cpu_PCLMULQDQ	(1u << 1)
+#define bit_cpu_DTES64		(1u << 2)
+#define bit_cpu_MONITOR		(1u << 3)
+#define bit_cpu_DS_CPL		(1u << 4)
+#define bit_cpu_VMX		(1u << 5)
+#define bit_cpu_SMX		(1u << 6)
+#define bit_cpu_EST		(1u << 7)
+#define bit_cpu_TM2		(1u << 8)
+#define bit_cpu_SSSE3		(1u << 9)
+#define bit_cpu_CNXT_ID		(1u << 10)
+#define bit_cpu_SDBG		(1u << 11)
+#define bit_cpu_FMA		(1u << 12)
+#define bit_cpu_CMPXCHG16B	(1u << 13)
+#define bit_cpu_XTPRUPDCTRL	(1u << 14)
+#define bit_cpu_PDCM		(1u << 15)
+#define bit_cpu_PCID		(1u << 17)
+#define bit_cpu_DCA		(1u << 18)
+#define bit_cpu_SSE4_1		(1u << 19)
+#define bit_cpu_SSE4_2		(1u << 20)
+#define bit_cpu_X2APIC		(1u << 21)
+#define bit_cpu_MOVBE		(1u << 22)
+#define bit_cpu_POPCNT		(1u << 23)
+#define bit_cpu_TSC_DEADLINE	(1u << 24)
+#define bit_cpu_AES		(1u << 25)
+#define bit_cpu_XSAVE		(1u << 26)
+#define bit_cpu_OSXSAVE		(1u << 27)
+#define bit_cpu_AVX		(1u << 28)
+#define bit_cpu_F16C		(1u << 29)
+#define bit_cpu_RDRAND		(1u << 30)
+
+/* EDX.  */
+#define bit_cpu_FPU		(1u << 0)
+#define bit_cpu_VME		(1u << 1)
+#define bit_cpu_DE		(1u << 2)
+#define bit_cpu_PSE		(1u << 3)
+#define bit_cpu_TSC		(1u << 4)
+#define bit_cpu_MSR		(1u << 5)
+#define bit_cpu_PAE		(1u << 6)
+#define bit_cpu_MCE		(1u << 7)
+#define bit_cpu_CX8		(1u << 8)
+#define bit_cpu_APIC		(1u << 9)
+#define bit_cpu_SEP		(1u << 11)
+#define bit_cpu_MTRR		(1u << 12)
+#define bit_cpu_PGE		(1u << 13)
+#define bit_cpu_MCA		(1u << 14)
+#define bit_cpu_CMOV		(1u << 15)
+#define bit_cpu_PAT		(1u << 16)
+#define bit_cpu_PSE_36		(1u << 17)
+#define bit_cpu_PSN		(1u << 18)
+#define bit_cpu_CLFSH		(1u << 20)
+#define bit_cpu_DS		(1u << 21)
+#define bit_cpu_ACPI		(1u << 22)
+#define bit_cpu_MMX		(1u << 23)
+#define bit_cpu_FXSR		(1u << 24)
+#define bit_cpu_SSE		(1u << 25)
+#define bit_cpu_SSE2		(1u << 26)
+#define bit_cpu_SS		(1u << 27)
+#define bit_cpu_HTT		(1u << 28)
+#define bit_cpu_TM		(1u << 29)
+#define bit_cpu_PBE		(1u << 31)
+
+/* COMMON_CPUID_INDEX_7.  */
+
+/* EBX.  */
+#define bit_cpu_FSGSBASE	(1u << 0)
+#define bit_cpu_TSC_ADJUST	(1u << 1)
+#define bit_cpu_SGX		(1u << 2)
+#define bit_cpu_BMI1		(1u << 3)
+#define bit_cpu_HLE		(1u << 4)
+#define bit_cpu_AVX2		(1u << 5)
+#define bit_cpu_SMEP		(1u << 7)
+#define bit_cpu_BMI2		(1u << 8)
+#define bit_cpu_ERMS		(1u << 9)
+#define bit_cpu_INVPCID		(1u << 10)
+#define bit_cpu_RTM		(1u << 11)
+#define bit_cpu_PQM		(1u << 12)
+#define bit_cpu_MPX		(1u << 14)
+#define bit_cpu_PQE		(1u << 15)
+#define bit_cpu_AVX512F		(1u << 16)
+#define bit_cpu_AVX512DQ	(1u << 17)
+#define bit_cpu_RDSEED		(1u << 18)
+#define bit_cpu_ADX		(1u << 19)
+#define bit_cpu_SMAP		(1u << 20)
+#define bit_cpu_AVX512_IFMA	(1u << 21)
+#define bit_cpu_CLFLUSHOPT	(1u << 22)
+#define bit_cpu_CLWB		(1u << 24)
+#define bit_cpu_TRACE		(1u << 25)
+#define bit_cpu_AVX512PF	(1u << 26)
+#define bit_cpu_AVX512ER	(1u << 27)
+#define bit_cpu_AVX512CD	(1u << 28)
+#define bit_cpu_SHA		(1u << 29)
+#define bit_cpu_AVX512BW	(1u << 30)
+#define bit_cpu_AVX512VL	(1u << 31)
+
+/* ECX.  */
+#define bit_cpu_PREFETCHWT1	(1u << 0)
+#define bit_cpu_AVX512_VBMI	(1u << 1)
+#define bit_cpu_UMIP		(1u << 2)
+#define bit_cpu_PKU		(1u << 3)
+#define bit_cpu_OSPKE		(1u << 4)
+#define bit_cpu_WAITPKG		(1u << 5)
+#define bit_cpu_SHSTK		(1u << 7)
+#define bit_cpu_AVX512_VBMI2	(1u << 6)
+#define bit_cpu_GFNI		(1u << 8)
+#define bit_cpu_VAES		(1u << 9)
+#define bit_cpu_VPCLMULQDQ	(1u << 10)
+#define bit_cpu_AVX512_VNNI	(1u << 11)
+#define bit_cpu_AVX512_BITALG	(1u << 12)
+#define bit_cpu_AVX512_VPOPCNTDQ (1u << 14)
+#define bit_cpu_RDPID		(1u << 22)
+#define bit_cpu_CLDEMOTE	(1u << 25)
+#define bit_cpu_MOVDIRI		(1u << 27)
+#define bit_cpu_MOVDIR64B	(1u << 28)
+#define bit_cpu_SGX_LC		(1u << 30)
+
+/* EDX.  */
+#define bit_cpu_AVX512_4VNNIW	(1u << 2)
+#define bit_cpu_AVX512_4FMAPS	(1u << 3)
+#define bit_cpu_FSRM		(1u << 4)
+#define bit_cpu_PCONFIG		(1u << 18)
+#define bit_cpu_IBT		(1u << 20)
+
+/* COMMON_CPUID_INDEX_80000001.  */
+
+/* ECX.  */
+#define bit_cpu_LAHF64_SAHF64	(1u << 0)
+#define bit_cpu_SVM		(1u << 2)
+#define bit_cpu_LZCNT		(1u << 5)
+#define bit_cpu_SSE4A		(1u << 6)
+#define bit_cpu_PREFETCHW	(1u << 8)
+#define bit_cpu_XOP		(1u << 11)
+#define bit_cpu_LWP		(1u << 15)
+#define bit_cpu_FMA4		(1u << 16)
+#define bit_cpu_TBM		(1u << 21)
+
+/* EDX.  */
+#define bit_cpu_SYSCALL_SYSRET	(1u << 11)
+#define bit_cpu_NX		(1u << 20)
+#define bit_cpu_PAGE1GB		(1u << 26)
+#define bit_cpu_RDTSCP		(1u << 27)
+#define bit_cpu_LM		(1u << 29)
+
+/* COMMON_CPUID_INDEX_1.  */
+
+/* ECX.  */
+#define index_cpu_SSE3		COMMON_CPUID_INDEX_1
+#define index_cpu_PCLMULQDQ	COMMON_CPUID_INDEX_1
+#define index_cpu_DTES64	COMMON_CPUID_INDEX_1
+#define index_cpu_MONITOR	COMMON_CPUID_INDEX_1
+#define index_cpu_DS_CPL	COMMON_CPUID_INDEX_1
+#define index_cpu_VMX		COMMON_CPUID_INDEX_1
+#define index_cpu_SMX		COMMON_CPUID_INDEX_1
+#define index_cpu_EST		COMMON_CPUID_INDEX_1
+#define index_cpu_TM2		COMMON_CPUID_INDEX_1
+#define index_cpu_SSSE3		COMMON_CPUID_INDEX_1
+#define index_cpu_CNXT_ID	COMMON_CPUID_INDEX_1
+#define index_cpu_SDBG		COMMON_CPUID_INDEX_1
+#define index_cpu_FMA		COMMON_CPUID_INDEX_1
+#define index_cpu_CMPXCHG16B	COMMON_CPUID_INDEX_1
+#define index_cpu_XTPRUPDCTRL	COMMON_CPUID_INDEX_1
+#define index_cpu_PDCM		COMMON_CPUID_INDEX_1
+#define index_cpu_PCID		COMMON_CPUID_INDEX_1
+#define index_cpu_DCA		COMMON_CPUID_INDEX_1
+#define index_cpu_SSE4_1	COMMON_CPUID_INDEX_1
+#define index_cpu_SSE4_2	COMMON_CPUID_INDEX_1
+#define index_cpu_X2APIC	COMMON_CPUID_INDEX_1
+#define index_cpu_MOVBE		COMMON_CPUID_INDEX_1
+#define index_cpu_POPCNT	COMMON_CPUID_INDEX_1
+#define index_cpu_TSC_DEADLINE	COMMON_CPUID_INDEX_1
+#define index_cpu_AES		COMMON_CPUID_INDEX_1
+#define index_cpu_XSAVE		COMMON_CPUID_INDEX_1
+#define index_cpu_OSXSAVE	COMMON_CPUID_INDEX_1
+#define index_cpu_AVX		COMMON_CPUID_INDEX_1
+#define index_cpu_F16C		COMMON_CPUID_INDEX_1
+#define index_cpu_RDRAND	COMMON_CPUID_INDEX_1
+
+/* ECX.  */
+#define index_cpu_FPU		COMMON_CPUID_INDEX_1
+#define index_cpu_VME		COMMON_CPUID_INDEX_1
+#define index_cpu_DE		COMMON_CPUID_INDEX_1
+#define index_cpu_PSE		COMMON_CPUID_INDEX_1
+#define index_cpu_TSC		COMMON_CPUID_INDEX_1
+#define index_cpu_MSR		COMMON_CPUID_INDEX_1
+#define index_cpu_PAE		COMMON_CPUID_INDEX_1
+#define index_cpu_MCE		COMMON_CPUID_INDEX_1
+#define index_cpu_CX8		COMMON_CPUID_INDEX_1
+#define index_cpu_APIC		COMMON_CPUID_INDEX_1
+#define index_cpu_SEP		COMMON_CPUID_INDEX_1
+#define index_cpu_MTRR		COMMON_CPUID_INDEX_1
+#define index_cpu_PGE		COMMON_CPUID_INDEX_1
+#define index_cpu_MCA		COMMON_CPUID_INDEX_1
+#define index_cpu_CMOV		COMMON_CPUID_INDEX_1
+#define index_cpu_PAT		COMMON_CPUID_INDEX_1
+#define index_cpu_PSE_36	COMMON_CPUID_INDEX_1
+#define index_cpu_PSN		COMMON_CPUID_INDEX_1
+#define index_cpu_CLFSH		COMMON_CPUID_INDEX_1
+#define index_cpu_DS		COMMON_CPUID_INDEX_1
+#define index_cpu_ACPI		COMMON_CPUID_INDEX_1
+#define index_cpu_MMX		COMMON_CPUID_INDEX_1
+#define index_cpu_FXSR		COMMON_CPUID_INDEX_1
+#define index_cpu_SSE		COMMON_CPUID_INDEX_1
+#define index_cpu_SSE2		COMMON_CPUID_INDEX_1
+#define index_cpu_SS		COMMON_CPUID_INDEX_1
+#define index_cpu_HTT		COMMON_CPUID_INDEX_1
+#define index_cpu_TM		COMMON_CPUID_INDEX_1
+#define index_cpu_PBE		COMMON_CPUID_INDEX_1
+
+/* COMMON_CPUID_INDEX_7.  */
+
+/* EBX.  */
+#define index_cpu_FSGSBASE	COMMON_CPUID_INDEX_7
+#define index_cpu_TSC_ADJUST	COMMON_CPUID_INDEX_7
+#define index_cpu_SGX		COMMON_CPUID_INDEX_7
+#define index_cpu_BMI1		COMMON_CPUID_INDEX_7
+#define index_cpu_HLE		COMMON_CPUID_INDEX_7
+#define index_cpu_AVX2		COMMON_CPUID_INDEX_7
+#define index_cpu_SMEP		COMMON_CPUID_INDEX_7
+#define index_cpu_BMI2		COMMON_CPUID_INDEX_7
+#define index_cpu_ERMS		COMMON_CPUID_INDEX_7
+#define index_cpu_INVPCID	COMMON_CPUID_INDEX_7
+#define index_cpu_RTM		COMMON_CPUID_INDEX_7
+#define index_cpu_PQM		COMMON_CPUID_INDEX_7
+#define index_cpu_MPX		COMMON_CPUID_INDEX_7
+#define index_cpu_PQE		COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512F	COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512DQ	COMMON_CPUID_INDEX_7
+#define index_cpu_RDSEED	COMMON_CPUID_INDEX_7
+#define index_cpu_ADX		COMMON_CPUID_INDEX_7
+#define index_cpu_SMAP		COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512_IFMA	COMMON_CPUID_INDEX_7
+#define index_cpu_CLFLUSHOPT	COMMON_CPUID_INDEX_7
+#define index_cpu_CLWB		COMMON_CPUID_INDEX_7
+#define index_cpu_TRACE		COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512PF	COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512ER	COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512CD	COMMON_CPUID_INDEX_7
+#define index_cpu_SHA		COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512BW	COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512VL	COMMON_CPUID_INDEX_7
+
+/* ECX.  */
+#define index_cpu_PREFETCHWT1	COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512_VBMI	COMMON_CPUID_INDEX_7
+#define index_cpu_UMIP		COMMON_CPUID_INDEX_7
+#define index_cpu_PKU		COMMON_CPUID_INDEX_7
+#define index_cpu_OSPKE		COMMON_CPUID_INDEX_7
+#define index_cpu_WAITPKG	COMMON_CPUID_INDEX_7
+#define index_cpu_SHSTK		COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512_VBMI2	COMMON_CPUID_INDEX_7
+#define index_cpu_GFNI		COMMON_CPUID_INDEX_7
+#define index_cpu_VAES		COMMON_CPUID_INDEX_7
+#define index_cpu_VPCLMULQDQ	COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512_VNNI	COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512_BITALG COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512_VPOPCNTDQ COMMON_CPUID_INDEX_7
+#define index_cpu_RDPID		COMMON_CPUID_INDEX_7
+#define index_cpu_CLDEMOTE	COMMON_CPUID_INDEX_7
+#define index_cpu_MOVDIRI	COMMON_CPUID_INDEX_7
+#define index_cpu_MOVDIR64B	COMMON_CPUID_INDEX_7
+#define index_cpu_SGX_LC	COMMON_CPUID_INDEX_7
+
+/* EDX.  */
+#define index_cpu_AVX512_4VNNIW COMMON_CPUID_INDEX_7
+#define index_cpu_AVX512_4FMAPS	COMMON_CPUID_INDEX_7
+#define index_cpu_FSRM		COMMON_CPUID_INDEX_7
+#define index_cpu_PCONFIG	COMMON_CPUID_INDEX_7
+#define index_cpu_IBT		COMMON_CPUID_INDEX_7
+
+/* COMMON_CPUID_INDEX_80000001.  */
+
+/* ECX.  */
+#define index_cpu_LAHF64_SAHF64 COMMON_CPUID_INDEX_80000001
+#define index_cpu_SVM		COMMON_CPUID_INDEX_80000001
+#define index_cpu_LZCNT		COMMON_CPUID_INDEX_80000001
+#define index_cpu_SSE4A		COMMON_CPUID_INDEX_80000001
+#define index_cpu_PREFETCHW	COMMON_CPUID_INDEX_80000001
+#define index_cpu_XOP		COMMON_CPUID_INDEX_80000001
+#define index_cpu_LWP		COMMON_CPUID_INDEX_80000001
+#define index_cpu_FMA4		COMMON_CPUID_INDEX_80000001
+#define index_cpu_TBM		COMMON_CPUID_INDEX_80000001
+
+/* EDX.  */
+#define index_cpu_SYSCALL_SYSRET COMMON_CPUID_INDEX_80000001
+#define index_cpu_NX		COMMON_CPUID_INDEX_80000001
+#define index_cpu_PAGE1GB	COMMON_CPUID_INDEX_80000001
+#define index_cpu_RDTSCP	COMMON_CPUID_INDEX_80000001
+#define index_cpu_LM		COMMON_CPUID_INDEX_80000001
+
+/* COMMON_CPUID_INDEX_1.  */
+
+/* ECX.  */
+#define reg_SSE3		ecx
+#define reg_PCLMULQDQ		ecx
+#define reg_DTES64		ecx
+#define reg_MONITOR		ecx
+#define reg_DS_CPL		ecx
+#define reg_VMX			ecx
+#define reg_SMX			ecx
+#define reg_EST			ecx
+#define reg_TM2			ecx
+#define reg_SSSE3		ecx
+#define reg_CNXT_ID		ecx
+#define reg_SDBG		ecx
+#define reg_FMA			ecx
+#define reg_CMPXCHG16B		ecx
+#define reg_XTPRUPDCTRL		ecx
+#define reg_PDCM		ecx
+#define reg_PCID		ecx
+#define reg_DCA			ecx
+#define reg_SSE4_1		ecx
+#define reg_SSE4_2		ecx
+#define reg_X2APIC		ecx
+#define reg_MOVBE		ecx
+#define reg_POPCNT		ecx
+#define reg_TSC_DEADLINE	ecx
+#define reg_AES			ecx
+#define reg_XSAVE		ecx
+#define reg_OSXSAVE		ecx
+#define reg_AVX			ecx
+#define reg_F16C		ecx
+#define reg_RDRAND		ecx
+
+/* EDX.  */
+#define reg_FPU			edx
+#define reg_VME			edx
+#define reg_DE			edx
+#define reg_PSE			edx
+#define reg_TSC			edx
+#define reg_MSR			edx
+#define reg_PAE			edx
+#define reg_MCE			edx
+#define reg_CX8			edx
+#define reg_APIC		edx
+#define reg_SEP			edx
+#define reg_MTRR		edx
+#define reg_PGE			edx
+#define reg_MCA			edx
+#define reg_CMOV		edx
+#define reg_PAT			edx
+#define reg_PSE_36		edx
+#define reg_PSN			edx
+#define reg_CLFSH		edx
+#define reg_DS			edx
+#define reg_ACPI		edx
+#define reg_MMX			edx
+#define reg_FXSR		edx
+#define reg_SSE			edx
+#define reg_SSE2		edx
+#define reg_SS			edx
+#define reg_HTT			edx
+#define reg_TM			edx
+#define reg_PBE			edx
+
+/* COMMON_CPUID_INDEX_7.  */
+
+/* EBX.  */
+#define reg_FSGSBASE		ebx
+#define reg_TSC_ADJUST		ebx
+#define reg_SGX			ebx
+#define reg_BMI1		ebx
+#define reg_HLE			ebx
+#define reg_BMI2		ebx
+#define reg_AVX2		ebx
+#define reg_SMEP		ebx
+#define reg_ERMS		ebx
+#define reg_INVPCID		ebx
+#define reg_RTM			ebx
+#define reg_PQM			ebx
+#define reg_MPX			ebx
+#define reg_PQE			ebx
+#define reg_AVX512F		ebx
+#define reg_AVX512DQ		ebx
+#define reg_RDSEED		ebx
+#define reg_ADX			ebx
+#define reg_SMAP		ebx
+#define reg_AVX512_IFMA		ebx
+#define reg_CLFLUSHOPT		ebx
+#define reg_CLWB		ebx
+#define reg_TRACE		ebx
+#define reg_AVX512PF		ebx
+#define reg_AVX512ER		ebx
+#define reg_AVX512CD		ebx
+#define reg_SHA			ebx
+#define reg_AVX512BW		ebx
+#define reg_AVX512VL		ebx
+
+/* ECX.  */
+#define reg_PREFETCHWT1		ecx
+#define reg_AVX512_VBMI		ecx
+#define reg_UMIP		ecx
+#define reg_PKU			ecx
+#define reg_OSPKE		ecx
+#define reg_WAITPKG		ecx
+#define reg_SHSTK		ecx
+#define reg_AVX512_VBMI2	ecx
+#define reg_GFNI		ecx
+#define reg_VAES		ecx
+#define reg_VPCLMULQDQ		ecx
+#define reg_AVX512_VNNI		ecx
+#define reg_AVX512_BITALG	ecx
+#define reg_AVX512_VPOPCNTDQ	ecx
+#define reg_RDPID		ecx
+#define reg_CLDEMOTE		ecx
+#define reg_MOVDIRI		ecx
+#define reg_MOVDIR64B		ecx
+#define reg_SGX_LC		ecx
+
+/* EDX.  */
+#define reg_AVX512_4VNNIW	edx
+#define reg_AVX512_4FMAPS	edx
+#define reg_FSRM		edx
+#define reg_PCONFIG		edx
+#define reg_IBT			edx
+
+/* COMMON_CPUID_INDEX_80000001.  */
+
+/* ECX.  */
+#define reg_LAHF64_SAHF64	ecx
+#define reg_SVM			ecx
+#define reg_LZCNT		ecx
+#define reg_SSE4A		ecx
+#define reg_PREFETCHW		ecx
+#define reg_XOP			ecx
+#define reg_LWP			ecx
+#define reg_FMA4		ecx
+#define reg_TBM			ecx
+
+/* EDX.  */
+#define reg_SYSCALL_SYSRET	edx
+#define reg_NX			edx
+#define reg_PAGE1GB		edx
+#define reg_RDTSCP		edx
+#define reg_LM			edx
+
+__END_DECLS
+
+#endif  /* _SYS_PLATFORM_X86_H */
diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
index b2fac197da..1d85845f76 100644
--- a/sysdeps/x86/tst-get-cpu-features.c
+++ b/sysdeps/x86/tst-get-cpu-features.c
@@ -17,15 +17,221 @@ 
    <http://www.gnu.org/licenses/>.  */
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <cpu-features.h>
+#include <support/check.h>
+
+static const char * const cpu_kinds[] =
+{
+  "Unknown",
+  "Intel",
+  "AMD",
+  "Other",
+};
+
+#define CHECK_CPU_FEATURE(name) \
+  {					\
+    if (HAS_CPU_FEATURE (name))		\
+      printf ("  " #name "\n");		\
+  }
+
+#define CHECK_ARCH_FEATURE(name) \
+  {					\
+    if (HAS_ARCH_FEATURE (name))		\
+      printf ("  " #name "\n");		\
+  }
 
 static int
 do_test (void)
 {
-  if (__get_cpu_features ()->kind == arch_kind_unknown)
-    abort ();
+  enum cpu_features_kind kind = __get_cpu_features ()->kind;
+
+  switch (kind)
+    {
+    case arch_kind_intel:
+    case arch_kind_amd:
+    case arch_kind_other:
+      printf ("Vendor: %s\n", cpu_kinds[kind]);
+      break;
+
+    default:
+      abort ();
+    }
+
+#ifdef __SSE2__
+  TEST_VERIFY_EXIT (HAS_CPU_FEATURE (SSE2));
+#endif
+
+  printf ("CPU features:\n");
+  CHECK_CPU_FEATURE (SSE3);
+  CHECK_CPU_FEATURE (PCLMULQDQ);
+  CHECK_CPU_FEATURE (DTES64);
+  CHECK_CPU_FEATURE (MONITOR);
+  CHECK_CPU_FEATURE (DS_CPL);
+  CHECK_CPU_FEATURE (VMX);
+  CHECK_CPU_FEATURE (SMX);
+  CHECK_CPU_FEATURE (EST);
+  CHECK_CPU_FEATURE (TM2);
+  CHECK_CPU_FEATURE (SSSE3);
+  CHECK_CPU_FEATURE (CNXT_ID);
+  CHECK_CPU_FEATURE (SDBG);
+  CHECK_CPU_FEATURE (FMA);
+  CHECK_CPU_FEATURE (CMPXCHG16B);
+  CHECK_CPU_FEATURE (XTPRUPDCTRL);
+  CHECK_CPU_FEATURE (PDCM);
+  CHECK_CPU_FEATURE (PCID);
+  CHECK_CPU_FEATURE (DCA);
+  CHECK_CPU_FEATURE (SSE4_1);
+  CHECK_CPU_FEATURE (SSE4_2);
+  CHECK_CPU_FEATURE (X2APIC);
+  CHECK_CPU_FEATURE (MOVBE);
+  CHECK_CPU_FEATURE (POPCNT);
+  CHECK_CPU_FEATURE (TSC_DEADLINE);
+  CHECK_CPU_FEATURE (AES);
+  CHECK_CPU_FEATURE (XSAVE);
+  CHECK_CPU_FEATURE (OSXSAVE);
+  CHECK_CPU_FEATURE (AVX);
+  CHECK_CPU_FEATURE (F16C);
+  CHECK_CPU_FEATURE (RDRAND);
+  CHECK_CPU_FEATURE (FPU);
+  CHECK_CPU_FEATURE (VME);
+  CHECK_CPU_FEATURE (DE);
+  CHECK_CPU_FEATURE (PSE);
+  CHECK_CPU_FEATURE (TSC);
+  CHECK_CPU_FEATURE (MSR);
+  CHECK_CPU_FEATURE (PAE);
+  CHECK_CPU_FEATURE (MCE);
+  CHECK_CPU_FEATURE (CX8);
+  CHECK_CPU_FEATURE (APIC);
+  CHECK_CPU_FEATURE (SEP);
+  CHECK_CPU_FEATURE (MTRR);
+  CHECK_CPU_FEATURE (PGE);
+  CHECK_CPU_FEATURE (MCA);
+  CHECK_CPU_FEATURE (CMOV);
+  CHECK_CPU_FEATURE (PAT);
+  CHECK_CPU_FEATURE (PSE_36);
+  CHECK_CPU_FEATURE (PSN);
+  CHECK_CPU_FEATURE (CLFSH);
+  CHECK_CPU_FEATURE (DS);
+  CHECK_CPU_FEATURE (ACPI);
+  CHECK_CPU_FEATURE (MMX);
+  CHECK_CPU_FEATURE (FXSR);
+  CHECK_CPU_FEATURE (SSE);
+  CHECK_CPU_FEATURE (SSE2);
+  CHECK_CPU_FEATURE (SS);
+  CHECK_CPU_FEATURE (HTT);
+  CHECK_CPU_FEATURE (TM);
+  CHECK_CPU_FEATURE (PBE);
+  CHECK_CPU_FEATURE (FSGSBASE);
+  CHECK_CPU_FEATURE (TSC_ADJUST);
+  CHECK_CPU_FEATURE (SGX);
+  CHECK_CPU_FEATURE (BMI1);
+  CHECK_CPU_FEATURE (HLE);
+  CHECK_CPU_FEATURE (AVX2);
+  CHECK_CPU_FEATURE (SMEP);
+  CHECK_CPU_FEATURE (BMI2);
+  CHECK_CPU_FEATURE (ERMS);
+  CHECK_CPU_FEATURE (INVPCID);
+  CHECK_CPU_FEATURE (RTM);
+  CHECK_CPU_FEATURE (PQM);
+  CHECK_CPU_FEATURE (MPX);
+  CHECK_CPU_FEATURE (PQE);
+  CHECK_CPU_FEATURE (AVX512F);
+  CHECK_CPU_FEATURE (AVX512DQ);
+  CHECK_CPU_FEATURE (RDSEED);
+  CHECK_CPU_FEATURE (ADX);
+  CHECK_CPU_FEATURE (SMAP);
+  CHECK_CPU_FEATURE (AVX512_IFMA);
+  CHECK_CPU_FEATURE (CLFLUSHOPT);
+  CHECK_CPU_FEATURE (CLWB);
+  CHECK_CPU_FEATURE (TRACE);
+  CHECK_CPU_FEATURE (AVX512PF);
+  CHECK_CPU_FEATURE (AVX512ER);
+  CHECK_CPU_FEATURE (AVX512CD);
+  CHECK_CPU_FEATURE (SHA);
+  CHECK_CPU_FEATURE (AVX512BW);
+  CHECK_CPU_FEATURE (AVX512VL);
+  CHECK_CPU_FEATURE (PREFETCHWT1);
+  CHECK_CPU_FEATURE (AVX512_VBMI);
+  CHECK_CPU_FEATURE (UMIP);
+  CHECK_CPU_FEATURE (PKU);
+  CHECK_CPU_FEATURE (OSPKE);
+  CHECK_CPU_FEATURE (WAITPKG);
+  CHECK_CPU_FEATURE (SHSTK);
+  CHECK_CPU_FEATURE (AVX512_VBMI2);
+  CHECK_CPU_FEATURE (GFNI);
+  CHECK_CPU_FEATURE (VAES);
+  CHECK_CPU_FEATURE (VPCLMULQDQ);
+  CHECK_CPU_FEATURE (AVX512_VNNI);
+  CHECK_CPU_FEATURE (AVX512_BITALG);
+  CHECK_CPU_FEATURE (AVX512_VPOPCNTDQ);
+  CHECK_CPU_FEATURE (RDPID);
+  CHECK_CPU_FEATURE (CLDEMOTE);
+  CHECK_CPU_FEATURE (MOVDIRI);
+  CHECK_CPU_FEATURE (MOVDIR64B);
+  CHECK_CPU_FEATURE (SGX_LC);
+  CHECK_CPU_FEATURE (AVX512_4VNNIW);
+  CHECK_CPU_FEATURE (AVX512_4FMAPS);
+  CHECK_CPU_FEATURE (FSRM);
+  CHECK_CPU_FEATURE (PCONFIG);
+  CHECK_CPU_FEATURE (IBT);
+  CHECK_CPU_FEATURE (LAHF64_SAHF64);
+  CHECK_CPU_FEATURE (SVM);
+  CHECK_CPU_FEATURE (LZCNT);
+  CHECK_CPU_FEATURE (SSE4A);
+  CHECK_CPU_FEATURE (PREFETCHW);
+  CHECK_CPU_FEATURE (XOP);
+  CHECK_CPU_FEATURE (LWP);
+  CHECK_CPU_FEATURE (FMA4);
+  CHECK_CPU_FEATURE (TBM);
+  CHECK_CPU_FEATURE (SYSCALL_SYSRET);
+  CHECK_CPU_FEATURE (NX);
+  CHECK_CPU_FEATURE (PAGE1GB);
+  CHECK_CPU_FEATURE (RDTSCP);
+  CHECK_CPU_FEATURE (LM);
+
+  printf ("Architecture features:\n");
+  CHECK_ARCH_FEATURE (I586);
+  CHECK_ARCH_FEATURE (I686);
+  CHECK_ARCH_FEATURE (Fast_Rep_String);
+  CHECK_ARCH_FEATURE (Fast_Copy_Backward);
+  CHECK_ARCH_FEATURE (Fast_Unaligned_Load);
+  CHECK_ARCH_FEATURE (Fast_Unaligned_Copy);
+  CHECK_ARCH_FEATURE (Slow_BSF);
+  CHECK_ARCH_FEATURE (Slow_SSE4_2);
+  CHECK_ARCH_FEATURE (AVX_Fast_Unaligned_Load);
+  CHECK_ARCH_FEATURE (Prefer_MAP_32BIT_EXEC);
+  CHECK_ARCH_FEATURE (Prefer_PMINUB_for_stringop);
+  CHECK_ARCH_FEATURE (Prefer_No_VZEROUPPER);
+  CHECK_ARCH_FEATURE (Prefer_ERMS);
+  CHECK_ARCH_FEATURE (Prefer_FSRM);
+  CHECK_ARCH_FEATURE (Prefer_No_AVX512);
+  CHECK_ARCH_FEATURE (MathVec_Prefer_No_AVX512);
+
+  CHECK_ARCH_FEATURE (AVX_Usable);
+  CHECK_ARCH_FEATURE (AVX2_Usable);
+  CHECK_ARCH_FEATURE (AVX512F_Usable);
+  CHECK_ARCH_FEATURE (AVX512CD_Usable);
+  CHECK_ARCH_FEATURE (AVX512ER_Usable);
+  CHECK_ARCH_FEATURE (AVX512PF_Usable);
+  CHECK_ARCH_FEATURE (AVX512VL_Usable);
+  CHECK_ARCH_FEATURE (AVX512DQ_Usable);
+  CHECK_ARCH_FEATURE (AVX512BW_Usable);
+  CHECK_ARCH_FEATURE (AVX512_4FMAPS_Usable);
+  CHECK_ARCH_FEATURE (AVX512_4VNNIW_Usable);
+  CHECK_ARCH_FEATURE (AVX512_BITALG_Usable);
+  CHECK_ARCH_FEATURE (AVX512_IFMA_Usable);
+  CHECK_ARCH_FEATURE (AVX512_VBMI_Usable);
+  CHECK_ARCH_FEATURE (AVX512_VBMI2_Usable);
+  CHECK_ARCH_FEATURE (AVX512_VNNI_Usable);
+  CHECK_ARCH_FEATURE (GFNI_Usable);
+  CHECK_ARCH_FEATURE (VAES_Usable);
+  CHECK_ARCH_FEATURE (VPCLMULQDQ_Usable);
+  CHECK_ARCH_FEATURE (FMA_Usable);
+  CHECK_ARCH_FEATURE (FMA4_Usable);
+  CHECK_ARCH_FEATURE (XSAVEC_Usable);
+
   return 0;
 }
 
-#define TEST_FUNCTION do_test ()
-#include "../../test-skeleton.c"
+#include <support/test-driver.c>
diff --git a/sysdeps/x86/tst-x86-platform-1-static.c b/sysdeps/x86/tst-x86-platform-1-static.c
new file mode 100644
index 0000000000..d8c2a0c441
--- /dev/null
+++ b/sysdeps/x86/tst-x86-platform-1-static.c
@@ -0,0 +1 @@ 
+#include "tst-x86-platform-1.c"
diff --git a/sysdeps/x86/tst-x86-platform-1.c b/sysdeps/x86/tst-x86-platform-1.c
new file mode 100644
index 0000000000..75008a80d0
--- /dev/null
+++ b/sysdeps/x86/tst-x86-platform-1.c
@@ -0,0 +1,205 @@ 
+/* Test case for x86 <sys/platform/x86.h>.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/platform/x86.h>
+#include <support/check.h>
+
+#define CHECK_CPU_FEATURE(name) \
+  {					\
+    if (HAS_CPU_FEATURE (name))		\
+      printf ("  " #name "\n");		\
+  }
+
+#define CHECK_ARCH_FEATURE(name) \
+  {					\
+    if (HAS_ARCH_FEATURE (name))		\
+      printf ("  " #name "\n");		\
+  }
+
+#ifdef DO_TEST_FUNCTION
+int
+DO_TEST_FUNCTION (void)
+#else
+static int
+do_test (void)
+#endif
+{
+#ifdef __SSE2__
+  TEST_VERIFY_EXIT (HAS_CPU_FEATURE (SSE2));
+#endif
+
+  printf ("CPU features:\n");
+  CHECK_CPU_FEATURE (SSE3);
+  CHECK_CPU_FEATURE (PCLMULQDQ);
+  CHECK_CPU_FEATURE (DTES64);
+  CHECK_CPU_FEATURE (MONITOR);
+  CHECK_CPU_FEATURE (DS_CPL);
+  CHECK_CPU_FEATURE (VMX);
+  CHECK_CPU_FEATURE (SMX);
+  CHECK_CPU_FEATURE (EST);
+  CHECK_CPU_FEATURE (TM2);
+  CHECK_CPU_FEATURE (SSSE3);
+  CHECK_CPU_FEATURE (CNXT_ID);
+  CHECK_CPU_FEATURE (SDBG);
+  CHECK_CPU_FEATURE (FMA);
+  CHECK_CPU_FEATURE (CMPXCHG16B);
+  CHECK_CPU_FEATURE (XTPRUPDCTRL);
+  CHECK_CPU_FEATURE (PDCM);
+  CHECK_CPU_FEATURE (PCID);
+  CHECK_CPU_FEATURE (DCA);
+  CHECK_CPU_FEATURE (SSE4_1);
+  CHECK_CPU_FEATURE (SSE4_2);
+  CHECK_CPU_FEATURE (X2APIC);
+  CHECK_CPU_FEATURE (MOVBE);
+  CHECK_CPU_FEATURE (POPCNT);
+  CHECK_CPU_FEATURE (TSC_DEADLINE);
+  CHECK_CPU_FEATURE (AES);
+  CHECK_CPU_FEATURE (XSAVE);
+  CHECK_CPU_FEATURE (OSXSAVE);
+  CHECK_CPU_FEATURE (AVX);
+  CHECK_CPU_FEATURE (F16C);
+  CHECK_CPU_FEATURE (RDRAND);
+  CHECK_CPU_FEATURE (FPU);
+  CHECK_CPU_FEATURE (VME);
+  CHECK_CPU_FEATURE (DE);
+  CHECK_CPU_FEATURE (PSE);
+  CHECK_CPU_FEATURE (TSC);
+  CHECK_CPU_FEATURE (MSR);
+  CHECK_CPU_FEATURE (PAE);
+  CHECK_CPU_FEATURE (MCE);
+  CHECK_CPU_FEATURE (CX8);
+  CHECK_CPU_FEATURE (APIC);
+  CHECK_CPU_FEATURE (SEP);
+  CHECK_CPU_FEATURE (MTRR);
+  CHECK_CPU_FEATURE (PGE);
+  CHECK_CPU_FEATURE (MCA);
+  CHECK_CPU_FEATURE (CMOV);
+  CHECK_CPU_FEATURE (PAT);
+  CHECK_CPU_FEATURE (PSE_36);
+  CHECK_CPU_FEATURE (PSN);
+  CHECK_CPU_FEATURE (CLFSH);
+  CHECK_CPU_FEATURE (DS);
+  CHECK_CPU_FEATURE (ACPI);
+  CHECK_CPU_FEATURE (MMX);
+  CHECK_CPU_FEATURE (FXSR);
+  CHECK_CPU_FEATURE (SSE);
+  CHECK_CPU_FEATURE (SSE2);
+  CHECK_CPU_FEATURE (SS);
+  CHECK_CPU_FEATURE (HTT);
+  CHECK_CPU_FEATURE (TM);
+  CHECK_CPU_FEATURE (PBE);
+  CHECK_CPU_FEATURE (FSGSBASE);
+  CHECK_CPU_FEATURE (TSC_ADJUST);
+  CHECK_CPU_FEATURE (SGX);
+  CHECK_CPU_FEATURE (BMI1);
+  CHECK_CPU_FEATURE (HLE);
+  CHECK_CPU_FEATURE (AVX2);
+  CHECK_CPU_FEATURE (SMEP);
+  CHECK_CPU_FEATURE (BMI2);
+  CHECK_CPU_FEATURE (ERMS);
+  CHECK_CPU_FEATURE (INVPCID);
+  CHECK_CPU_FEATURE (RTM);
+  CHECK_CPU_FEATURE (PQM);
+  CHECK_CPU_FEATURE (MPX);
+  CHECK_CPU_FEATURE (PQE);
+  CHECK_CPU_FEATURE (AVX512F);
+  CHECK_CPU_FEATURE (AVX512DQ);
+  CHECK_CPU_FEATURE (RDSEED);
+  CHECK_CPU_FEATURE (ADX);
+  CHECK_CPU_FEATURE (SMAP);
+  CHECK_CPU_FEATURE (AVX512_IFMA);
+  CHECK_CPU_FEATURE (CLFLUSHOPT);
+  CHECK_CPU_FEATURE (CLWB);
+  CHECK_CPU_FEATURE (TRACE);
+  CHECK_CPU_FEATURE (AVX512PF);
+  CHECK_CPU_FEATURE (AVX512ER);
+  CHECK_CPU_FEATURE (AVX512CD);
+  CHECK_CPU_FEATURE (SHA);
+  CHECK_CPU_FEATURE (AVX512BW);
+  CHECK_CPU_FEATURE (AVX512VL);
+  CHECK_CPU_FEATURE (PREFETCHWT1);
+  CHECK_CPU_FEATURE (AVX512_VBMI);
+  CHECK_CPU_FEATURE (UMIP);
+  CHECK_CPU_FEATURE (PKU);
+  CHECK_CPU_FEATURE (OSPKE);
+  CHECK_CPU_FEATURE (WAITPKG);
+  CHECK_CPU_FEATURE (SHSTK);
+  CHECK_CPU_FEATURE (AVX512_VBMI2);
+  CHECK_CPU_FEATURE (GFNI);
+  CHECK_CPU_FEATURE (VAES);
+  CHECK_CPU_FEATURE (VPCLMULQDQ);
+  CHECK_CPU_FEATURE (AVX512_VNNI);
+  CHECK_CPU_FEATURE (AVX512_BITALG);
+  CHECK_CPU_FEATURE (AVX512_VPOPCNTDQ);
+  CHECK_CPU_FEATURE (RDPID);
+  CHECK_CPU_FEATURE (CLDEMOTE);
+  CHECK_CPU_FEATURE (MOVDIRI);
+  CHECK_CPU_FEATURE (MOVDIR64B);
+  CHECK_CPU_FEATURE (SGX_LC);
+  CHECK_CPU_FEATURE (AVX512_4VNNIW);
+  CHECK_CPU_FEATURE (AVX512_4FMAPS);
+  CHECK_CPU_FEATURE (FSRM);
+  CHECK_CPU_FEATURE (PCONFIG);
+  CHECK_CPU_FEATURE (IBT);
+  CHECK_CPU_FEATURE (LAHF64_SAHF64);
+  CHECK_CPU_FEATURE (SVM);
+  CHECK_CPU_FEATURE (LZCNT);
+  CHECK_CPU_FEATURE (SSE4A);
+  CHECK_CPU_FEATURE (PREFETCHW);
+  CHECK_CPU_FEATURE (XOP);
+  CHECK_CPU_FEATURE (LWP);
+  CHECK_CPU_FEATURE (FMA4);
+  CHECK_CPU_FEATURE (TBM);
+  CHECK_CPU_FEATURE (SYSCALL_SYSRET);
+  CHECK_CPU_FEATURE (NX);
+  CHECK_CPU_FEATURE (PAGE1GB);
+  CHECK_CPU_FEATURE (RDTSCP);
+  CHECK_CPU_FEATURE (LM);
+
+  printf ("Architecture features:\n");
+  CHECK_ARCH_FEATURE (AVX_Usable);
+  CHECK_ARCH_FEATURE (AVX2_Usable);
+  CHECK_ARCH_FEATURE (AVX512F_Usable);
+  CHECK_ARCH_FEATURE (AVX512CD_Usable);
+  CHECK_ARCH_FEATURE (AVX512ER_Usable);
+  CHECK_ARCH_FEATURE (AVX512PF_Usable);
+  CHECK_ARCH_FEATURE (AVX512VL_Usable);
+  CHECK_ARCH_FEATURE (AVX512DQ_Usable);
+  CHECK_ARCH_FEATURE (AVX512BW_Usable);
+  CHECK_ARCH_FEATURE (AVX512_4FMAPS_Usable);
+  CHECK_ARCH_FEATURE (AVX512_4VNNIW_Usable);
+  CHECK_ARCH_FEATURE (AVX512_BITALG_Usable);
+  CHECK_ARCH_FEATURE (AVX512_IFMA_Usable);
+  CHECK_ARCH_FEATURE (AVX512_VBMI_Usable);
+  CHECK_ARCH_FEATURE (AVX512_VBMI2_Usable);
+  CHECK_ARCH_FEATURE (AVX512_VNNI_Usable);
+  CHECK_ARCH_FEATURE (GFNI_Usable);
+  CHECK_ARCH_FEATURE (VAES_Usable);
+  CHECK_ARCH_FEATURE (VPCLMULQDQ_Usable);
+  CHECK_ARCH_FEATURE (FMA_Usable);
+  CHECK_ARCH_FEATURE (FMA4_Usable);
+  CHECK_ARCH_FEATURE (XSAVEC_Usable);
+
+  return 0;
+}
+
+#ifndef DO_TEST_FUNCTION
+#include <support/test-driver.c>
+#endif
diff --git a/sysdeps/x86/tst-x86-platform-2.c b/sysdeps/x86/tst-x86-platform-2.c
new file mode 100644
index 0000000000..7f3c13287c
--- /dev/null
+++ b/sysdeps/x86/tst-x86-platform-2.c
@@ -0,0 +1,27 @@ 
+/* Test case for x86 <sys/platform/x86.h>.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+extern int do_test_function (void);
+
+static int
+do_test (void)
+{
+  return do_test_function ();
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/x86/tst-x86-platform-3.c b/sysdeps/x86/tst-x86-platform-3.c
new file mode 100644
index 0000000000..7f3c13287c
--- /dev/null
+++ b/sysdeps/x86/tst-x86-platform-3.c
@@ -0,0 +1,27 @@ 
+/* Test case for x86 <sys/platform/x86.h>.
+   Copyright (C) 2018 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
+   <http://www.gnu.org/licenses/>.  */
+
+extern int do_test_function (void);
+
+static int
+do_test (void)
+{
+  return do_test_function ();
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/x86/tst-x86-platform-mod-2.c b/sysdeps/x86/tst-x86-platform-mod-2.c
new file mode 100644
index 0000000000..e7adc025eb
--- /dev/null
+++ b/sysdeps/x86/tst-x86-platform-mod-2.c
@@ -0,0 +1,2 @@ 
+#define DO_TEST_FUNCTION do_test_function
+#include "tst-x86-platform-1.c"
diff --git a/sysdeps/x86/tst-x86-platform-mod-3.c b/sysdeps/x86/tst-x86-platform-mod-3.c
new file mode 100644
index 0000000000..e7adc025eb
--- /dev/null
+++ b/sysdeps/x86/tst-x86-platform-mod-3.c
@@ -0,0 +1,2 @@ 
+#define DO_TEST_FUNCTION do_test_function
+#include "tst-x86-platform-1.c"
diff --git a/sysdeps/x86_64/multiarch/sched_cpucount.c b/sysdeps/x86_64/multiarch/sched_cpucount.c
index d10d74ae21..7949119dcd 100644
--- a/sysdeps/x86_64/multiarch/sched_cpucount.c
+++ b/sysdeps/x86_64/multiarch/sched_cpucount.c
@@ -33,4 +33,4 @@ 
 #undef __sched_cpucount
 
 libc_ifunc (__sched_cpucount,
-	    HAS_CPU_FEATURE (POPCOUNT) ? popcount_cpucount : generic_cpucount);
+	    HAS_CPU_FEATURE (POPCNT) ? popcount_cpucount : generic_cpucount);
diff --git a/sysdeps/x86_64/multiarch/test-multiarch.c b/sysdeps/x86_64/multiarch/test-multiarch.c
index aa872f27db..417147c3d5 100644
--- a/sysdeps/x86_64/multiarch/test-multiarch.c
+++ b/sysdeps/x86_64/multiarch/test-multiarch.c
@@ -85,8 +85,8 @@  do_test (int argc, char **argv)
 		       , "HAS_CPU_FEATURE (SSE4_1)");
   fails += check_proc ("ssse3", HAS_CPU_FEATURE (SSSE3),
 		       "HAS_CPU_FEATURE (SSSE3)");
-  fails += check_proc ("popcnt", HAS_CPU_FEATURE (POPCOUNT),
-		       "HAS_CPU_FEATURE (POPCOUNT)");
+  fails += check_proc ("popcnt", HAS_CPU_FEATURE (POPCNT),
+		       "HAS_CPU_FEATURE (POPCNT)");
 
   printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails);