public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] x86: Install <cpu-features.h> [BZ #26124]
@ 2020-06-17 19:31 H.J. Lu
  2020-06-17 20:54 ` Joseph Myers
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2020-06-17 19:31 UTC (permalink / raw)
  To: libc-alpha

Install <cpu-features.h> so that programmers can do

 #if __has_include(<cpu-features.h>)
 #include <cpu-features.h>
 #endif
 ...

   if (HAS_CPU_FEATURE (SSE3))
 ...
   if (CPU_FEATURE_USABLE (SSE3))
 ...

<cpu-features.h> exports only:

struct cpu_features
{
  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
  unsigned int feature[FEATURE_INDEX_MAX];
  struct cpu_features_basic basic;
};

/* Get a pointer to the CPU features structure.  */
extern const struct cpu_features *__get_cpu_features (void)
     __attribute__ ((const));

Since all feature checks are done through macros, programs compiled with
a newer <cpu-features.h> header are compatible with the older ones as
long as the layout of struct cpu_features is identical.

Note: Although GCC has __builtin_cpu_supports, it only supports a subset
of <cpu-features.h>.
---
 sysdeps/unix/sysv/linux/i386/ld.abilist       |  1 +
 sysdeps/unix/sysv/linux/x86_64/64/ld.abilist  |  1 +
 sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |  1 +
 sysdeps/x86/Makefile                          |  1 +
 sysdeps/x86/Versions                          |  2 +-
 sysdeps/x86/cpu-features.h                    | 58 ++---------
 sysdeps/x86/include/cpu-features.h            | 95 +++++++++++++++++++
 7 files changed, 106 insertions(+), 53 deletions(-)
 create mode 100644 sysdeps/x86/include/cpu-features.h

diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
index 0478e22071..2f522173b4 100644
--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
+++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
@@ -3,3 +3,4 @@ GLIBC_2.1 __libc_stack_end D 0x4
 GLIBC_2.1 _dl_mcount F
 GLIBC_2.3 ___tls_get_addr F
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
index d3cdf7611e..5a6abd4da0 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.2.5 __libc_stack_end D 0x8
 GLIBC_2.2.5 _dl_mcount F
 GLIBC_2.2.5 _r_debug D 0x28
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
index c70bccf782..1169d8135d 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.16 __libc_stack_end D 0x4
 GLIBC_2.16 __tls_get_addr F
 GLIBC_2.16 _dl_mcount F
 GLIBC_2.16 _r_debug D 0x14
+GLIBC_2.32 __get_cpu_features F
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index beab426f67..47051a3c82 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -4,6 +4,7 @@ endif
 
 ifeq ($(subdir),elf)
 sysdep-dl-routines += dl-get-cpu-features
+sysdep_headers += cpu-features.h
 
 tests += tst-get-cpu-features tst-get-cpu-features-static
 tests-static += tst-get-cpu-features-static
diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions
index e02923708e..04596dd688 100644
--- a/sysdeps/x86/Versions
+++ b/sysdeps/x86/Versions
@@ -1,5 +1,5 @@
 ld {
-  GLIBC_PRIVATE {
+  GLIBC_2.32 {
     __get_cpu_features;
   }
 }
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h
index de20044417..5c4e1a726a 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/cpu-features.h
@@ -1,4 +1,5 @@
-/* This file is part of the GNU C Library.
+/* Data structure for x86 CPU features.
+   This file is part of the GNU C Library.
    Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,8 +16,8 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#ifndef cpu_features_h
-#define cpu_features_h
+#ifndef _CPU_FEATURES_H
+#define _CPU_FEATURES_H
 
 enum
 {
@@ -72,34 +73,12 @@ struct cpu_features
   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
   unsigned int feature[FEATURE_INDEX_MAX];
   struct cpu_features_basic basic;
-  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
-     int so that we use
-
-	sub xsave_state_size_offset(%rip) %RSP_LP
-
-     in _dl_runtime_resolve.  */
-  unsigned long int xsave_state_size;
-  /* The full state size for XSAVE when XSAVEC is disabled by
-
-     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
-   */
-  unsigned int xsave_state_full_size;
-  /* Data cache size for use in memory and string routines, typically
-     L1 size.  */
-  unsigned long int data_cache_size;
-  /* Shared cache size for use in memory and string routines, typically
-     L2 or L3 size.  */
-  unsigned long int shared_cache_size;
-  /* Threshold to use non temporal store.  */
-  unsigned long int non_temporal_threshold;
 };
 
-/* Used from outside of glibc to get access to the CPU features
-   structure.  */
+/* Get a pointer to the CPU features structure.  */
 extern const struct cpu_features *__get_cpu_features (void)
      __attribute__ ((const));
 
-/* 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) \
@@ -976,29 +955,4 @@ extern const struct cpu_features *__get_cpu_features (void)
 #define bit_ZMM0_15_state	(1u << 6)
 #define bit_ZMM16_31_state	(1u << 7)
 
-# 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]))
-# endif
-
-#ifdef __x86_64__
-# define HAS_CPUID 1
-#elif (defined __i586__ || defined __pentium__	\
-       || defined __geode__ || defined __k6__)
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#elif defined __i486__
-# define HAS_CPUID 0
-# define HAS_I586 HAS_ARCH_FEATURE (I586)
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#else
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 1
-#endif
-
-#endif  /* cpu_features_h */
+#endif  /* _CPU_FEATURES_H */
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
new file mode 100644
index 0000000000..e2a303dc1f
--- /dev/null
+++ b/sysdeps/x86/include/cpu-features.h
@@ -0,0 +1,95 @@
+/* Data structure for x86 CPU features.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef	_PRIVATE_CPU_FEATURES_H
+#define	_PRIVATE_CPU_FEATURES_H	1
+
+#ifdef _CPU_FEATURES_H
+# error this should be impossible
+#endif
+
+#ifndef _ISOMAC
+/* Get most of the contents from the public header, but we define a
+   different `struct cpu_features' type for private use.  */
+# define cpu_features	cpu_features_public
+# define __get_cpu_features __get_cpu_features_public
+#endif
+
+#include <sysdeps/x86/cpu-features.h>
+
+#ifndef _ISOMAC
+
+# undef	cpu_features
+# undef __get_cpu_features
+
+/* Forward declaration.  */
+struct cpu_features
+{
+  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
+  unsigned int feature[FEATURE_INDEX_MAX];
+  struct cpu_features_basic basic;
+  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
+     int so that we use
+
+	sub xsave_state_size_offset(%rip) %RSP_LP
+
+     in _dl_runtime_resolve.  */
+  unsigned long int xsave_state_size;
+  /* The full state size for XSAVE when XSAVEC is disabled by
+
+     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
+   */
+  unsigned int xsave_state_full_size;
+  /* Data cache size for use in memory and string routines, typically
+     L1 size.  */
+  unsigned long int data_cache_size;
+  /* Shared cache size for use in memory and string routines, typically
+     L2 or L3 size.  */
+  unsigned long int shared_cache_size;
+  /* Threshold to use non temporal store.  */
+  unsigned long int non_temporal_threshold;
+};
+
+# 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]))
+# endif
+
+# ifdef __x86_64__
+#  define HAS_CPUID 1
+# elif (defined __i586__ || defined __pentium__	\
+	|| defined __geode__ || defined __k6__)
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# elif defined __i486__
+#  define HAS_CPUID 0
+#  define HAS_I586 HAS_ARCH_FEATURE (I586)
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# else
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 1
+# endif
+
+#endif /* !_ISOMAC */
+
+#endif /* include/link.h */
-- 
2.26.2


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] x86: Install <cpu-features.h> [BZ #26124]
  2020-06-17 19:31 [PATCH] x86: Install <cpu-features.h> [BZ #26124] H.J. Lu
@ 2020-06-17 20:54 ` Joseph Myers
  2020-06-18  0:08   ` [PATCH] x86: Install <sys/platform/x86.h> " H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Joseph Myers @ 2020-06-17 20:54 UTC (permalink / raw)
  To: H.J. Lu; +Cc: libc-alpha

On Wed, 17 Jun 2020, H.J. Lu via Libc-alpha wrote:

> Install <cpu-features.h> so that programmers can do

This appears to be x86-specific.  The convention for such 
architecture-specific headers is names such as sys/platform/x86.h (with 
corresponding naming conventions for individual symbols as documented in 
maint.texi).

This patch needs documentation in the glibc manual of the API provided by 
this header (which would also say that it's x86-specific, and go in 
platform.texi alongside other such documentation of architecture-specific 
interfaces).

New features should also have NEWS entries.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-17 20:54 ` Joseph Myers
@ 2020-06-18  0:08   ` H.J. Lu
  2020-06-18  8:45     ` Florian Weimer
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2020-06-18  0:08 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GNU C Library

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

On Wed, Jun 17, 2020 at 1:54 PM Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Wed, 17 Jun 2020, H.J. Lu via Libc-alpha wrote:
>
> > Install <cpu-features.h> so that programmers can do
>
> This appears to be x86-specific.  The convention for such
> architecture-specific headers is names such as sys/platform/x86.h (with
> corresponding naming conventions for individual symbols as documented in
> maint.texi).

Done.

> This patch needs documentation in the glibc manual of the API provided by
> this header (which would also say that it's x86-specific, and go in
> platform.texi alongside other such documentation of architecture-specific
> interfaces).

Done.

> New features should also have NEWS entries.
>

Done.

Here is the updated patch to provide <sys/platform/x86.h>.

Thanks.

-- 
H.J.

[-- Attachment #2: 0001-x86-Install-sys-platform-x86.h-BZ-26124.patch --]
[-- Type: text/x-patch, Size: 14570 bytes --]

From 588eaccaf70fdecb6a3f76fe892a97c57ccf051b Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 17 Jun 2020 09:12:18 -0700
Subject: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]

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

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

   if (HAS_CPU_FEATURE (SSE3))
 ...
   if (CPU_FEATURE_USABLE (SSE3))
 ...

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

struct cpu_features
{
  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
  unsigned int feature[FEATURE_INDEX_MAX];
  struct cpu_features_basic basic;
};

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

Since all feature checks are done through macros, programs compiled with
a newer <sys/platform/x86.h> header are compatible with the older ones as
long as the layout of struct cpu_features is identical.

Note: Although GCC has __builtin_cpu_supports, it only supports a subset
of <sys/platform/x86.h>.
---
 NEWS                                          |   2 +
 manual/platform.texi                          |  28 +++++
 sysdeps/unix/sysv/linux/i386/ld.abilist       |   1 +
 sysdeps/unix/sysv/linux/x86_64/64/ld.abilist  |   1 +
 sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |   1 +
 sysdeps/x86/Makefile                          |   1 +
 sysdeps/x86/Versions                          |   4 +-
 sysdeps/x86/dl-get-cpu-features.c             |   4 +-
 sysdeps/x86/include/cpu-features.h            | 102 ++++++++++++++++++
 .../{cpu-features.h => sys/platform/x86.h}    |  71 ++----------
 sysdeps/x86/tst-get-cpu-features.c            |   6 +-
 11 files changed, 152 insertions(+), 69 deletions(-)
 create mode 100644 sysdeps/x86/include/cpu-features.h
 rename sysdeps/x86/{cpu-features.h => sys/platform/x86.h} (94%)

diff --git a/NEWS b/NEWS
index a660fc59a8..ae7d1ece35 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,8 @@ Version 2.32
 
 Major new features:
 
+* Add <sys/platform/x86.h> to provide query macros for x86 CPU features.
+
 * Unicode 12.1.0 Support: Character encoding, character type info, and
   transliteration tables are all updated to Unicode 12.1.0, using
   generator scripts contributed by Mike FABIAN (Red Hat).
diff --git a/manual/platform.texi b/manual/platform.texi
index 504addc956..0a11f52612 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,30 @@ all threads in the current process.  Setting the
 ordering on only the current thread is necessary.  All other flag bits are
 reserved.
 @end deftypefun
+
+@node X86
+@appendixsec X86-specific Facilities
+
+Facilities specific to X86 that are not specific to a particular
+operating system are declared in @file{sys/platform/x86.h}.
+
+@deftypefun {const struct cpu_features *} __x86_get_cpu_features (void)
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Return a pointer to x86 CPU feature structure used by query macros for x86
+CPU features.
+@end deftypefun
+
+@deftypefn Macro int HAS_CPU_FEATURE (@var{name})
+This macro returns a nonzero value (true) if the processor feature
+@var{name} is available.
+@end deftypefn
+
+@deftypefn Macro int CPU_FEATURE_USABLE (@var{name})
+This macro returns a nonzero value (true) if the processor feature
+@var{name} is usable.
+@end deftypefn
+
+@deftypefn Macro int HAS_ARCH_FEATURE (@var{name})
+This macro returns a nonzero value (true) if the architecture feature
+@var{name} is available.
+@end deftypefn
diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
index 0478e22071..1226876689 100644
--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
+++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
@@ -3,3 +3,4 @@ GLIBC_2.1 __libc_stack_end D 0x4
 GLIBC_2.1 _dl_mcount F
 GLIBC_2.3 ___tls_get_addr F
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
index d3cdf7611e..886e57abd5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.2.5 __libc_stack_end D 0x8
 GLIBC_2.2.5 _dl_mcount F
 GLIBC_2.2.5 _r_debug D 0x28
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
index c70bccf782..0d2f8a2cc5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.16 __libc_stack_end D 0x4
 GLIBC_2.16 __tls_get_addr F
 GLIBC_2.16 _dl_mcount F
 GLIBC_2.16 _r_debug D 0x14
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index beab426f67..0e4d132803 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -4,6 +4,7 @@ endif
 
 ifeq ($(subdir),elf)
 sysdep-dl-routines += dl-get-cpu-features
+sysdep_headers += sys/platform/x86.h
 
 tests += tst-get-cpu-features tst-get-cpu-features-static
 tests-static += tst-get-cpu-features-static
diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions
index e02923708e..7e3139dbb1 100644
--- a/sysdeps/x86/Versions
+++ b/sysdeps/x86/Versions
@@ -1,5 +1,5 @@
 ld {
-  GLIBC_PRIVATE {
-    __get_cpu_features;
+  GLIBC_2.32 {
+    __x86_get_cpu_features;
   }
 }
diff --git a/sysdeps/x86/dl-get-cpu-features.c b/sysdeps/x86/dl-get-cpu-features.c
index 9d61cd56be..fa1a1caa87 100644
--- a/sysdeps/x86/dl-get-cpu-features.c
+++ b/sysdeps/x86/dl-get-cpu-features.c
@@ -18,10 +18,10 @@
 
 #include <ldsodefs.h>
 
-#undef __get_cpu_features
+#undef __x86_get_cpu_features
 
 const struct cpu_features *
-__get_cpu_features (void)
+__x86_get_cpu_features (void)
 {
   return &GLRO(dl_x86_cpu_features);
 }
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
new file mode 100644
index 0000000000..081483898e
--- /dev/null
+++ b/sysdeps/x86/include/cpu-features.h
@@ -0,0 +1,102 @@
+/* Data structure for x86 CPU features.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef	_PRIVATE_CPU_FEATURES_H
+#define	_PRIVATE_CPU_FEATURES_H	1
+
+#ifdef _CPU_FEATURES_H
+# error this should be impossible
+#endif
+
+#ifndef _ISOMAC
+/* Get most of the contents from the public header, but we define a
+   different `struct cpu_features' type for private use.  */
+# define cpu_features		cpu_features_public
+# define __x86_get_cpu_features	__x86_get_cpu_features_public
+#endif
+
+#include <sysdeps/x86/sys/platform/x86.h>
+
+#ifndef _ISOMAC
+
+# undef	cpu_features
+# undef __x86_get_cpu_features
+# define __get_cpu_features	__x86_get_cpu_features
+
+/* XCR0 Feature flags.  */
+# define bit_XMM_state		(1u << 1)
+# define bit_YMM_state		(1u << 2)
+# define bit_Opmask_state	(1u << 5)
+# define bit_ZMM0_15_state	(1u << 6)
+# define bit_ZMM16_31_state	(1u << 7)
+
+struct cpu_features
+{
+  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
+  unsigned int feature[FEATURE_INDEX_MAX];
+  struct cpu_features_basic basic;
+  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
+     int so that we use
+
+	sub xsave_state_size_offset(%rip) %RSP_LP
+
+     in _dl_runtime_resolve.  */
+  unsigned long int xsave_state_size;
+  /* The full state size for XSAVE when XSAVEC is disabled by
+
+     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
+   */
+  unsigned int xsave_state_full_size;
+  /* Data cache size for use in memory and string routines, typically
+     L1 size.  */
+  unsigned long int data_cache_size;
+  /* Shared cache size for use in memory and string routines, typically
+     L2 or L3 size.  */
+  unsigned long int shared_cache_size;
+  /* Threshold to use non temporal store.  */
+  unsigned long int non_temporal_threshold;
+};
+
+# if defined (_LIBC) && !IS_IN (nonlib)
+/* Unused for x86.  */
+#  define INIT_ARCH()
+#  define __x86_get_cpu_features()	(&GLRO(dl_x86_cpu_features))
+#  define x86_get_cpuid_registers(i) \
+       (&(GLRO(dl_x86_cpu_features).cpuid[i]))
+# endif
+
+# ifdef __x86_64__
+#  define HAS_CPUID 1
+# elif (defined __i586__ || defined __pentium__	\
+	|| defined __geode__ || defined __k6__)
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# elif defined __i486__
+#  define HAS_CPUID 0
+#  define HAS_I586 HAS_ARCH_FEATURE (I586)
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# else
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 1
+# endif
+
+#endif /* !_ISOMAC */
+
+#endif /* include/cpu-features.h */
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/sys/platform/x86.h
similarity index 94%
rename from sysdeps/x86/cpu-features.h
rename to sysdeps/x86/sys/platform/x86.h
index de20044417..2acb7fb5fa 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/sys/platform/x86.h
@@ -1,4 +1,5 @@
-/* This file is part of the GNU C Library.
+/* Data structure for x86 CPU features.
+   This file is part of the GNU C Library.
    Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,8 +16,8 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#ifndef cpu_features_h
-#define cpu_features_h
+#ifndef _SYS_PLATFORM_X86_H
+#define _SYS_PLATFORM_X86_H
 
 enum
 {
@@ -72,34 +73,12 @@ struct cpu_features
   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
   unsigned int feature[FEATURE_INDEX_MAX];
   struct cpu_features_basic basic;
-  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
-     int so that we use
-
-	sub xsave_state_size_offset(%rip) %RSP_LP
-
-     in _dl_runtime_resolve.  */
-  unsigned long int xsave_state_size;
-  /* The full state size for XSAVE when XSAVEC is disabled by
-
-     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
-   */
-  unsigned int xsave_state_full_size;
-  /* Data cache size for use in memory and string routines, typically
-     L1 size.  */
-  unsigned long int data_cache_size;
-  /* Shared cache size for use in memory and string routines, typically
-     L2 or L3 size.  */
-  unsigned long int shared_cache_size;
-  /* Threshold to use non temporal store.  */
-  unsigned long int non_temporal_threshold;
 };
 
-/* Used from outside of glibc to get access to the CPU features
-   structure.  */
-extern const struct cpu_features *__get_cpu_features (void)
+/* Get a pointer to the CPU features structure.  */
+extern const struct cpu_features *__x86_get_cpu_features (void)
      __attribute__ ((const));
 
-/* 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) \
@@ -107,11 +86,11 @@ extern const struct cpu_features *__get_cpu_features (void)
 
 /* HAS_CPU_FEATURE evaluates to true if CPU supports the feature.  */
 #define HAS_CPU_FEATURE(name) \
-  CPU_FEATURES_CPU_P (__get_cpu_features (), name)
+  CPU_FEATURES_CPU_P (__x86_get_cpu_features (), name)
 /* HAS_ARCH_FEATURE evaluates to true if we may use the feature at
    runtime.  */
 # define HAS_ARCH_FEATURE(name) \
-  CPU_FEATURES_ARCH_P (__get_cpu_features (), name)
+  CPU_FEATURES_ARCH_P (__x86_get_cpu_features (), name)
 /* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
 #define CPU_FEATURE_USABLE(name)				\
   ((need_arch_feature_##name && HAS_ARCH_FEATURE (name##_Usable))	\
@@ -969,36 +948,4 @@ extern const struct cpu_features *__get_cpu_features (void)
 #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		(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)
-
-# 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]))
-# endif
-
-#ifdef __x86_64__
-# define HAS_CPUID 1
-#elif (defined __i586__ || defined __pentium__	\
-       || defined __geode__ || defined __k6__)
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#elif defined __i486__
-# define HAS_CPUID 0
-# define HAS_I586 HAS_ARCH_FEATURE (I586)
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#else
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 1
-#endif
-
-#endif  /* cpu_features_h */
+#endif  /* _SYS_PLATFORM_X86_H */
diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
index 815fdb664a..010c2e2224 100644
--- a/sysdeps/x86/tst-get-cpu-features.c
+++ b/sysdeps/x86/tst-get-cpu-features.c
@@ -1,4 +1,4 @@
-/* Test case for x86 __get_cpu_features interface
+/* Test case for __x86_get_cpu_features interface
    Copyright (C) 2015-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -18,7 +18,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 #include <support/check.h>
 
 #define CHECK_CPU_FEATURE(name)		\
@@ -45,7 +45,7 @@ static const char * const cpu_kinds[] =
 static int
 do_test (void)
 {
-  const struct cpu_features *cpu_features = __get_cpu_features ();
+  const struct cpu_features *cpu_features = __x86_get_cpu_features ();
 
   switch (cpu_features->basic.kind)
     {
-- 
2.26.2


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-18  0:08   ` [PATCH] x86: Install <sys/platform/x86.h> " H.J. Lu
@ 2020-06-18  8:45     ` Florian Weimer
  2020-06-18 16:14       ` V2: " H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2020-06-18  8:45 UTC (permalink / raw)
  To: H.J. Lu via Libc-alpha; +Cc: Joseph Myers, H.J. Lu

* H. J. Lu via Libc-alpha:

> <sys/platform/x86.h> exports only:
>
> struct cpu_features
> {
>   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
>   unsigned int feature[FEATURE_INDEX_MAX];
>   struct cpu_features_basic basic;
> };

The struct cpu_features ABI does not appear to be stable, as I wrote on
the other thread:

  <https://sourceware.org/pipermail/libc-alpha/2020-June/115161.html>

Thanks,
Florian


^ permalink raw reply	[flat|nested] 28+ messages in thread

* V2: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-18  8:45     ` Florian Weimer
@ 2020-06-18 16:14       ` H.J. Lu
  2020-06-22  9:09         ` Florian Weimer
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2020-06-18 16:14 UTC (permalink / raw)
  To: Florian Weimer; +Cc: H.J. Lu via Libc-alpha, Joseph Myers

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

On Thu, Jun 18, 2020 at 1:45 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu via Libc-alpha:
>
> > <sys/platform/x86.h> exports only:
> >
> > struct cpu_features
> > {
> >   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
> >   unsigned int feature[FEATURE_INDEX_MAX];
> >   struct cpu_features_basic basic;
> > };
>
> The struct cpu_features ABI does not appear to be stable, as I wrote on
> the other thread:
>
>   <https://sourceware.org/pipermail/libc-alpha/2020-June/115161.html>
>

Here is the updated patch to use

struct cpu_features
{
  struct cpu_features_basic basic;
  unsigned int usable[USABLE_FEATURE_INDEX_MAX];
  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
};

This should be backward compatible for both .o and .so files.


-- 
H.J.

[-- Attachment #2: 0001-x86-Install-sys-platform-x86.h-BZ-26124.patch --]
[-- Type: application/x-patch, Size: 23394 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V2: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-18 16:14       ` V2: " H.J. Lu
@ 2020-06-22  9:09         ` Florian Weimer
  2020-06-22 20:25           ` V3: " H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2020-06-22  9:09 UTC (permalink / raw)
  To: H.J. Lu via Libc-alpha; +Cc: H.J. Lu, Joseph Myers

* H. J. Lu via Libc-alpha:

> On Thu, Jun 18, 2020 at 1:45 AM Florian Weimer <fweimer@redhat.com> wrote:
>>
>> * H. J. Lu via Libc-alpha:
>>
>> > <sys/platform/x86.h> exports only:
>> >
>> > struct cpu_features
>> > {
>> >   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
>> >   unsigned int feature[FEATURE_INDEX_MAX];
>> >   struct cpu_features_basic basic;
>> > };
>>
>> The struct cpu_features ABI does not appear to be stable, as I wrote on
>> the other thread:
>>
>>   <https://sourceware.org/pipermail/libc-alpha/2020-June/115161.html>
>>
>
> Here is the updated patch to use
>
> struct cpu_features
> {
>   struct cpu_features_basic basic;
>   unsigned int usable[USABLE_FEATURE_INDEX_MAX];
>   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
> };
>
> This should be backward compatible for both .o and .so files.

This is an improvement.  I still see issues with this interface, though.

Programmers will need something like this for IFUNC resolvers, but this
is not usable there if the relocation order does not match the explicit
ELF dependency order (e.g., due to symbol interposition).  This is a
generic problem with IFUNC resolvers.  Other architectures solve this by
adding arguments to IFUNC resolvers, so that the required can be
accessed without relocations.  __builtin_cpu_supports does not have this
issue.

The manual does not explain the difference between “available” and
“usable”.  I do not think we should expose both.  I don't see any
circumstances under which “available” would provide useful information.

struct cpu_features (even in its reduced form) is fairly large.  We will
never be able to reduce its size again if it becomes public ABI.

I'm not convinced that this interface conforms to the API contract for
the CPUID instruction.  Aren't the raw bits in the cpuid field subject
to interpretation based on family and model?  HAS_CPU_FEATURE does not
reflect this at all.

My preferred interface would look like this:

* The low-level function call ABI is:

  unsigned long long long int __x86_get_cpu_features (unsigned int word)
    __attribute__ ((const));

* IFUNC resolvers receive two arguments,

  unsigned long long long int *feature_words, size_t feature_words_length

* CPU_FEATURE_USABLE (NAME) would expand to something like

    ((__x86_get_cpu_features (NAME_word) & NAME_bitmask) != 0)

  The implementation of __x86_get_cpu_features simply returns 0 if the
  index is too large, which solves the extension problem.

* CPU_FEATURE_USABLE_ARRAY (WORDS, WORDS_LENGTH, NAME) would expand to this:

  (((NAME_word < WORDS_LENGTH ? WORDS[NAME_word] ? : 0) & NAME_bitmask) != 0)

  This version is expected to be used in IFUNC resolvers.  The macro
  name is just a strawman.

Only the “usable” bits are exposed, so the interface makes it clear that
the implementation performs some normalization.

Alternatively, the __builtin_cpu_supports interface could be enhanced to
cover all the features you need.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 28+ messages in thread

* V3: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-22  9:09         ` Florian Weimer
@ 2020-06-22 20:25           ` H.J. Lu
  2020-06-22 20:41             ` Florian Weimer
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2020-06-22 20:25 UTC (permalink / raw)
  To: Florian Weimer; +Cc: H.J. Lu via Libc-alpha, Joseph Myers

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

On Mon, Jun 22, 2020 at 2:09 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu via Libc-alpha:
>
> > On Thu, Jun 18, 2020 at 1:45 AM Florian Weimer <fweimer@redhat.com> wrote:
> >>
> >> * H. J. Lu via Libc-alpha:
> >>
> >> > <sys/platform/x86.h> exports only:
> >> >
> >> > struct cpu_features
> >> > {
> >> >   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
> >> >   unsigned int feature[FEATURE_INDEX_MAX];
> >> >   struct cpu_features_basic basic;
> >> > };
> >>
> >> The struct cpu_features ABI does not appear to be stable, as I wrote on
> >> the other thread:
> >>
> >>   <https://sourceware.org/pipermail/libc-alpha/2020-June/115161.html>
> >>
> >
> > Here is the updated patch to use
> >
> > struct cpu_features
> > {
> >   struct cpu_features_basic basic;
> >   unsigned int usable[USABLE_FEATURE_INDEX_MAX];
> >   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
> > };
> >
> > This should be backward compatible for both .o and .so files.
>
> This is an improvement.  I still see issues with this interface, though.
>
> Programmers will need something like this for IFUNC resolvers, but this
> is not usable there if the relocation order does not match the explicit
> ELF dependency order (e.g., due to symbol interposition).  This is a
> generic problem with IFUNC resolvers.  Other architectures solve this by
> adding arguments to IFUNC resolvers, so that the required can be

This issue is orthogonal to <sys/platform/x86.h>.

> accessed without relocations.  __builtin_cpu_supports does not have this
> issue.
>
> The manual does not explain the difference between “available” and
> “usable”.  I do not think we should expose both.  I don't see any
> circumstances under which “available” would provide useful information.

Fixed.  "available" means supported by the operating system, which is
very useful information.

> struct cpu_features (even in its reduced form) is fairly large.  We will
> never be able to reduce its size again if it becomes public ABI.

Fixed by

struct cpu_features
{
  struct cpu_features_basic basic;
  unsigned int *usable_p;
  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
};


> I'm not convinced that this interface conforms to the API contract for
> the CPUID instruction.  Aren't the raw bits in the cpuid field subject
> to interpretation based on family and model?  HAS_CPU_FEATURE does not
> reflect this at all.

Yes, it does.  The cpuid array is populated based on family and model.
It has accurate information about processor features.

> My preferred interface would look like this:
>
> * The low-level function call ABI is:
>
>   unsigned long long long int __x86_get_cpu_features (unsigned int word)
>     __attribute__ ((const));
>
> * IFUNC resolvers receive two arguments,
>
>   unsigned long long long int *feature_words, size_t feature_words_length
>
> * CPU_FEATURE_USABLE (NAME) would expand to something like
>
>     ((__x86_get_cpu_features (NAME_word) & NAME_bitmask) != 0)
>
>   The implementation of __x86_get_cpu_features simply returns 0 if the
>   index is too large, which solves the extension problem.
>
> * CPU_FEATURE_USABLE_ARRAY (WORDS, WORDS_LENGTH, NAME) would expand to this:
>
>   (((NAME_word < WORDS_LENGTH ? WORDS[NAME_word] ? : 0) & NAME_bitmask) != 0)
>
>   This version is expected to be used in IFUNC resolvers.  The macro
>   name is just a strawman.
>
> Only the “usable” bits are exposed, so the interface makes it clear that
> the implementation performs some normalization.

My new interface is expandable and backward compatible.  It is also
forward compatible
since the older libc.so works with binaries compiled against the newer
<sys/platform/x86.h>
as long as the cpuid and usable array sizes are the same.

> Alternatively, the __builtin_cpu_supports interface could be enhanced to
> cover all the features you need.

__builtin_cpu_supports is equivalent to CPU_FEATURE_USABLE and it
doesn't support HAS_CPU_FEATURE which does provide useful information.

-- 
H.J.

[-- Attachment #2: 0001-x86-Install-sys-platform-x86.h-BZ-26124.patch --]
[-- Type: text/x-patch, Size: 26541 bytes --]

From 4ee18b75b4f187487842b58062408d704c0af777 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 17 Jun 2020 09:12:18 -0700
Subject: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]

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

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

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

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

struct cpu_features
{
  struct cpu_features_basic basic;
  unsigned int *usable_p;
  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
};

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

Since all feature checks are done through macros, programs compiled with
a newer <sys/platform/x86.h> header are compatible with the older ones as
long as the layout of struct cpu_features is identical.  The cpuid array
can be expanded with backward binary compatibility for both .o and .so
files.

Note: Although GCC has __builtin_cpu_supports, it only supports a subset
of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE.  It
doesn't support HAS_CPU_FEATURE.
---
 NEWS                                          |   2 +
 manual/platform.texi                          |  23 ++
 sysdeps/unix/sysv/linux/i386/ld.abilist       |   1 +
 sysdeps/unix/sysv/linux/x86_64/64/ld.abilist  |   1 +
 sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |   1 +
 sysdeps/x86/Makefile                          |   1 +
 sysdeps/x86/Versions                          |   4 +-
 sysdeps/x86/dl-get-cpu-features.c             |   4 +-
 sysdeps/x86/include/cpu-features.h            | 207 ++++++++++++++++++
 .../{cpu-features.h => sys/platform/x86.h}    | 172 +--------------
 sysdeps/x86/tst-get-cpu-features.c            |   6 +-
 sysdeps/x86_64/fpu/math-tests-arch.h          |   8 +-
 sysdeps/x86_64/multiarch/test-multiarch.c     |  10 +-
 13 files changed, 264 insertions(+), 176 deletions(-)
 create mode 100644 sysdeps/x86/include/cpu-features.h
 rename sysdeps/x86/{cpu-features.h => sys/platform/x86.h} (77%)

diff --git a/NEWS b/NEWS
index a660fc59a8..ae7d1ece35 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,8 @@ Version 2.32
 
 Major new features:
 
+* Add <sys/platform/x86.h> to provide query macros for x86 CPU features.
+
 * Unicode 12.1.0 Support: Character encoding, character type info, and
   transliteration tables are all updated to Unicode 12.1.0, using
   generator scripts contributed by Mike FABIAN (Red Hat).
diff --git a/manual/platform.texi b/manual/platform.texi
index 504addc956..39cb68bd78 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,25 @@ all threads in the current process.  Setting the
 ordering on only the current thread is necessary.  All other flag bits are
 reserved.
 @end deftypefun
+
+@node X86
+@appendixsec X86-specific Facilities
+
+Facilities specific to X86 that are not specific to a particular
+operating system are declared in @file{sys/platform/x86.h}.
+
+@deftypefun {const struct cpu_features *} __x86_get_cpu_features (void)
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Return a pointer to x86 CPU feature structure used by query macros for x86
+CPU features.
+@end deftypefun
+
+@deftypefn Macro int HAS_CPU_FEATURE (@var{name})
+This macro returns a nonzero value (true) if the processor feature
+@var{name} is available.
+@end deftypefn
+
+@deftypefn Macro int CPU_FEATURE_USABLE (@var{name})
+This macro returns a nonzero value (true) if the processor feature
+@var{name} is supported by the operating system.
+@end deftypefn
diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
index 0478e22071..1226876689 100644
--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
+++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
@@ -3,3 +3,4 @@ GLIBC_2.1 __libc_stack_end D 0x4
 GLIBC_2.1 _dl_mcount F
 GLIBC_2.3 ___tls_get_addr F
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
index d3cdf7611e..886e57abd5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.2.5 __libc_stack_end D 0x8
 GLIBC_2.2.5 _dl_mcount F
 GLIBC_2.2.5 _r_debug D 0x28
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
index c70bccf782..0d2f8a2cc5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.16 __libc_stack_end D 0x4
 GLIBC_2.16 __tls_get_addr F
 GLIBC_2.16 _dl_mcount F
 GLIBC_2.16 _r_debug D 0x14
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index beab426f67..0e4d132803 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -4,6 +4,7 @@ endif
 
 ifeq ($(subdir),elf)
 sysdep-dl-routines += dl-get-cpu-features
+sysdep_headers += sys/platform/x86.h
 
 tests += tst-get-cpu-features tst-get-cpu-features-static
 tests-static += tst-get-cpu-features-static
diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions
index e02923708e..7e3139dbb1 100644
--- a/sysdeps/x86/Versions
+++ b/sysdeps/x86/Versions
@@ -1,5 +1,5 @@
 ld {
-  GLIBC_PRIVATE {
-    __get_cpu_features;
+  GLIBC_2.32 {
+    __x86_get_cpu_features;
   }
 }
diff --git a/sysdeps/x86/dl-get-cpu-features.c b/sysdeps/x86/dl-get-cpu-features.c
index 9d61cd56be..fa1a1caa87 100644
--- a/sysdeps/x86/dl-get-cpu-features.c
+++ b/sysdeps/x86/dl-get-cpu-features.c
@@ -18,10 +18,10 @@
 
 #include <ldsodefs.h>
 
-#undef __get_cpu_features
+#undef __x86_get_cpu_features
 
 const struct cpu_features *
-__get_cpu_features (void)
+__x86_get_cpu_features (void)
 {
   return &GLRO(dl_x86_cpu_features);
 }
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
new file mode 100644
index 0000000000..c6efa3f066
--- /dev/null
+++ b/sysdeps/x86/include/cpu-features.h
@@ -0,0 +1,207 @@
+/* Data structure for x86 CPU features.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef	_PRIVATE_CPU_FEATURES_H
+#define	_PRIVATE_CPU_FEATURES_H	1
+
+#ifdef _CPU_FEATURES_H
+# error this should be impossible
+#endif
+
+#ifndef _ISOMAC
+/* Get most of the contents from the public header, but we define a
+   different `struct cpu_features' type for private use.  */
+# define cpu_features		cpu_features_public
+# define __x86_get_cpu_features	__x86_get_cpu_features_public
+#endif
+
+#include <sysdeps/x86/sys/platform/x86.h>
+
+#ifndef _ISOMAC
+
+# undef	cpu_features
+# undef __x86_get_cpu_features
+# define __get_cpu_features	__x86_get_cpu_features
+
+enum
+{
+  /* The integer bit array index for the first set of preferred feature
+     bits.  */
+  PREFERRED_FEATURE_INDEX_1 = 0,
+  /* The current maximum size of the feature integer bit array.  */
+  PREFERRED_FEATURE_INDEX_MAX
+};
+
+# undef CPU_FEATURES_ARCH_P
+# define CPU_FEATURES_ARCH_P(ptr, name) \
+  ((ptr->feature_##name[index_arch_##name] & (bit_arch_##name)) != 0)
+
+/* HAS_ARCH_FEATURE evaluates to true if we may use the feature at
+   runtime.  */
+# define HAS_ARCH_FEATURE(name) \
+  CPU_FEATURES_ARCH_P (__x86_get_cpu_features (), name)
+/* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
+# undef CPU_FEATURE_USABLE
+# define CPU_FEATURE_USABLE(name) \
+  CPU_FEATURES_ARCH_P (__x86_get_cpu_features (), name##_Usable)
+
+/* USABLE_FEATURE_INDEX_1.  */
+# define feature_AVX_Usable			usable
+# define feature_AVX2_Usable			usable
+# define feature_AVX512F_Usable			usable
+# define feature_AVX512CD_Usable		usable
+# define feature_AVX512ER_Usable		usable
+# define feature_AVX512PF_Usable		usable
+# define feature_AVX512VL_Usable		usable
+# define feature_AVX512BW_Usable		usable
+# define feature_AVX512DQ_Usable		usable
+# define feature_AVX512_4FMAPS_Usable		usable
+# define feature_AVX512_4VNNIW_Usable		usable
+# define feature_AVX512_BITALG_Usable		usable
+# define feature_AVX512_IFMA_Usable		usable
+# define feature_AVX512_VBMI_Usable		usable
+# define feature_AVX512_VBMI2_Usable		usable
+# define feature_AVX512_VNNI_Usable		usable
+# define feature_AVX512_VPOPCNTDQ_Usable	usable
+# define feature_FMA_Usable			usable
+# define feature_FMA4_Usable			usable
+# define feature_VAES_Usable			usable
+# define feature_VPCLMULQDQ_Usable		usable
+# define feature_XOP_Usable			usable
+# define feature_XSAVEC_Usable			usable
+# define feature_F16C_Usable			usable
+# define feature_AVX512_VP2INTERSECT_Usable	usable
+# define feature_AVX512_BF16_Usable		usable
+# define feature_PKU_Usable			usable
+
+/* PREFERRED_FEATURE_INDEX_1.  */
+# define bit_arch_I586				(1u << 0)
+# define bit_arch_I686				(1u << 1)
+# define bit_arch_Fast_Rep_String		(1u << 2)
+# define bit_arch_Fast_Copy_Backward		(1u << 3)
+# define bit_arch_Fast_Unaligned_Load		(1u << 4)
+# define bit_arch_Fast_Unaligned_Copy		(1u << 5)
+# define bit_arch_Slow_BSF			(1u << 6)
+# define bit_arch_Slow_SSE4_2			(1u << 7)
+# define bit_arch_AVX_Fast_Unaligned_Load	(1u << 8)
+# define bit_arch_Prefer_MAP_32BIT_EXEC		(1u << 9)
+# define bit_arch_Prefer_PMINUB_for_stringop	(1u << 10)
+# define bit_arch_Prefer_No_VZEROUPPER		(1u << 11)
+# define bit_arch_Prefer_ERMS			(1u << 12)
+# define bit_arch_Prefer_FSRM			(1u << 13)
+# define bit_arch_Prefer_No_AVX512		(1u << 14)
+# define bit_arch_MathVec_Prefer_No_AVX512	(1u << 15)
+
+# define index_arch_Fast_Rep_String		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Copy_Backward		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_BSF			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Load		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_PMINUB_for_stringop 	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Copy		PREFERRED_FEATURE_INDEX_1
+# define index_arch_I586			PREFERRED_FEATURE_INDEX_1
+# define index_arch_I686			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_SSE4_2			PREFERRED_FEATURE_INDEX_1
+# define index_arch_AVX_Fast_Unaligned_Load	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_MAP_32BIT_EXEC	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_VZEROUPPER	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_ERMS			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_AVX512		PREFERRED_FEATURE_INDEX_1
+# define index_arch_MathVec_Prefer_No_AVX512	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_FSRM			PREFERRED_FEATURE_INDEX_1
+
+# define feature_Fast_Rep_String		preferred
+# define feature_Fast_Copy_Backward		preferred
+# define feature_Slow_BSF			preferred
+# define feature_Fast_Unaligned_Load		preferred
+# define feature_Prefer_PMINUB_for_stringop 	preferred
+# define feature_Fast_Unaligned_Copy		preferred
+# define feature_I586				preferred
+# define feature_I686				preferred
+# define feature_Slow_SSE4_2			preferred
+# define feature_AVX_Fast_Unaligned_Load	preferred
+# define feature_Prefer_MAP_32BIT_EXEC		preferred
+# define feature_Prefer_No_VZEROUPPER		preferred
+# define feature_Prefer_ERMS			preferred
+# define feature_Prefer_No_AVX512		preferred
+# define feature_MathVec_Prefer_No_AVX512	preferred
+# define feature_Prefer_FSRM			preferred
+
+/* XCR0 Feature flags.  */
+# define bit_XMM_state		(1u << 1)
+# define bit_YMM_state		(1u << 2)
+# define bit_Opmask_state	(1u << 5)
+# define bit_ZMM0_15_state	(1u << 6)
+# define bit_ZMM16_31_state	(1u << 7)
+
+struct cpu_features
+{
+  struct cpu_features_basic basic;
+  unsigned int *usable_p;
+  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
+  unsigned int usable[USABLE_FEATURE_INDEX_MAX];
+  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
+  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
+     int so that we use
+
+	sub xsave_state_size_offset(%rip) %RSP_LP
+
+     in _dl_runtime_resolve.  */
+  unsigned long int xsave_state_size;
+  /* The full state size for XSAVE when XSAVEC is disabled by
+
+     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
+   */
+  unsigned int xsave_state_full_size;
+  /* Data cache size for use in memory and string routines, typically
+     L1 size.  */
+  unsigned long int data_cache_size;
+  /* Shared cache size for use in memory and string routines, typically
+     L2 or L3 size.  */
+  unsigned long int shared_cache_size;
+  /* Threshold to use non temporal store.  */
+  unsigned long int non_temporal_threshold;
+};
+
+# if defined (_LIBC) && !IS_IN (nonlib)
+/* Unused for x86.  */
+#  define INIT_ARCH()
+#  define __x86_get_cpu_features()	(&GLRO(dl_x86_cpu_features))
+#  define x86_get_cpuid_registers(i) \
+       (&(GLRO(dl_x86_cpu_features).cpuid[i]))
+# endif
+
+# ifdef __x86_64__
+#  define HAS_CPUID 1
+# elif (defined __i586__ || defined __pentium__	\
+	|| defined __geode__ || defined __k6__)
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# elif defined __i486__
+#  define HAS_CPUID 0
+#  define HAS_I586 HAS_ARCH_FEATURE (I586)
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# else
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 1
+# endif
+
+#endif /* !_ISOMAC */
+
+#endif /* include/cpu-features.h */
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/sys/platform/x86.h
similarity index 77%
rename from sysdeps/x86/cpu-features.h
rename to sysdeps/x86/sys/platform/x86.h
index 574f055e0c..43e286cde3 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/sys/platform/x86.h
@@ -1,4 +1,5 @@
-/* This file is part of the GNU C Library.
+/* Data structure for x86 CPU features.
+   This file is part of the GNU C Library.
    Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,8 +16,8 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#ifndef cpu_features_h
-#define cpu_features_h
+#ifndef _SYS_PLATFORM_X86_H
+#define _SYS_PLATFORM_X86_H
 
 enum
 {
@@ -27,15 +28,6 @@ enum
   USABLE_FEATURE_INDEX_MAX
 };
 
-enum
-{
-  /* The integer bit array index for the first set of preferred feature
-     bits.  */
-  PREFERRED_FEATURE_INDEX_1 = 0,
-  /* The current maximum size of the feature integer bit array.  */
-  PREFERRED_FEATURE_INDEX_MAX
-};
-
 enum
 {
   COMMON_CPUID_INDEX_1 = 0,
@@ -80,51 +72,23 @@ struct cpu_features
   struct cpu_features_basic basic;
   unsigned int *usable_p;
   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
-  unsigned int usable[USABLE_FEATURE_INDEX_MAX];
-  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
-  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
-     int so that we use
-
-	sub xsave_state_size_offset(%rip) %RSP_LP
-
-     in _dl_runtime_resolve.  */
-  unsigned long int xsave_state_size;
-  /* The full state size for XSAVE when XSAVEC is disabled by
-
-     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
-   */
-  unsigned int xsave_state_full_size;
-  /* Data cache size for use in memory and string routines, typically
-     L1 size.  */
-  unsigned long int data_cache_size;
-  /* Shared cache size for use in memory and string routines, typically
-     L2 or L3 size.  */
-  unsigned long int shared_cache_size;
-  /* Threshold to use non temporal store.  */
-  unsigned long int non_temporal_threshold;
 };
 
-/* Used from outside of glibc to get access to the CPU features
-   structure.  */
-extern const struct cpu_features *__get_cpu_features (void)
+/* Get a pointer to the CPU features structure.  */
+extern const struct cpu_features *__x86_get_cpu_features (void)
      __attribute__ ((const));
 
-/* Only used directly in cpu-features.c.  */
-# define CPU_FEATURES_CPU_P(ptr, name) \
+#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_##name[index_arch_##name] & (bit_arch_##name)) != 0)
+#define CPU_FEATURES_ARCH_P(ptr, name) \
+  ((ptr->usable_p[index_arch_##name] & (bit_arch_##name)) != 0)
 
 /* HAS_CPU_FEATURE evaluates to true if CPU supports the feature.  */
 #define HAS_CPU_FEATURE(name) \
-  CPU_FEATURES_CPU_P (__get_cpu_features (), name)
-/* HAS_ARCH_FEATURE evaluates to true if we may use the feature at
-   runtime.  */
-# define HAS_ARCH_FEATURE(name) \
-  CPU_FEATURES_ARCH_P (__get_cpu_features (), name)
+  CPU_FEATURES_CPU_P (__x86_get_cpu_features (), name)
 /* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
 #define CPU_FEATURE_USABLE(name) \
-  HAS_ARCH_FEATURE (name##_Usable)
+  CPU_FEATURES_ARCH_P (__x86_get_cpu_features (), name##_Usable)
 
 /* Architecture features.  */
 
@@ -185,34 +149,6 @@ extern const struct cpu_features *__get_cpu_features (void)
 #define index_arch_AVX512_BF16_Usable		USABLE_FEATURE_INDEX_1
 #define index_arch_PKU_Usable			USABLE_FEATURE_INDEX_1
 
-#define feature_AVX_Usable			usable
-#define feature_AVX2_Usable			usable
-#define feature_AVX512F_Usable			usable
-#define feature_AVX512CD_Usable			usable
-#define feature_AVX512ER_Usable			usable
-#define feature_AVX512PF_Usable			usable
-#define feature_AVX512VL_Usable			usable
-#define feature_AVX512BW_Usable			usable
-#define feature_AVX512DQ_Usable			usable
-#define feature_AVX512_4FMAPS_Usable		usable
-#define feature_AVX512_4VNNIW_Usable		usable
-#define feature_AVX512_BITALG_Usable		usable
-#define feature_AVX512_IFMA_Usable		usable
-#define feature_AVX512_VBMI_Usable		usable
-#define feature_AVX512_VBMI2_Usable		usable
-#define feature_AVX512_VNNI_Usable		usable
-#define feature_AVX512_VPOPCNTDQ_Usable		usable
-#define feature_FMA_Usable			usable
-#define feature_FMA4_Usable			usable
-#define feature_VAES_Usable			usable
-#define feature_VPCLMULQDQ_Usable		usable
-#define feature_XOP_Usable			usable
-#define feature_XSAVEC_Usable			usable
-#define feature_F16C_Usable			usable
-#define feature_AVX512_VP2INTERSECT_Usable	usable
-#define feature_AVX512_BF16_Usable		usable
-#define feature_PKU_Usable			usable
-
 /* CPU features.  */
 
 /* COMMON_CPUID_INDEX_1.  */
@@ -761,88 +697,4 @@ extern const struct cpu_features *__get_cpu_features (void)
 /* EAX.  */
 #define reg_AVX512_BF16		eax
 
-/* FEATURE_INDEX_2.  */
-#define bit_arch_I586				(1u << 0)
-#define bit_arch_I686				(1u << 1)
-#define bit_arch_Fast_Rep_String		(1u << 2)
-#define bit_arch_Fast_Copy_Backward		(1u << 3)
-#define bit_arch_Fast_Unaligned_Load		(1u << 4)
-#define bit_arch_Fast_Unaligned_Copy		(1u << 5)
-#define bit_arch_Slow_BSF			(1u << 6)
-#define bit_arch_Slow_SSE4_2			(1u << 7)
-#define bit_arch_AVX_Fast_Unaligned_Load	(1u << 8)
-#define bit_arch_Prefer_MAP_32BIT_EXEC		(1u << 9)
-#define bit_arch_Prefer_PMINUB_for_stringop	(1u << 10)
-#define bit_arch_Prefer_No_VZEROUPPER		(1u << 11)
-#define bit_arch_Prefer_ERMS			(1u << 12)
-#define bit_arch_Prefer_FSRM			(1u << 13)
-#define bit_arch_Prefer_No_AVX512		(1u << 14)
-#define bit_arch_MathVec_Prefer_No_AVX512	(1u << 15)
-
-#define index_arch_Fast_Rep_String		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Copy_Backward		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_BSF			PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Load		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_PMINUB_for_stringop 	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Copy		PREFERRED_FEATURE_INDEX_1
-#define index_arch_I586				PREFERRED_FEATURE_INDEX_1
-#define index_arch_I686				PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_SSE4_2			PREFERRED_FEATURE_INDEX_1
-#define index_arch_AVX_Fast_Unaligned_Load	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_MAP_32BIT_EXEC	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_VZEROUPPER		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_ERMS			PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_AVX512		PREFERRED_FEATURE_INDEX_1
-#define index_arch_MathVec_Prefer_No_AVX512	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_FSRM			PREFERRED_FEATURE_INDEX_1
-
-#define feature_Fast_Rep_String			preferred
-#define feature_Fast_Copy_Backward		preferred
-#define feature_Slow_BSF			preferred
-#define feature_Fast_Unaligned_Load		preferred
-#define feature_Prefer_PMINUB_for_stringop 	preferred
-#define feature_Fast_Unaligned_Copy		preferred
-#define feature_I586				preferred
-#define feature_I686				preferred
-#define feature_Slow_SSE4_2			preferred
-#define feature_AVX_Fast_Unaligned_Load		preferred
-#define feature_Prefer_MAP_32BIT_EXEC		preferred
-#define feature_Prefer_No_VZEROUPPER		preferred
-#define feature_Prefer_ERMS			preferred
-#define feature_Prefer_No_AVX512		preferred
-#define feature_MathVec_Prefer_No_AVX512	preferred
-#define feature_Prefer_FSRM			preferred
-
-/* XCR0 Feature flags.  */
-#define bit_XMM_state		(1u << 1)
-#define bit_YMM_state		(1u << 2)
-#define bit_Opmask_state	(1u << 5)
-#define bit_ZMM0_15_state	(1u << 6)
-#define bit_ZMM16_31_state	(1u << 7)
-
-# 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]))
-# endif
-
-#ifdef __x86_64__
-# define HAS_CPUID 1
-#elif (defined __i586__ || defined __pentium__	\
-       || defined __geode__ || defined __k6__)
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#elif defined __i486__
-# define HAS_CPUID 0
-# define HAS_I586 HAS_ARCH_FEATURE (I586)
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#else
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 1
-#endif
-
-#endif  /* cpu_features_h */
+#endif  /* _SYS_PLATFORM_X86_H */
diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
index c60918cf00..c470bfb345 100644
--- a/sysdeps/x86/tst-get-cpu-features.c
+++ b/sysdeps/x86/tst-get-cpu-features.c
@@ -1,4 +1,4 @@
-/* Test case for x86 __get_cpu_features interface
+/* Test case for __x86_get_cpu_features interface
    Copyright (C) 2015-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -18,7 +18,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 #include <support/check.h>
 
 #define CHECK_CPU_FEATURE(name)		\
@@ -45,7 +45,7 @@ static const char * const cpu_kinds[] =
 static int
 do_test (void)
 {
-  const struct cpu_features *cpu_features = __get_cpu_features ();
+  const struct cpu_features *cpu_features = __x86_get_cpu_features ();
 
   switch (cpu_features->basic.kind)
     {
diff --git a/sysdeps/x86_64/fpu/math-tests-arch.h b/sysdeps/x86_64/fpu/math-tests-arch.h
index 435ddad991..cc3c2b0c11 100644
--- a/sysdeps/x86_64/fpu/math-tests-arch.h
+++ b/sysdeps/x86_64/fpu/math-tests-arch.h
@@ -16,7 +16,7 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 
 #if defined REQUIRE_AVX
 
@@ -24,7 +24,7 @@
 # define CHECK_ARCH_EXT                                        \
   do                                                           \
     {                                                          \
-      if (!HAS_ARCH_FEATURE (AVX_Usable)) return;              \
+      if (!CPU_FEATURE_USABLE (AVX)) return;                   \
     }                                                          \
   while (0)
 
@@ -34,7 +34,7 @@
 # define CHECK_ARCH_EXT                                        \
   do                                                           \
     {                                                          \
-      if (!HAS_ARCH_FEATURE (AVX2_Usable)) return;             \
+      if (!CPU_FEATURE_USABLE (AVX2)) return;                  \
     }                                                          \
   while (0)
 
@@ -44,7 +44,7 @@
 # define CHECK_ARCH_EXT                                        \
   do                                                           \
     {                                                          \
-      if (!HAS_ARCH_FEATURE (AVX512F_Usable)) return;          \
+      if (!CPU_FEATURE_USABLE (AVX512F)) return;               \
     }                                                          \
   while (0)
 
diff --git a/sysdeps/x86_64/multiarch/test-multiarch.c b/sysdeps/x86_64/multiarch/test-multiarch.c
index 317373ceda..9feaf057e5 100644
--- a/sysdeps/x86_64/multiarch/test-multiarch.c
+++ b/sysdeps/x86_64/multiarch/test-multiarch.c
@@ -16,7 +16,7 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -75,10 +75,10 @@ do_test (int argc, char **argv)
   int fails;
 
   get_cpuinfo ();
-  fails = check_proc ("avx", HAS_ARCH_FEATURE (AVX_Usable),
-		      "HAS_ARCH_FEATURE (AVX_Usable)");
-  fails += check_proc ("fma4", HAS_ARCH_FEATURE (FMA4_Usable),
-		       "HAS_ARCH_FEATURE (FMA4_Usable)");
+  fails = check_proc ("avx", CPU_FEATURE_USABLE (AVX),
+		      "CPU_FEATURE_USABLE (AVX)");
+  fails += check_proc ("fma4", CPU_FEATURE_USABLE (FMA4),
+		       "CPU_FEATURE_USABLE (FMA4)");
   fails += check_proc ("sse4_2", HAS_CPU_FEATURE (SSE4_2),
 		       "HAS_CPU_FEATURE (SSE4_2)");
   fails += check_proc ("sse4_1", HAS_CPU_FEATURE (SSE4_1)
-- 
2.26.2


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V3: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-22 20:25           ` V3: " H.J. Lu
@ 2020-06-22 20:41             ` Florian Weimer
  2020-06-22 20:53               ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2020-06-22 20:41 UTC (permalink / raw)
  To: H.J. Lu; +Cc: H.J. Lu via Libc-alpha, Joseph Myers

* H. J. Lu:

>> accessed without relocations.  __builtin_cpu_supports does not have this
>> issue.
>>
>> The manual does not explain the difference between “available” and
>> “usable”.  I do not think we should expose both.  I don't see any
>> circumstances under which “available” would provide useful information.
>
> Fixed.  "available" means supported by the operating system, which is
> very useful information.

The manual update contradicts that.  It says that “usable” is what
implies operating system support.  I hope the manual is correct. 8-)

“usable” is obviously useful.  As far as I understand it, if the flag is
set, all preconditions for using the feature are met, and attempting to
use it will not trap (unless there are memory faults etc.).

Does “available” means that the feature could become “usable” merely as
the result of configuration changes, or hypervisor and kernel software
updates?  Why is that useful information?  Is it even reliable?

I have not seen this distinction on any other architecture.

>> struct cpu_features (even in its reduced form) is fairly large.  We will
>> never be able to reduce its size again if it becomes public ABI.
>
> Fixed by
>
> struct cpu_features
> {
>   struct cpu_features_basic basic;
>   unsigned int *usable_p;
>   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
> };

I think the cpuid member is the fat part.  But the pointer indirection
allows us to grow the *usable_p part without having to duplicate the
backing storage for __x86_get_cpu_features, so it is an improvement.

> __builtin_cpu_supports is equivalent to CPU_FEATURE_USABLE and it
> doesn't support HAS_CPU_FEATURE which does provide useful information.

I'm still puzzled as to why you aren't extending the existing function.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V3: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-22 20:41             ` Florian Weimer
@ 2020-06-22 20:53               ` H.J. Lu
  2020-06-22 21:14                 ` Florian Weimer
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2020-06-22 20:53 UTC (permalink / raw)
  To: Florian Weimer; +Cc: H.J. Lu via Libc-alpha, Joseph Myers

On Mon, Jun 22, 2020 at 1:41 PM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> >> accessed without relocations.  __builtin_cpu_supports does not have this
> >> issue.
> >>
> >> The manual does not explain the difference between “available” and
> >> “usable”.  I do not think we should expose both.  I don't see any
> >> circumstances under which “available” would provide useful information.
> >
> > Fixed.  "available" means supported by the operating system, which is
> > very useful information.
>
> The manual update contradicts that.  It says that “usable” is what
> implies operating system support.  I hope the manual is correct. 8-)
>
> “usable” is obviously useful.  As far as I understand it, if the flag is
> set, all preconditions for using the feature are met, and attempting to
> use it will not trap (unless there are memory faults etc.).
>
> Does “available” means that the feature could become “usable” merely as
> the result of configuration changes, or hypervisor and kernel software
> updates?  Why is that useful information?  Is it even reliable?
>
> I have not seen this distinction on any other architecture.

I changed the manual to

@deftypefn Macro int HAS_CPU_FEATURE (@var{name})
This macro returns a nonzero value (true) if the processor has the feature
@var{name}.
@end deftypefn

@deftypefn Macro int CPU_FEATURE_USABLE (@var{name})
This macro returns a nonzero value (true) if the processor feature
@var{name} is supported by the operating system.

> >> struct cpu_features (even in its reduced form) is fairly large.  We will
> >> never be able to reduce its size again if it becomes public ABI.
> >
> > Fixed by
> >
> > struct cpu_features
> > {
> >   struct cpu_features_basic basic;
> >   unsigned int *usable_p;
> >   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
> > };
>
> I think the cpuid member is the fat part.  But the pointer indirection
> allows us to grow the *usable_p part without having to duplicate the
> backing storage for __x86_get_cpu_features, so it is an improvement.
>
> > __builtin_cpu_supports is equivalent to CPU_FEATURE_USABLE and it
> > doesn't support HAS_CPU_FEATURE which does provide useful information.
>
> I'm still puzzled as to why you aren't extending the existing function.
>

I am working on it:

https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546522.html

But it is very unlikely to support HAS_CPU_FEATURE and
<sys/platform/x86.h> works with all GCCs.

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V3: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-22 20:53               ` H.J. Lu
@ 2020-06-22 21:14                 ` Florian Weimer
  2020-06-22 22:18                   ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2020-06-22 21:14 UTC (permalink / raw)
  To: H.J. Lu; +Cc: H.J. Lu via Libc-alpha, Joseph Myers

* H. J. Lu:

> I changed the manual to
>
> @deftypefn Macro int HAS_CPU_FEATURE (@var{name})
> This macro returns a nonzero value (true) if the processor has the feature
> @var{name}.
> @end deftypefn
>
> @deftypefn Macro int CPU_FEATURE_USABLE (@var{name})
> This macro returns a nonzero value (true) if the processor feature
> @var{name} is supported by the operating system.

Does this mean that it's necessary to check both before using the
feature?  This is what the description implies to me.

If CPU_FEATURE_USABLE implies HAS_CPU_FEATURE (so it's not necessary to
check both), then I don't see the use case for HAS_CPU_FEATURE.  To me,
exposing both liks like a trap for programmers: they might check CPU
support only, but not operating system support.  That's trap that we
have fallen into with glibc itself at least once.

>> >> struct cpu_features (even in its reduced form) is fairly large.  We will
>> >> never be able to reduce its size again if it becomes public ABI.
>> >
>> > Fixed by
>> >
>> > struct cpu_features
>> > {
>> >   struct cpu_features_basic basic;
>> >   unsigned int *usable_p;
>> >   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
>> > };
>>
>> I think the cpuid member is the fat part.  But the pointer indirection
>> allows us to grow the *usable_p part without having to duplicate the
>> backing storage for __x86_get_cpu_features, so it is an improvement.
>>
>> > __builtin_cpu_supports is equivalent to CPU_FEATURE_USABLE and it
>> > doesn't support HAS_CPU_FEATURE which does provide useful information.
>>
>> I'm still puzzled as to why you aren't extending the existing function.
>>
>
> I am working on it:
>
> https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546522.html
>
> But it is very unlikely to support HAS_CPU_FEATURE and
> <sys/platform/x86.h> works with all GCCs.

On the other hand, it's easier for our users to upgrade GCC than to
update glibc.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V3: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-22 21:14                 ` Florian Weimer
@ 2020-06-22 22:18                   ` H.J. Lu
  2020-06-22 23:14                     ` V4: " H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2020-06-22 22:18 UTC (permalink / raw)
  To: Florian Weimer; +Cc: H.J. Lu via Libc-alpha, Joseph Myers

On Mon, Jun 22, 2020 at 2:15 PM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> > I changed the manual to
> >
> > @deftypefn Macro int HAS_CPU_FEATURE (@var{name})
> > This macro returns a nonzero value (true) if the processor has the feature
> > @var{name}.
> > @end deftypefn
> >
> > @deftypefn Macro int CPU_FEATURE_USABLE (@var{name})
> > This macro returns a nonzero value (true) if the processor feature
> > @var{name} is supported by the operating system.
>
> Does this mean that it's necessary to check both before using the
> feature?  This is what the description implies to me.

CPU_FEATURE_USABLE  is true only if HAS_CPU_FEATURE is true.

> If CPU_FEATURE_USABLE implies HAS_CPU_FEATURE (so it's not necessary to
> check both), then I don't see the use case for HAS_CPU_FEATURE.  To me,
> exposing both liks like a trap for programmers: they might check CPU
> support only, but not operating system support.  That's trap that we
> have fallen into with glibc itself at least once.

Since not all features need OS support, only a subset of features have both.
HAS_CPU_FEATURE is useful on its own.  For example, it can be used to
identify processors even if OS doesn't support the feature.  All the information
is readily available.  I just provide a macro with a stable ABI to access it.

>
> >> >> struct cpu_features (even in its reduced form) is fairly large.  We will
> >> >> never be able to reduce its size again if it becomes public ABI.
> >> >
> >> > Fixed by
> >> >
> >> > struct cpu_features
> >> > {
> >> >   struct cpu_features_basic basic;
> >> >   unsigned int *usable_p;
> >> >   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
> >> > };
> >>
> >> I think the cpuid member is the fat part.  But the pointer indirection
> >> allows us to grow the *usable_p part without having to duplicate the
> >> backing storage for __x86_get_cpu_features, so it is an improvement.
> >>
> >> > __builtin_cpu_supports is equivalent to CPU_FEATURE_USABLE and it
> >> > doesn't support HAS_CPU_FEATURE which does provide useful information.
> >>
> >> I'm still puzzled as to why you aren't extending the existing function.
> >>
> >
> > I am working on it:
> >
> > https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546522.html
> >
> > But it is very unlikely to support HAS_CPU_FEATURE and
> > <sys/platform/x86.h> works with all GCCs.
>
> On the other hand, it's easier for our users to upgrade GCC than to
> update glibc.

Not everyone needs/wants to upgrade GCC.

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* V4: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-22 22:18                   ` H.J. Lu
@ 2020-06-22 23:14                     ` H.J. Lu
  2020-06-24 14:33                       ` Florian Weimer
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2020-06-22 23:14 UTC (permalink / raw)
  To: Florian Weimer; +Cc: H.J. Lu via Libc-alpha, Joseph Myers

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

On Mon, Jun 22, 2020 at 3:18 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, Jun 22, 2020 at 2:15 PM Florian Weimer <fweimer@redhat.com> wrote:
> >
> > * H. J. Lu:
> >
> > > I changed the manual to
> > >
> > > @deftypefn Macro int HAS_CPU_FEATURE (@var{name})
> > > This macro returns a nonzero value (true) if the processor has the feature
> > > @var{name}.
> > > @end deftypefn
> > >
> > > @deftypefn Macro int CPU_FEATURE_USABLE (@var{name})
> > > This macro returns a nonzero value (true) if the processor feature
> > > @var{name} is supported by the operating system.
> >
> > Does this mean that it's necessary to check both before using the
> > feature?  This is what the description implies to me.
>
> CPU_FEATURE_USABLE  is true only if HAS_CPU_FEATURE is true.
>
> > If CPU_FEATURE_USABLE implies HAS_CPU_FEATURE (so it's not necessary to
> > check both), then I don't see the use case for HAS_CPU_FEATURE.  To me,
> > exposing both liks like a trap for programmers: they might check CPU
> > support only, but not operating system support.  That's trap that we
> > have fallen into with glibc itself at least once.
>
> Since not all features need OS support, only a subset of features have both.
> HAS_CPU_FEATURE is useful on its own.  For example, it can be used to
> identify processors even if OS doesn't support the feature.  All the information
> is readily available.  I just provide a macro with a stable ABI to access it.
>
> >
> > >> >> struct cpu_features (even in its reduced form) is fairly large.  We will
> > >> >> never be able to reduce its size again if it becomes public ABI.
> > >> >
> > >> > Fixed by
> > >> >
> > >> > struct cpu_features
> > >> > {
> > >> >   struct cpu_features_basic basic;
> > >> >   unsigned int *usable_p;
> > >> >   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
> > >> > };
> > >>
> > >> I think the cpuid member is the fat part.  But the pointer indirection
> > >> allows us to grow the *usable_p part without having to duplicate the
> > >> backing storage for __x86_get_cpu_features, so it is an improvement.
> > >>
> > >> > __builtin_cpu_supports is equivalent to CPU_FEATURE_USABLE and it
> > >> > doesn't support HAS_CPU_FEATURE which does provide useful information.
> > >>
> > >> I'm still puzzled as to why you aren't extending the existing function.
> > >>
> > >
> > > I am working on it:
> > >
> > > https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546522.html
> > >
> > > But it is very unlikely to support HAS_CPU_FEATURE and
> > > <sys/platform/x86.h> works with all GCCs.
> >
> > On the other hand, it's easier for our users to upgrade GCC than to
> > update glibc.
>
> Not everyone needs/wants to upgrade GCC.
>

Here is the updated patch with

 -- Macro: int HAS_CPU_FEATURE (NAME)
     This macro returns a nonzero value (true) if the processor has the
     feature NAME.

 -- Macro: int CPU_FEATURE_USABLE (NAME)
     This macro returns a nonzero value (true) if the processor has the
     feature NAME and the feature is supported by the operating system.

-- 
H.J.

[-- Attachment #2: 0001-x86-Install-sys-platform-x86.h-BZ-26124.patch --]
[-- Type: text/x-patch, Size: 26560 bytes --]

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

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

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

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

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

struct cpu_features
{
  struct cpu_features_basic basic;
  unsigned int *usable_p;
  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
};

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

Since all feature checks are done through macros, programs compiled with
a newer <sys/platform/x86.h> header are compatible with the older ones as
long as the layout of struct cpu_features is identical.  The cpuid array
can be expanded with backward binary compatibility for both .o and .so
files.

Note: Although GCC has __builtin_cpu_supports, it only supports a subset
of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE.  It
doesn't support HAS_CPU_FEATURE.
---
 NEWS                                          |   2 +
 manual/platform.texi                          |  23 ++
 sysdeps/unix/sysv/linux/i386/ld.abilist       |   1 +
 sysdeps/unix/sysv/linux/x86_64/64/ld.abilist  |   1 +
 sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |   1 +
 sysdeps/x86/Makefile                          |   1 +
 sysdeps/x86/Versions                          |   4 +-
 sysdeps/x86/dl-get-cpu-features.c             |   4 +-
 sysdeps/x86/include/cpu-features.h            | 207 ++++++++++++++++++
 .../{cpu-features.h => sys/platform/x86.h}    | 172 +--------------
 sysdeps/x86/tst-get-cpu-features.c            |   6 +-
 sysdeps/x86_64/fpu/math-tests-arch.h          |   8 +-
 sysdeps/x86_64/multiarch/test-multiarch.c     |  10 +-
 13 files changed, 264 insertions(+), 176 deletions(-)
 create mode 100644 sysdeps/x86/include/cpu-features.h
 rename sysdeps/x86/{cpu-features.h => sys/platform/x86.h} (77%)

diff --git a/NEWS b/NEWS
index a660fc59a8..ae7d1ece35 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,8 @@ Version 2.32
 
 Major new features:
 
+* Add <sys/platform/x86.h> to provide query macros for x86 CPU features.
+
 * Unicode 12.1.0 Support: Character encoding, character type info, and
   transliteration tables are all updated to Unicode 12.1.0, using
   generator scripts contributed by Mike FABIAN (Red Hat).
diff --git a/manual/platform.texi b/manual/platform.texi
index 504addc956..b5f00e5b8f 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,25 @@ all threads in the current process.  Setting the
 ordering on only the current thread is necessary.  All other flag bits are
 reserved.
 @end deftypefun
+
+@node X86
+@appendixsec X86-specific Facilities
+
+Facilities specific to X86 that are not specific to a particular
+operating system are declared in @file{sys/platform/x86.h}.
+
+@deftypefun {const struct cpu_features *} __x86_get_cpu_features (void)
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Return a pointer to x86 CPU feature structure used by query macros for x86
+CPU features.
+@end deftypefun
+
+@deftypefn Macro int HAS_CPU_FEATURE (@var{name})
+This macro returns a nonzero value (true) if the processor has the feature
+@var{name}.
+@end deftypefn
+
+@deftypefn Macro int CPU_FEATURE_USABLE (@var{name})
+This macro returns a nonzero value (true) if the processor has the feature
+@var{name} and the feature is supported by the operating system.
+@end deftypefn
diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
index 0478e22071..1226876689 100644
--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
+++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
@@ -3,3 +3,4 @@ GLIBC_2.1 __libc_stack_end D 0x4
 GLIBC_2.1 _dl_mcount F
 GLIBC_2.3 ___tls_get_addr F
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
index d3cdf7611e..886e57abd5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.2.5 __libc_stack_end D 0x8
 GLIBC_2.2.5 _dl_mcount F
 GLIBC_2.2.5 _r_debug D 0x28
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
index c70bccf782..0d2f8a2cc5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.16 __libc_stack_end D 0x4
 GLIBC_2.16 __tls_get_addr F
 GLIBC_2.16 _dl_mcount F
 GLIBC_2.16 _r_debug D 0x14
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index beab426f67..0e4d132803 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -4,6 +4,7 @@ endif
 
 ifeq ($(subdir),elf)
 sysdep-dl-routines += dl-get-cpu-features
+sysdep_headers += sys/platform/x86.h
 
 tests += tst-get-cpu-features tst-get-cpu-features-static
 tests-static += tst-get-cpu-features-static
diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions
index e02923708e..7e3139dbb1 100644
--- a/sysdeps/x86/Versions
+++ b/sysdeps/x86/Versions
@@ -1,5 +1,5 @@
 ld {
-  GLIBC_PRIVATE {
-    __get_cpu_features;
+  GLIBC_2.32 {
+    __x86_get_cpu_features;
   }
 }
diff --git a/sysdeps/x86/dl-get-cpu-features.c b/sysdeps/x86/dl-get-cpu-features.c
index 9d61cd56be..fa1a1caa87 100644
--- a/sysdeps/x86/dl-get-cpu-features.c
+++ b/sysdeps/x86/dl-get-cpu-features.c
@@ -18,10 +18,10 @@
 
 #include <ldsodefs.h>
 
-#undef __get_cpu_features
+#undef __x86_get_cpu_features
 
 const struct cpu_features *
-__get_cpu_features (void)
+__x86_get_cpu_features (void)
 {
   return &GLRO(dl_x86_cpu_features);
 }
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
new file mode 100644
index 0000000000..c6efa3f066
--- /dev/null
+++ b/sysdeps/x86/include/cpu-features.h
@@ -0,0 +1,207 @@
+/* Data structure for x86 CPU features.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef	_PRIVATE_CPU_FEATURES_H
+#define	_PRIVATE_CPU_FEATURES_H	1
+
+#ifdef _CPU_FEATURES_H
+# error this should be impossible
+#endif
+
+#ifndef _ISOMAC
+/* Get most of the contents from the public header, but we define a
+   different `struct cpu_features' type for private use.  */
+# define cpu_features		cpu_features_public
+# define __x86_get_cpu_features	__x86_get_cpu_features_public
+#endif
+
+#include <sysdeps/x86/sys/platform/x86.h>
+
+#ifndef _ISOMAC
+
+# undef	cpu_features
+# undef __x86_get_cpu_features
+# define __get_cpu_features	__x86_get_cpu_features
+
+enum
+{
+  /* The integer bit array index for the first set of preferred feature
+     bits.  */
+  PREFERRED_FEATURE_INDEX_1 = 0,
+  /* The current maximum size of the feature integer bit array.  */
+  PREFERRED_FEATURE_INDEX_MAX
+};
+
+# undef CPU_FEATURES_ARCH_P
+# define CPU_FEATURES_ARCH_P(ptr, name) \
+  ((ptr->feature_##name[index_arch_##name] & (bit_arch_##name)) != 0)
+
+/* HAS_ARCH_FEATURE evaluates to true if we may use the feature at
+   runtime.  */
+# define HAS_ARCH_FEATURE(name) \
+  CPU_FEATURES_ARCH_P (__x86_get_cpu_features (), name)
+/* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
+# undef CPU_FEATURE_USABLE
+# define CPU_FEATURE_USABLE(name) \
+  CPU_FEATURES_ARCH_P (__x86_get_cpu_features (), name##_Usable)
+
+/* USABLE_FEATURE_INDEX_1.  */
+# define feature_AVX_Usable			usable
+# define feature_AVX2_Usable			usable
+# define feature_AVX512F_Usable			usable
+# define feature_AVX512CD_Usable		usable
+# define feature_AVX512ER_Usable		usable
+# define feature_AVX512PF_Usable		usable
+# define feature_AVX512VL_Usable		usable
+# define feature_AVX512BW_Usable		usable
+# define feature_AVX512DQ_Usable		usable
+# define feature_AVX512_4FMAPS_Usable		usable
+# define feature_AVX512_4VNNIW_Usable		usable
+# define feature_AVX512_BITALG_Usable		usable
+# define feature_AVX512_IFMA_Usable		usable
+# define feature_AVX512_VBMI_Usable		usable
+# define feature_AVX512_VBMI2_Usable		usable
+# define feature_AVX512_VNNI_Usable		usable
+# define feature_AVX512_VPOPCNTDQ_Usable	usable
+# define feature_FMA_Usable			usable
+# define feature_FMA4_Usable			usable
+# define feature_VAES_Usable			usable
+# define feature_VPCLMULQDQ_Usable		usable
+# define feature_XOP_Usable			usable
+# define feature_XSAVEC_Usable			usable
+# define feature_F16C_Usable			usable
+# define feature_AVX512_VP2INTERSECT_Usable	usable
+# define feature_AVX512_BF16_Usable		usable
+# define feature_PKU_Usable			usable
+
+/* PREFERRED_FEATURE_INDEX_1.  */
+# define bit_arch_I586				(1u << 0)
+# define bit_arch_I686				(1u << 1)
+# define bit_arch_Fast_Rep_String		(1u << 2)
+# define bit_arch_Fast_Copy_Backward		(1u << 3)
+# define bit_arch_Fast_Unaligned_Load		(1u << 4)
+# define bit_arch_Fast_Unaligned_Copy		(1u << 5)
+# define bit_arch_Slow_BSF			(1u << 6)
+# define bit_arch_Slow_SSE4_2			(1u << 7)
+# define bit_arch_AVX_Fast_Unaligned_Load	(1u << 8)
+# define bit_arch_Prefer_MAP_32BIT_EXEC		(1u << 9)
+# define bit_arch_Prefer_PMINUB_for_stringop	(1u << 10)
+# define bit_arch_Prefer_No_VZEROUPPER		(1u << 11)
+# define bit_arch_Prefer_ERMS			(1u << 12)
+# define bit_arch_Prefer_FSRM			(1u << 13)
+# define bit_arch_Prefer_No_AVX512		(1u << 14)
+# define bit_arch_MathVec_Prefer_No_AVX512	(1u << 15)
+
+# define index_arch_Fast_Rep_String		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Copy_Backward		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_BSF			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Load		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_PMINUB_for_stringop 	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Copy		PREFERRED_FEATURE_INDEX_1
+# define index_arch_I586			PREFERRED_FEATURE_INDEX_1
+# define index_arch_I686			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_SSE4_2			PREFERRED_FEATURE_INDEX_1
+# define index_arch_AVX_Fast_Unaligned_Load	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_MAP_32BIT_EXEC	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_VZEROUPPER	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_ERMS			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_AVX512		PREFERRED_FEATURE_INDEX_1
+# define index_arch_MathVec_Prefer_No_AVX512	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_FSRM			PREFERRED_FEATURE_INDEX_1
+
+# define feature_Fast_Rep_String		preferred
+# define feature_Fast_Copy_Backward		preferred
+# define feature_Slow_BSF			preferred
+# define feature_Fast_Unaligned_Load		preferred
+# define feature_Prefer_PMINUB_for_stringop 	preferred
+# define feature_Fast_Unaligned_Copy		preferred
+# define feature_I586				preferred
+# define feature_I686				preferred
+# define feature_Slow_SSE4_2			preferred
+# define feature_AVX_Fast_Unaligned_Load	preferred
+# define feature_Prefer_MAP_32BIT_EXEC		preferred
+# define feature_Prefer_No_VZEROUPPER		preferred
+# define feature_Prefer_ERMS			preferred
+# define feature_Prefer_No_AVX512		preferred
+# define feature_MathVec_Prefer_No_AVX512	preferred
+# define feature_Prefer_FSRM			preferred
+
+/* XCR0 Feature flags.  */
+# define bit_XMM_state		(1u << 1)
+# define bit_YMM_state		(1u << 2)
+# define bit_Opmask_state	(1u << 5)
+# define bit_ZMM0_15_state	(1u << 6)
+# define bit_ZMM16_31_state	(1u << 7)
+
+struct cpu_features
+{
+  struct cpu_features_basic basic;
+  unsigned int *usable_p;
+  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
+  unsigned int usable[USABLE_FEATURE_INDEX_MAX];
+  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
+  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
+     int so that we use
+
+	sub xsave_state_size_offset(%rip) %RSP_LP
+
+     in _dl_runtime_resolve.  */
+  unsigned long int xsave_state_size;
+  /* The full state size for XSAVE when XSAVEC is disabled by
+
+     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
+   */
+  unsigned int xsave_state_full_size;
+  /* Data cache size for use in memory and string routines, typically
+     L1 size.  */
+  unsigned long int data_cache_size;
+  /* Shared cache size for use in memory and string routines, typically
+     L2 or L3 size.  */
+  unsigned long int shared_cache_size;
+  /* Threshold to use non temporal store.  */
+  unsigned long int non_temporal_threshold;
+};
+
+# if defined (_LIBC) && !IS_IN (nonlib)
+/* Unused for x86.  */
+#  define INIT_ARCH()
+#  define __x86_get_cpu_features()	(&GLRO(dl_x86_cpu_features))
+#  define x86_get_cpuid_registers(i) \
+       (&(GLRO(dl_x86_cpu_features).cpuid[i]))
+# endif
+
+# ifdef __x86_64__
+#  define HAS_CPUID 1
+# elif (defined __i586__ || defined __pentium__	\
+	|| defined __geode__ || defined __k6__)
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# elif defined __i486__
+#  define HAS_CPUID 0
+#  define HAS_I586 HAS_ARCH_FEATURE (I586)
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# else
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 1
+# endif
+
+#endif /* !_ISOMAC */
+
+#endif /* include/cpu-features.h */
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/sys/platform/x86.h
similarity index 77%
rename from sysdeps/x86/cpu-features.h
rename to sysdeps/x86/sys/platform/x86.h
index 574f055e0c..43e286cde3 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/sys/platform/x86.h
@@ -1,4 +1,5 @@
-/* This file is part of the GNU C Library.
+/* Data structure for x86 CPU features.
+   This file is part of the GNU C Library.
    Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,8 +16,8 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#ifndef cpu_features_h
-#define cpu_features_h
+#ifndef _SYS_PLATFORM_X86_H
+#define _SYS_PLATFORM_X86_H
 
 enum
 {
@@ -27,15 +28,6 @@ enum
   USABLE_FEATURE_INDEX_MAX
 };
 
-enum
-{
-  /* The integer bit array index for the first set of preferred feature
-     bits.  */
-  PREFERRED_FEATURE_INDEX_1 = 0,
-  /* The current maximum size of the feature integer bit array.  */
-  PREFERRED_FEATURE_INDEX_MAX
-};
-
 enum
 {
   COMMON_CPUID_INDEX_1 = 0,
@@ -80,51 +72,23 @@ struct cpu_features
   struct cpu_features_basic basic;
   unsigned int *usable_p;
   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
-  unsigned int usable[USABLE_FEATURE_INDEX_MAX];
-  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
-  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
-     int so that we use
-
-	sub xsave_state_size_offset(%rip) %RSP_LP
-
-     in _dl_runtime_resolve.  */
-  unsigned long int xsave_state_size;
-  /* The full state size for XSAVE when XSAVEC is disabled by
-
-     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
-   */
-  unsigned int xsave_state_full_size;
-  /* Data cache size for use in memory and string routines, typically
-     L1 size.  */
-  unsigned long int data_cache_size;
-  /* Shared cache size for use in memory and string routines, typically
-     L2 or L3 size.  */
-  unsigned long int shared_cache_size;
-  /* Threshold to use non temporal store.  */
-  unsigned long int non_temporal_threshold;
 };
 
-/* Used from outside of glibc to get access to the CPU features
-   structure.  */
-extern const struct cpu_features *__get_cpu_features (void)
+/* Get a pointer to the CPU features structure.  */
+extern const struct cpu_features *__x86_get_cpu_features (void)
      __attribute__ ((const));
 
-/* Only used directly in cpu-features.c.  */
-# define CPU_FEATURES_CPU_P(ptr, name) \
+#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_##name[index_arch_##name] & (bit_arch_##name)) != 0)
+#define CPU_FEATURES_ARCH_P(ptr, name) \
+  ((ptr->usable_p[index_arch_##name] & (bit_arch_##name)) != 0)
 
 /* HAS_CPU_FEATURE evaluates to true if CPU supports the feature.  */
 #define HAS_CPU_FEATURE(name) \
-  CPU_FEATURES_CPU_P (__get_cpu_features (), name)
-/* HAS_ARCH_FEATURE evaluates to true if we may use the feature at
-   runtime.  */
-# define HAS_ARCH_FEATURE(name) \
-  CPU_FEATURES_ARCH_P (__get_cpu_features (), name)
+  CPU_FEATURES_CPU_P (__x86_get_cpu_features (), name)
 /* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
 #define CPU_FEATURE_USABLE(name) \
-  HAS_ARCH_FEATURE (name##_Usable)
+  CPU_FEATURES_ARCH_P (__x86_get_cpu_features (), name##_Usable)
 
 /* Architecture features.  */
 
@@ -185,34 +149,6 @@ extern const struct cpu_features *__get_cpu_features (void)
 #define index_arch_AVX512_BF16_Usable		USABLE_FEATURE_INDEX_1
 #define index_arch_PKU_Usable			USABLE_FEATURE_INDEX_1
 
-#define feature_AVX_Usable			usable
-#define feature_AVX2_Usable			usable
-#define feature_AVX512F_Usable			usable
-#define feature_AVX512CD_Usable			usable
-#define feature_AVX512ER_Usable			usable
-#define feature_AVX512PF_Usable			usable
-#define feature_AVX512VL_Usable			usable
-#define feature_AVX512BW_Usable			usable
-#define feature_AVX512DQ_Usable			usable
-#define feature_AVX512_4FMAPS_Usable		usable
-#define feature_AVX512_4VNNIW_Usable		usable
-#define feature_AVX512_BITALG_Usable		usable
-#define feature_AVX512_IFMA_Usable		usable
-#define feature_AVX512_VBMI_Usable		usable
-#define feature_AVX512_VBMI2_Usable		usable
-#define feature_AVX512_VNNI_Usable		usable
-#define feature_AVX512_VPOPCNTDQ_Usable		usable
-#define feature_FMA_Usable			usable
-#define feature_FMA4_Usable			usable
-#define feature_VAES_Usable			usable
-#define feature_VPCLMULQDQ_Usable		usable
-#define feature_XOP_Usable			usable
-#define feature_XSAVEC_Usable			usable
-#define feature_F16C_Usable			usable
-#define feature_AVX512_VP2INTERSECT_Usable	usable
-#define feature_AVX512_BF16_Usable		usable
-#define feature_PKU_Usable			usable
-
 /* CPU features.  */
 
 /* COMMON_CPUID_INDEX_1.  */
@@ -761,88 +697,4 @@ extern const struct cpu_features *__get_cpu_features (void)
 /* EAX.  */
 #define reg_AVX512_BF16		eax
 
-/* FEATURE_INDEX_2.  */
-#define bit_arch_I586				(1u << 0)
-#define bit_arch_I686				(1u << 1)
-#define bit_arch_Fast_Rep_String		(1u << 2)
-#define bit_arch_Fast_Copy_Backward		(1u << 3)
-#define bit_arch_Fast_Unaligned_Load		(1u << 4)
-#define bit_arch_Fast_Unaligned_Copy		(1u << 5)
-#define bit_arch_Slow_BSF			(1u << 6)
-#define bit_arch_Slow_SSE4_2			(1u << 7)
-#define bit_arch_AVX_Fast_Unaligned_Load	(1u << 8)
-#define bit_arch_Prefer_MAP_32BIT_EXEC		(1u << 9)
-#define bit_arch_Prefer_PMINUB_for_stringop	(1u << 10)
-#define bit_arch_Prefer_No_VZEROUPPER		(1u << 11)
-#define bit_arch_Prefer_ERMS			(1u << 12)
-#define bit_arch_Prefer_FSRM			(1u << 13)
-#define bit_arch_Prefer_No_AVX512		(1u << 14)
-#define bit_arch_MathVec_Prefer_No_AVX512	(1u << 15)
-
-#define index_arch_Fast_Rep_String		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Copy_Backward		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_BSF			PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Load		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_PMINUB_for_stringop 	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Copy		PREFERRED_FEATURE_INDEX_1
-#define index_arch_I586				PREFERRED_FEATURE_INDEX_1
-#define index_arch_I686				PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_SSE4_2			PREFERRED_FEATURE_INDEX_1
-#define index_arch_AVX_Fast_Unaligned_Load	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_MAP_32BIT_EXEC	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_VZEROUPPER		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_ERMS			PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_AVX512		PREFERRED_FEATURE_INDEX_1
-#define index_arch_MathVec_Prefer_No_AVX512	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_FSRM			PREFERRED_FEATURE_INDEX_1
-
-#define feature_Fast_Rep_String			preferred
-#define feature_Fast_Copy_Backward		preferred
-#define feature_Slow_BSF			preferred
-#define feature_Fast_Unaligned_Load		preferred
-#define feature_Prefer_PMINUB_for_stringop 	preferred
-#define feature_Fast_Unaligned_Copy		preferred
-#define feature_I586				preferred
-#define feature_I686				preferred
-#define feature_Slow_SSE4_2			preferred
-#define feature_AVX_Fast_Unaligned_Load		preferred
-#define feature_Prefer_MAP_32BIT_EXEC		preferred
-#define feature_Prefer_No_VZEROUPPER		preferred
-#define feature_Prefer_ERMS			preferred
-#define feature_Prefer_No_AVX512		preferred
-#define feature_MathVec_Prefer_No_AVX512	preferred
-#define feature_Prefer_FSRM			preferred
-
-/* XCR0 Feature flags.  */
-#define bit_XMM_state		(1u << 1)
-#define bit_YMM_state		(1u << 2)
-#define bit_Opmask_state	(1u << 5)
-#define bit_ZMM0_15_state	(1u << 6)
-#define bit_ZMM16_31_state	(1u << 7)
-
-# 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]))
-# endif
-
-#ifdef __x86_64__
-# define HAS_CPUID 1
-#elif (defined __i586__ || defined __pentium__	\
-       || defined __geode__ || defined __k6__)
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#elif defined __i486__
-# define HAS_CPUID 0
-# define HAS_I586 HAS_ARCH_FEATURE (I586)
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#else
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 1
-#endif
-
-#endif  /* cpu_features_h */
+#endif  /* _SYS_PLATFORM_X86_H */
diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
index c60918cf00..c470bfb345 100644
--- a/sysdeps/x86/tst-get-cpu-features.c
+++ b/sysdeps/x86/tst-get-cpu-features.c
@@ -1,4 +1,4 @@
-/* Test case for x86 __get_cpu_features interface
+/* Test case for __x86_get_cpu_features interface
    Copyright (C) 2015-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -18,7 +18,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 #include <support/check.h>
 
 #define CHECK_CPU_FEATURE(name)		\
@@ -45,7 +45,7 @@ static const char * const cpu_kinds[] =
 static int
 do_test (void)
 {
-  const struct cpu_features *cpu_features = __get_cpu_features ();
+  const struct cpu_features *cpu_features = __x86_get_cpu_features ();
 
   switch (cpu_features->basic.kind)
     {
diff --git a/sysdeps/x86_64/fpu/math-tests-arch.h b/sysdeps/x86_64/fpu/math-tests-arch.h
index 435ddad991..cc3c2b0c11 100644
--- a/sysdeps/x86_64/fpu/math-tests-arch.h
+++ b/sysdeps/x86_64/fpu/math-tests-arch.h
@@ -16,7 +16,7 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 
 #if defined REQUIRE_AVX
 
@@ -24,7 +24,7 @@
 # define CHECK_ARCH_EXT                                        \
   do                                                           \
     {                                                          \
-      if (!HAS_ARCH_FEATURE (AVX_Usable)) return;              \
+      if (!CPU_FEATURE_USABLE (AVX)) return;                   \
     }                                                          \
   while (0)
 
@@ -34,7 +34,7 @@
 # define CHECK_ARCH_EXT                                        \
   do                                                           \
     {                                                          \
-      if (!HAS_ARCH_FEATURE (AVX2_Usable)) return;             \
+      if (!CPU_FEATURE_USABLE (AVX2)) return;                  \
     }                                                          \
   while (0)
 
@@ -44,7 +44,7 @@
 # define CHECK_ARCH_EXT                                        \
   do                                                           \
     {                                                          \
-      if (!HAS_ARCH_FEATURE (AVX512F_Usable)) return;          \
+      if (!CPU_FEATURE_USABLE (AVX512F)) return;               \
     }                                                          \
   while (0)
 
diff --git a/sysdeps/x86_64/multiarch/test-multiarch.c b/sysdeps/x86_64/multiarch/test-multiarch.c
index 317373ceda..9feaf057e5 100644
--- a/sysdeps/x86_64/multiarch/test-multiarch.c
+++ b/sysdeps/x86_64/multiarch/test-multiarch.c
@@ -16,7 +16,7 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -75,10 +75,10 @@ do_test (int argc, char **argv)
   int fails;
 
   get_cpuinfo ();
-  fails = check_proc ("avx", HAS_ARCH_FEATURE (AVX_Usable),
-		      "HAS_ARCH_FEATURE (AVX_Usable)");
-  fails += check_proc ("fma4", HAS_ARCH_FEATURE (FMA4_Usable),
-		       "HAS_ARCH_FEATURE (FMA4_Usable)");
+  fails = check_proc ("avx", CPU_FEATURE_USABLE (AVX),
+		      "CPU_FEATURE_USABLE (AVX)");
+  fails += check_proc ("fma4", CPU_FEATURE_USABLE (FMA4),
+		       "CPU_FEATURE_USABLE (FMA4)");
   fails += check_proc ("sse4_2", HAS_CPU_FEATURE (SSE4_2),
 		       "HAS_CPU_FEATURE (SSE4_2)");
   fails += check_proc ("sse4_1", HAS_CPU_FEATURE (SSE4_1)
-- 
2.26.2


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V4: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-22 23:14                     ` V4: " H.J. Lu
@ 2020-06-24 14:33                       ` Florian Weimer
  2020-06-24 20:04                         ` Adhemerval Zanella
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2020-06-24 14:33 UTC (permalink / raw)
  To: H.J. Lu; +Cc: H.J. Lu via Libc-alpha, Joseph Myers

* H. J. Lu:

> Here is the updated patch with
>
>  -- Macro: int HAS_CPU_FEATURE (NAME)
>      This macro returns a nonzero value (true) if the processor has the
>      feature NAME.
>
>  -- Macro: int CPU_FEATURE_USABLE (NAME)
>      This macro returns a nonzero value (true) if the processor has the
>      feature NAME and the feature is supported by the operating system.

This is indeed less confusing.  Thanks.

I'm still convinced we have a real use case for HAS_CPU_FEATURE.

Does anyone else want to comment on this?

Thanks,
Florian


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V4: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-24 14:33                       ` Florian Weimer
@ 2020-06-24 20:04                         ` Adhemerval Zanella
  2020-06-24 21:10                           ` H.J. Lu
  2020-06-24 22:07                           ` V4: " Joseph Myers
  0 siblings, 2 replies; 28+ messages in thread
From: Adhemerval Zanella @ 2020-06-24 20:04 UTC (permalink / raw)
  To: libc-alpha



On 24/06/2020 11:33, Florian Weimer via Libc-alpha wrote:
> * H. J. Lu:
> 
>> Here is the updated patch with
>>
>>  -- Macro: int HAS_CPU_FEATURE (NAME)
>>      This macro returns a nonzero value (true) if the processor has the
>>      feature NAME.
>>
>>  -- Macro: int CPU_FEATURE_USABLE (NAME)
>>      This macro returns a nonzero value (true) if the processor has the
>>      feature NAME and the feature is supported by the operating system.
> 
> This is indeed less confusing.  Thanks.
> 
> I'm still convinced we have a real use case for HAS_CPU_FEATURE.
> 
> Does anyone else want to comment on this?
> 
> Thanks,
> Florian
> 

Should we provide it only for __USE_GNU (_GNU_SOURCE)? And I guess that cpuid
is not expected to be extendable. The macro API is not my favorite way of 
doing it, but it looks ok.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V4: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-24 20:04                         ` Adhemerval Zanella
@ 2020-06-24 21:10                           ` H.J. Lu
  2020-06-25  7:33                             ` Florian Weimer
  2020-06-24 22:07                           ` V4: " Joseph Myers
  1 sibling, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2020-06-24 21:10 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library

On Wed, Jun 24, 2020 at 1:04 PM Adhemerval Zanella via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
>
>
> On 24/06/2020 11:33, Florian Weimer via Libc-alpha wrote:
> > * H. J. Lu:
> >
> >> Here is the updated patch with
> >>
> >>  -- Macro: int HAS_CPU_FEATURE (NAME)
> >>      This macro returns a nonzero value (true) if the processor has the
> >>      feature NAME.
> >>
> >>  -- Macro: int CPU_FEATURE_USABLE (NAME)
> >>      This macro returns a nonzero value (true) if the processor has the
> >>      feature NAME and the feature is supported by the operating system.
> >
> > This is indeed less confusing.  Thanks.
> >
> > I'm still convinced we have a real use case for HAS_CPU_FEATURE.
> >
> > Does anyone else want to comment on this?
> >
> > Thanks,
> > Florian
> >
>
> Should we provide it only for __USE_GNU (_GNU_SOURCE)? And I guess that cpuid

Do we do that for other <sys/platform/XXX.h> files?

> is not expected to be extendable. The macro API is not my favorite way of

We can expand the cpuid array.  We just need to add an alias to
__x86_get_cpu_features
with a new symbol version.

> doing it, but it looks ok.

I will check it in tomorrow if there are no further comments.

Thanks.

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V4: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-24 20:04                         ` Adhemerval Zanella
  2020-06-24 21:10                           ` H.J. Lu
@ 2020-06-24 22:07                           ` Joseph Myers
  1 sibling, 0 replies; 28+ messages in thread
From: Joseph Myers @ 2020-06-24 22:07 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

On Wed, 24 Jun 2020, Adhemerval Zanella via Libc-alpha wrote:

> Should we provide it only for __USE_GNU (_GNU_SOURCE)? And I guess that cpuid
> is not expected to be extendable. The macro API is not my favorite way of 
> doing it, but it looks ok.

The proposed header is glibc-specific.  Having __USE_GNU conditionals in 
such headers is questionable.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V4: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-24 21:10                           ` H.J. Lu
@ 2020-06-25  7:33                             ` Florian Weimer
  2020-06-25 12:30                               ` V5: " H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2020-06-25  7:33 UTC (permalink / raw)
  To: H.J. Lu via Libc-alpha

* H. J. Lu via Libc-alpha:

>> is not expected to be extendable. The macro API is not my favorite way of
>
> We can expand the cpuid array.  We just need to add an alias to
> __x86_get_cpu_features
> with a new symbol version.

Agreed, from a GNU gABI perspective.

However, for some distributions, this requirement will put hardware
enablement for new CPUs on hold until we have reworked our package
dependency generation, so that we can express symbol-specific version
information.  Debian & downstreams can already do this, with some manual
work, but Fedora & downstreams can only express versions on sonames.
(Without these changes, we would have to backport the entire GLIBC_2.33
symbol set to get __x86_get_cpu_features@GLIBC_2.33, for example.  This
is not something we will be able to do in all cases, depending on the
other changes that are going in.)

Even then, we can only backport such changes if a glibc release has
happened (so that we can be sure that the meaning of the symbol version
will not change again).

My proposal, where the index is passed to the function and the function
returns the flag word, does not have these issues: old glibcs will
simply return 0 flags, and the feature appears unusable/unavailable.
This is what already happens with your approach, too, if we use more
bits inside the existing array elements.

I'm not entirely opposed to enhancing the RPM dependency generation, but
I already tried once and couldn't get it done, and if I fail again, it
might seriously impact CPU hardware enablement in Red Hat Enterprise
Linux 9.  I hope this explains my reservations about this interface
design.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 28+ messages in thread

* V5: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-25  7:33                             ` Florian Weimer
@ 2020-06-25 12:30                               ` H.J. Lu
  2020-06-25 13:20                                 ` V6: " H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2020-06-25 12:30 UTC (permalink / raw)
  To: Florian Weimer; +Cc: H.J. Lu via Libc-alpha, Adhemerval Zanella

On Thu, Jun 25, 2020 at 09:33:26AM +0200, Florian Weimer wrote:
> * H. J. Lu via Libc-alpha:
> 
> >> is not expected to be extendable. The macro API is not my favorite way of
> >
> > We can expand the cpuid array.  We just need to add an alias to
> > __x86_get_cpu_features
> > with a new symbol version.
> 
> Agreed, from a GNU gABI perspective.
> 
> However, for some distributions, this requirement will put hardware
> enablement for new CPUs on hold until we have reworked our package
> dependency generation, so that we can express symbol-specific version
> information.  Debian & downstreams can already do this, with some manual
> work, but Fedora & downstreams can only express versions on sonames.
> (Without these changes, we would have to backport the entire GLIBC_2.33
> symbol set to get __x86_get_cpu_features@GLIBC_2.33, for example.  This
> is not something we will be able to do in all cases, depending on the
> other changes that are going in.)
> 
> Even then, we can only backport such changes if a glibc release has
> happened (so that we can be sure that the meaning of the symbol version
> will not change again).
> 
> My proposal, where the index is passed to the function and the function
> returns the flag word, does not have these issues: old glibcs will
> simply return 0 flags, and the feature appears unusable/unavailable.
> This is what already happens with your approach, too, if we use more
> bits inside the existing array elements.
> 
> I'm not entirely opposed to enhancing the RPM dependency generation, but
> I already tried once and couldn't get it done, and if I fail again, it
> might seriously impact CPU hardware enablement in Red Hat Enterprise
> Linux 9.  I hope this explains my reservations about this interface
> design.
> 

Thanks for your detailed explanation.  Here is the revised patch.
COMMON_CPUID_INDEX_MAX and USABLE_FEATURE_INDEX_MAX are passed to
__x86_get_cpu_features so that when USABLE_FEATURE_INDEX_MAX or
COMMON_CPUID_INDEX_MAX are increased to support new processor features,
__x86_get_cpu_features in the older glibc binaries returns NULL and
HAS_CPU_FEATURE/CPU_FEATURE_USABLE return falses on the new processor
feature.  No new symbol version is neeeded.

Any comments?

Thanks.

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

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

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

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

enum
{
  /* The integer bit array index for the first set of usable feature
     bits.  */
  USABLE_FEATURE_INDEX_1 = 0,
  /* The current maximum size of the feature integer bit array.  */
  USABLE_FEATURE_INDEX_MAX
};

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

struct cpu_features
{
  struct cpu_features_basic basic;
  unsigned int *usable_p;
  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
};

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

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

Note: Although GCC has __builtin_cpu_supports, it only supports a subset
of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE.  It
doesn't support HAS_CPU_FEATURE.
---
 NEWS                                          |   2 +
 manual/platform.texi                          |  23 ++
 sysdeps/unix/sysv/linux/i386/ld.abilist       |   1 +
 sysdeps/unix/sysv/linux/x86_64/64/ld.abilist  |   1 +
 sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |   1 +
 sysdeps/x86/Makefile                          |   1 +
 sysdeps/x86/Versions                          |   4 +-
 sysdeps/x86/dl-get-cpu-features.c             |   7 +-
 sysdeps/x86/include/cpu-features.h            | 216 ++++++++++++++++++
 .../{cpu-features.h => sys/platform/x86.h}    | 185 ++-------------
 sysdeps/x86/tst-get-cpu-features.c            |   8 +-
 sysdeps/x86_64/fpu/math-tests-arch.h          |   8 +-
 sysdeps/x86_64/multiarch/test-multiarch.c     |  10 +-
 13 files changed, 289 insertions(+), 178 deletions(-)
 create mode 100644 sysdeps/x86/include/cpu-features.h
 rename sysdeps/x86/{cpu-features.h => sys/platform/x86.h} (77%)

diff --git a/NEWS b/NEWS
index a660fc59a8..ae7d1ece35 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,8 @@ Version 2.32
 
 Major new features:
 
+* Add <sys/platform/x86.h> to provide query macros for x86 CPU features.
+
 * Unicode 12.1.0 Support: Character encoding, character type info, and
   transliteration tables are all updated to Unicode 12.1.0, using
   generator scripts contributed by Mike FABIAN (Red Hat).
diff --git a/manual/platform.texi b/manual/platform.texi
index 504addc956..4cc58fbc6a 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,25 @@ all threads in the current process.  Setting the
 ordering on only the current thread is necessary.  All other flag bits are
 reserved.
 @end deftypefun
+
+@node X86
+@appendixsec X86-specific Facilities
+
+Facilities specific to X86 that are not specific to a particular
+operating system are declared in @file{sys/platform/x86.h}.
+
+@deftypefun {const struct cpu_features *} __x86_get_cpu_features (unsigned int, unsigned int)
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Return a pointer to x86 CPU feature structure used by query macros for x86
+CPU features.
+@end deftypefun
+
+@deftypefn Macro int HAS_CPU_FEATURE (@var{name})
+This macro returns a nonzero value (true) if the processor has the feature
+@var{name}.
+@end deftypefn
+
+@deftypefn Macro int CPU_FEATURE_USABLE (@var{name})
+This macro returns a nonzero value (true) if the processor has the feature
+@var{name} and the feature is supported by the operating system.
+@end deftypefn
diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
index 0478e22071..1226876689 100644
--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
+++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
@@ -3,3 +3,4 @@ GLIBC_2.1 __libc_stack_end D 0x4
 GLIBC_2.1 _dl_mcount F
 GLIBC_2.3 ___tls_get_addr F
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
index d3cdf7611e..886e57abd5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.2.5 __libc_stack_end D 0x8
 GLIBC_2.2.5 _dl_mcount F
 GLIBC_2.2.5 _r_debug D 0x28
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
index c70bccf782..0d2f8a2cc5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.16 __libc_stack_end D 0x4
 GLIBC_2.16 __tls_get_addr F
 GLIBC_2.16 _dl_mcount F
 GLIBC_2.16 _r_debug D 0x14
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index beab426f67..0e4d132803 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -4,6 +4,7 @@ endif
 
 ifeq ($(subdir),elf)
 sysdep-dl-routines += dl-get-cpu-features
+sysdep_headers += sys/platform/x86.h
 
 tests += tst-get-cpu-features tst-get-cpu-features-static
 tests-static += tst-get-cpu-features-static
diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions
index e02923708e..7e3139dbb1 100644
--- a/sysdeps/x86/Versions
+++ b/sysdeps/x86/Versions
@@ -1,5 +1,5 @@
 ld {
-  GLIBC_PRIVATE {
-    __get_cpu_features;
+  GLIBC_2.32 {
+    __x86_get_cpu_features;
   }
 }
diff --git a/sysdeps/x86/dl-get-cpu-features.c b/sysdeps/x86/dl-get-cpu-features.c
index 9d61cd56be..68cdee26c1 100644
--- a/sysdeps/x86/dl-get-cpu-features.c
+++ b/sysdeps/x86/dl-get-cpu-features.c
@@ -18,10 +18,13 @@
 
 #include <ldsodefs.h>
 
-#undef __get_cpu_features
+#undef __x86_get_cpu_features
 
 const struct cpu_features *
-__get_cpu_features (void)
+__x86_get_cpu_features (unsigned int max_cpuid, unsigned int max_usable)
 {
+  if (max_cpuid > COMMON_CPUID_INDEX_MAX
+      || max_usable > USABLE_FEATURE_INDEX_MAX)
+    return NULL;
   return &GLRO(dl_x86_cpu_features);
 }
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
new file mode 100644
index 0000000000..8fe2e42e25
--- /dev/null
+++ b/sysdeps/x86/include/cpu-features.h
@@ -0,0 +1,216 @@
+/* Data structure for x86 CPU features.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef	_PRIVATE_CPU_FEATURES_H
+#define	_PRIVATE_CPU_FEATURES_H	1
+
+#ifdef _CPU_FEATURES_H
+# error this should be impossible
+#endif
+
+#ifndef _ISOMAC
+/* Get most of the contents from the public header, but we define a
+   different `struct cpu_features' type for private use.  */
+# define cpu_features		cpu_features_public
+# define __x86_get_cpu_features	__x86_get_cpu_features_public
+#endif
+
+#include <sysdeps/x86/sys/platform/x86.h>
+
+#ifndef _ISOMAC
+
+# undef	cpu_features
+# undef __x86_get_cpu_features
+# define __get_cpu_features() \
+  __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX, USABLE_FEATURE_INDEX_MAX)
+
+enum
+{
+  /* The integer bit array index for the first set of preferred feature
+     bits.  */
+  PREFERRED_FEATURE_INDEX_1 = 0,
+  /* The current maximum size of the feature integer bit array.  */
+  PREFERRED_FEATURE_INDEX_MAX
+};
+
+# undef CPU_FEATURES_ARCH_P
+# define CPU_FEATURES_ARCH_P(ptr, name) \
+  ((ptr->feature_##name[index_arch_##name] & (bit_arch_##name)) != 0)
+
+/* HAS_CPU_FEATURE evaluates to true if CPU supports the feature.  */
+# undef HAS_CPU_FEATURE
+# define HAS_CPU_FEATURE(name)						 \
+  CPU_FEATURES_CPU_P (__x86_get_cpu_features (COMMON_CPUID_INDEX_MAX,	 \
+					      USABLE_FEATURE_INDEX_MAX), \
+					      name)
+/* HAS_ARCH_FEATURE evaluates to true if we may use the feature at
+   runtime.  */
+# define HAS_ARCH_FEATURE(name)						  \
+  CPU_FEATURES_ARCH_P (__x86_get_cpu_features (COMMON_CPUID_INDEX_MAX,	  \
+					       USABLE_FEATURE_INDEX_MAX), \
+					       name)
+/* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
+# undef CPU_FEATURE_USABLE
+# define CPU_FEATURE_USABLE(name) \
+  CPU_FEATURES_ARCH_P (__x86_get_cpu_features (COMMON_CPUID_INDEX_MAX,	  \
+					       USABLE_FEATURE_INDEX_MAX), \
+					       name##_Usable)
+
+/* USABLE_FEATURE_INDEX_1.  */
+# define feature_AVX_Usable			usable
+# define feature_AVX2_Usable			usable
+# define feature_AVX512F_Usable			usable
+# define feature_AVX512CD_Usable		usable
+# define feature_AVX512ER_Usable		usable
+# define feature_AVX512PF_Usable		usable
+# define feature_AVX512VL_Usable		usable
+# define feature_AVX512BW_Usable		usable
+# define feature_AVX512DQ_Usable		usable
+# define feature_AVX512_4FMAPS_Usable		usable
+# define feature_AVX512_4VNNIW_Usable		usable
+# define feature_AVX512_BITALG_Usable		usable
+# define feature_AVX512_IFMA_Usable		usable
+# define feature_AVX512_VBMI_Usable		usable
+# define feature_AVX512_VBMI2_Usable		usable
+# define feature_AVX512_VNNI_Usable		usable
+# define feature_AVX512_VPOPCNTDQ_Usable	usable
+# define feature_FMA_Usable			usable
+# define feature_FMA4_Usable			usable
+# define feature_VAES_Usable			usable
+# define feature_VPCLMULQDQ_Usable		usable
+# define feature_XOP_Usable			usable
+# define feature_XSAVEC_Usable			usable
+# define feature_F16C_Usable			usable
+# define feature_AVX512_VP2INTERSECT_Usable	usable
+# define feature_AVX512_BF16_Usable		usable
+# define feature_PKU_Usable			usable
+
+/* PREFERRED_FEATURE_INDEX_1.  */
+# define bit_arch_I586				(1u << 0)
+# define bit_arch_I686				(1u << 1)
+# define bit_arch_Fast_Rep_String		(1u << 2)
+# define bit_arch_Fast_Copy_Backward		(1u << 3)
+# define bit_arch_Fast_Unaligned_Load		(1u << 4)
+# define bit_arch_Fast_Unaligned_Copy		(1u << 5)
+# define bit_arch_Slow_BSF			(1u << 6)
+# define bit_arch_Slow_SSE4_2			(1u << 7)
+# define bit_arch_AVX_Fast_Unaligned_Load	(1u << 8)
+# define bit_arch_Prefer_MAP_32BIT_EXEC		(1u << 9)
+# define bit_arch_Prefer_PMINUB_for_stringop	(1u << 10)
+# define bit_arch_Prefer_No_VZEROUPPER		(1u << 11)
+# define bit_arch_Prefer_ERMS			(1u << 12)
+# define bit_arch_Prefer_FSRM			(1u << 13)
+# define bit_arch_Prefer_No_AVX512		(1u << 14)
+# define bit_arch_MathVec_Prefer_No_AVX512	(1u << 15)
+
+# define index_arch_Fast_Rep_String		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Copy_Backward		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_BSF			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Load		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_PMINUB_for_stringop 	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Copy		PREFERRED_FEATURE_INDEX_1
+# define index_arch_I586			PREFERRED_FEATURE_INDEX_1
+# define index_arch_I686			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_SSE4_2			PREFERRED_FEATURE_INDEX_1
+# define index_arch_AVX_Fast_Unaligned_Load	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_MAP_32BIT_EXEC	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_VZEROUPPER	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_ERMS			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_AVX512		PREFERRED_FEATURE_INDEX_1
+# define index_arch_MathVec_Prefer_No_AVX512	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_FSRM			PREFERRED_FEATURE_INDEX_1
+
+# define feature_Fast_Rep_String		preferred
+# define feature_Fast_Copy_Backward		preferred
+# define feature_Slow_BSF			preferred
+# define feature_Fast_Unaligned_Load		preferred
+# define feature_Prefer_PMINUB_for_stringop 	preferred
+# define feature_Fast_Unaligned_Copy		preferred
+# define feature_I586				preferred
+# define feature_I686				preferred
+# define feature_Slow_SSE4_2			preferred
+# define feature_AVX_Fast_Unaligned_Load	preferred
+# define feature_Prefer_MAP_32BIT_EXEC		preferred
+# define feature_Prefer_No_VZEROUPPER		preferred
+# define feature_Prefer_ERMS			preferred
+# define feature_Prefer_No_AVX512		preferred
+# define feature_MathVec_Prefer_No_AVX512	preferred
+# define feature_Prefer_FSRM			preferred
+
+/* XCR0 Feature flags.  */
+# define bit_XMM_state		(1u << 1)
+# define bit_YMM_state		(1u << 2)
+# define bit_Opmask_state	(1u << 5)
+# define bit_ZMM0_15_state	(1u << 6)
+# define bit_ZMM16_31_state	(1u << 7)
+
+struct cpu_features
+{
+  struct cpu_features_basic basic;
+  unsigned int *usable_p;
+  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
+  unsigned int usable[USABLE_FEATURE_INDEX_MAX];
+  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
+  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
+     int so that we use
+
+	sub xsave_state_size_offset(%rip) %RSP_LP
+
+     in _dl_runtime_resolve.  */
+  unsigned long int xsave_state_size;
+  /* The full state size for XSAVE when XSAVEC is disabled by
+
+     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
+   */
+  unsigned int xsave_state_full_size;
+  /* Data cache size for use in memory and string routines, typically
+     L1 size.  */
+  unsigned long int data_cache_size;
+  /* Shared cache size for use in memory and string routines, typically
+     L2 or L3 size.  */
+  unsigned long int shared_cache_size;
+  /* Threshold to use non temporal store.  */
+  unsigned long int non_temporal_threshold;
+};
+
+# if defined (_LIBC) && !IS_IN (nonlib)
+/* Unused for x86.  */
+#  define INIT_ARCH()
+#  define __x86_get_cpu_features(c, u)	(&GLRO(dl_x86_cpu_features))
+# endif
+
+# ifdef __x86_64__
+#  define HAS_CPUID 1
+# elif (defined __i586__ || defined __pentium__	\
+	|| defined __geode__ || defined __k6__)
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# elif defined __i486__
+#  define HAS_CPUID 0
+#  define HAS_I586 HAS_ARCH_FEATURE (I586)
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# else
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 1
+# endif
+
+#endif /* !_ISOMAC */
+
+#endif /* include/cpu-features.h */
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/sys/platform/x86.h
similarity index 77%
rename from sysdeps/x86/cpu-features.h
rename to sysdeps/x86/sys/platform/x86.h
index 574f055e0c..6d0310892b 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/sys/platform/x86.h
@@ -1,4 +1,5 @@
-/* This file is part of the GNU C Library.
+/* Data structure for x86 CPU features.
+   This file is part of the GNU C Library.
    Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,8 +16,8 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#ifndef cpu_features_h
-#define cpu_features_h
+#ifndef _SYS_PLATFORM_X86_H
+#define _SYS_PLATFORM_X86_H
 
 enum
 {
@@ -27,15 +28,6 @@ enum
   USABLE_FEATURE_INDEX_MAX
 };
 
-enum
-{
-  /* The integer bit array index for the first set of preferred feature
-     bits.  */
-  PREFERRED_FEATURE_INDEX_1 = 0,
-  /* The current maximum size of the feature integer bit array.  */
-  PREFERRED_FEATURE_INDEX_MAX
-};
-
 enum
 {
   COMMON_CPUID_INDEX_1 = 0,
@@ -80,51 +72,32 @@ struct cpu_features
   struct cpu_features_basic basic;
   unsigned int *usable_p;
   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
-  unsigned int usable[USABLE_FEATURE_INDEX_MAX];
-  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
-  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
-     int so that we use
-
-	sub xsave_state_size_offset(%rip) %RSP_LP
-
-     in _dl_runtime_resolve.  */
-  unsigned long int xsave_state_size;
-  /* The full state size for XSAVE when XSAVEC is disabled by
-
-     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
-   */
-  unsigned int xsave_state_full_size;
-  /* Data cache size for use in memory and string routines, typically
-     L1 size.  */
-  unsigned long int data_cache_size;
-  /* Shared cache size for use in memory and string routines, typically
-     L2 or L3 size.  */
-  unsigned long int shared_cache_size;
-  /* Threshold to use non temporal store.  */
-  unsigned long int non_temporal_threshold;
 };
 
-/* Used from outside of glibc to get access to the CPU features
-   structure.  */
-extern const struct cpu_features *__get_cpu_features (void)
+/* Get a pointer to the CPU features structure.  */
+extern const struct cpu_features *__x86_get_cpu_features (unsigned int,
+							  unsigned int)
      __attribute__ ((const));
 
-/* Only used directly in cpu-features.c.  */
-# define CPU_FEATURES_CPU_P(ptr, name) \
+#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_##name[index_arch_##name] & (bit_arch_##name)) != 0)
+#define CPU_FEATURES_ARCH_P(ptr, name) \
+  ((ptr->usable_p[index_arch_##name] & (bit_arch_##name)) != 0)
 
 /* HAS_CPU_FEATURE evaluates to true if CPU supports the feature.  */
-#define HAS_CPU_FEATURE(name) \
-  CPU_FEATURES_CPU_P (__get_cpu_features (), name)
-/* HAS_ARCH_FEATURE evaluates to true if we may use the feature at
-   runtime.  */
-# define HAS_ARCH_FEATURE(name) \
-  CPU_FEATURES_ARCH_P (__get_cpu_features (), name)
+#define HAS_CPU_FEATURE(name)					\
+  (__extension__						\
+   ({ const struct cpu_features *__ptr =			\
+	__x86_get_cpu_features (COMMON_CPUID_INDEX_MAX,		\
+				USABLE_FEATURE_INDEX_MAX);	\
+      __ptr && CPU_FEATURES_CPU_P (__ptr, name); }))
 /* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
-#define CPU_FEATURE_USABLE(name) \
-  HAS_ARCH_FEATURE (name##_Usable)
+#define CPU_FEATURE_USABLE(name)				\
+  (__extension__						\
+   ({ const struct cpu_features *__ptr =			\
+	__x86_get_cpu_features (COMMON_CPUID_INDEX_MAX,		\
+				USABLE_FEATURE_INDEX_MAX);	\
+      __ptr && CPU_FEATURES_ARCH_P (__ptr, name##_Usable); }))
 
 /* Architecture features.  */
 
@@ -185,34 +158,6 @@ extern const struct cpu_features *__get_cpu_features (void)
 #define index_arch_AVX512_BF16_Usable		USABLE_FEATURE_INDEX_1
 #define index_arch_PKU_Usable			USABLE_FEATURE_INDEX_1
 
-#define feature_AVX_Usable			usable
-#define feature_AVX2_Usable			usable
-#define feature_AVX512F_Usable			usable
-#define feature_AVX512CD_Usable			usable
-#define feature_AVX512ER_Usable			usable
-#define feature_AVX512PF_Usable			usable
-#define feature_AVX512VL_Usable			usable
-#define feature_AVX512BW_Usable			usable
-#define feature_AVX512DQ_Usable			usable
-#define feature_AVX512_4FMAPS_Usable		usable
-#define feature_AVX512_4VNNIW_Usable		usable
-#define feature_AVX512_BITALG_Usable		usable
-#define feature_AVX512_IFMA_Usable		usable
-#define feature_AVX512_VBMI_Usable		usable
-#define feature_AVX512_VBMI2_Usable		usable
-#define feature_AVX512_VNNI_Usable		usable
-#define feature_AVX512_VPOPCNTDQ_Usable		usable
-#define feature_FMA_Usable			usable
-#define feature_FMA4_Usable			usable
-#define feature_VAES_Usable			usable
-#define feature_VPCLMULQDQ_Usable		usable
-#define feature_XOP_Usable			usable
-#define feature_XSAVEC_Usable			usable
-#define feature_F16C_Usable			usable
-#define feature_AVX512_VP2INTERSECT_Usable	usable
-#define feature_AVX512_BF16_Usable		usable
-#define feature_PKU_Usable			usable
-
 /* CPU features.  */
 
 /* COMMON_CPUID_INDEX_1.  */
@@ -761,88 +706,4 @@ extern const struct cpu_features *__get_cpu_features (void)
 /* EAX.  */
 #define reg_AVX512_BF16		eax
 
-/* FEATURE_INDEX_2.  */
-#define bit_arch_I586				(1u << 0)
-#define bit_arch_I686				(1u << 1)
-#define bit_arch_Fast_Rep_String		(1u << 2)
-#define bit_arch_Fast_Copy_Backward		(1u << 3)
-#define bit_arch_Fast_Unaligned_Load		(1u << 4)
-#define bit_arch_Fast_Unaligned_Copy		(1u << 5)
-#define bit_arch_Slow_BSF			(1u << 6)
-#define bit_arch_Slow_SSE4_2			(1u << 7)
-#define bit_arch_AVX_Fast_Unaligned_Load	(1u << 8)
-#define bit_arch_Prefer_MAP_32BIT_EXEC		(1u << 9)
-#define bit_arch_Prefer_PMINUB_for_stringop	(1u << 10)
-#define bit_arch_Prefer_No_VZEROUPPER		(1u << 11)
-#define bit_arch_Prefer_ERMS			(1u << 12)
-#define bit_arch_Prefer_FSRM			(1u << 13)
-#define bit_arch_Prefer_No_AVX512		(1u << 14)
-#define bit_arch_MathVec_Prefer_No_AVX512	(1u << 15)
-
-#define index_arch_Fast_Rep_String		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Copy_Backward		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_BSF			PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Load		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_PMINUB_for_stringop 	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Copy		PREFERRED_FEATURE_INDEX_1
-#define index_arch_I586				PREFERRED_FEATURE_INDEX_1
-#define index_arch_I686				PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_SSE4_2			PREFERRED_FEATURE_INDEX_1
-#define index_arch_AVX_Fast_Unaligned_Load	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_MAP_32BIT_EXEC	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_VZEROUPPER		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_ERMS			PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_AVX512		PREFERRED_FEATURE_INDEX_1
-#define index_arch_MathVec_Prefer_No_AVX512	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_FSRM			PREFERRED_FEATURE_INDEX_1
-
-#define feature_Fast_Rep_String			preferred
-#define feature_Fast_Copy_Backward		preferred
-#define feature_Slow_BSF			preferred
-#define feature_Fast_Unaligned_Load		preferred
-#define feature_Prefer_PMINUB_for_stringop 	preferred
-#define feature_Fast_Unaligned_Copy		preferred
-#define feature_I586				preferred
-#define feature_I686				preferred
-#define feature_Slow_SSE4_2			preferred
-#define feature_AVX_Fast_Unaligned_Load		preferred
-#define feature_Prefer_MAP_32BIT_EXEC		preferred
-#define feature_Prefer_No_VZEROUPPER		preferred
-#define feature_Prefer_ERMS			preferred
-#define feature_Prefer_No_AVX512		preferred
-#define feature_MathVec_Prefer_No_AVX512	preferred
-#define feature_Prefer_FSRM			preferred
-
-/* XCR0 Feature flags.  */
-#define bit_XMM_state		(1u << 1)
-#define bit_YMM_state		(1u << 2)
-#define bit_Opmask_state	(1u << 5)
-#define bit_ZMM0_15_state	(1u << 6)
-#define bit_ZMM16_31_state	(1u << 7)
-
-# 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]))
-# endif
-
-#ifdef __x86_64__
-# define HAS_CPUID 1
-#elif (defined __i586__ || defined __pentium__	\
-       || defined __geode__ || defined __k6__)
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#elif defined __i486__
-# define HAS_CPUID 0
-# define HAS_I586 HAS_ARCH_FEATURE (I586)
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#else
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 1
-#endif
-
-#endif  /* cpu_features_h */
+#endif  /* _SYS_PLATFORM_X86_H */
diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
index c60918cf00..f6e2cfc556 100644
--- a/sysdeps/x86/tst-get-cpu-features.c
+++ b/sysdeps/x86/tst-get-cpu-features.c
@@ -1,4 +1,4 @@
-/* Test case for x86 __get_cpu_features interface
+/* Test case for __x86_get_cpu_features interface
    Copyright (C) 2015-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -18,7 +18,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 #include <support/check.h>
 
 #define CHECK_CPU_FEATURE(name)		\
@@ -45,7 +45,9 @@ static const char * const cpu_kinds[] =
 static int
 do_test (void)
 {
-  const struct cpu_features *cpu_features = __get_cpu_features ();
+  const struct cpu_features *cpu_features
+    = __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX,
+			      USABLE_FEATURE_INDEX_MAX);
 
   switch (cpu_features->basic.kind)
     {
diff --git a/sysdeps/x86_64/fpu/math-tests-arch.h b/sysdeps/x86_64/fpu/math-tests-arch.h
index 435ddad991..cc3c2b0c11 100644
--- a/sysdeps/x86_64/fpu/math-tests-arch.h
+++ b/sysdeps/x86_64/fpu/math-tests-arch.h
@@ -16,7 +16,7 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 
 #if defined REQUIRE_AVX
 
@@ -24,7 +24,7 @@
 # define CHECK_ARCH_EXT                                        \
   do                                                           \
     {                                                          \
-      if (!HAS_ARCH_FEATURE (AVX_Usable)) return;              \
+      if (!CPU_FEATURE_USABLE (AVX)) return;                   \
     }                                                          \
   while (0)
 
@@ -34,7 +34,7 @@
 # define CHECK_ARCH_EXT                                        \
   do                                                           \
     {                                                          \
-      if (!HAS_ARCH_FEATURE (AVX2_Usable)) return;             \
+      if (!CPU_FEATURE_USABLE (AVX2)) return;                  \
     }                                                          \
   while (0)
 
@@ -44,7 +44,7 @@
 # define CHECK_ARCH_EXT                                        \
   do                                                           \
     {                                                          \
-      if (!HAS_ARCH_FEATURE (AVX512F_Usable)) return;          \
+      if (!CPU_FEATURE_USABLE (AVX512F)) return;               \
     }                                                          \
   while (0)
 
diff --git a/sysdeps/x86_64/multiarch/test-multiarch.c b/sysdeps/x86_64/multiarch/test-multiarch.c
index 317373ceda..9feaf057e5 100644
--- a/sysdeps/x86_64/multiarch/test-multiarch.c
+++ b/sysdeps/x86_64/multiarch/test-multiarch.c
@@ -16,7 +16,7 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -75,10 +75,10 @@ do_test (int argc, char **argv)
   int fails;
 
   get_cpuinfo ();
-  fails = check_proc ("avx", HAS_ARCH_FEATURE (AVX_Usable),
-		      "HAS_ARCH_FEATURE (AVX_Usable)");
-  fails += check_proc ("fma4", HAS_ARCH_FEATURE (FMA4_Usable),
-		       "HAS_ARCH_FEATURE (FMA4_Usable)");
+  fails = check_proc ("avx", CPU_FEATURE_USABLE (AVX),
+		      "CPU_FEATURE_USABLE (AVX)");
+  fails += check_proc ("fma4", CPU_FEATURE_USABLE (FMA4),
+		       "CPU_FEATURE_USABLE (FMA4)");
   fails += check_proc ("sse4_2", HAS_CPU_FEATURE (SSE4_2),
 		       "HAS_CPU_FEATURE (SSE4_2)");
   fails += check_proc ("sse4_1", HAS_CPU_FEATURE (SSE4_1)
-- 
2.26.2


^ permalink raw reply	[flat|nested] 28+ messages in thread

* V6: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-25 12:30                               ` V5: " H.J. Lu
@ 2020-06-25 13:20                                 ` H.J. Lu
  2020-06-26 12:52                                   ` H.J. Lu
  2020-06-29 16:13                                   ` Florian Weimer
  0 siblings, 2 replies; 28+ messages in thread
From: H.J. Lu @ 2020-06-25 13:20 UTC (permalink / raw)
  To: Florian Weimer, H.J. Lu via Libc-alpha, Adhemerval Zanella

On Thu, Jun 25, 2020 at 05:30:59AM -0700, H.J. Lu wrote:
> On Thu, Jun 25, 2020 at 09:33:26AM +0200, Florian Weimer wrote:
> > * H. J. Lu via Libc-alpha:
> > 
> > >> is not expected to be extendable. The macro API is not my favorite way of
> > >
> > > We can expand the cpuid array.  We just need to add an alias to
> > > __x86_get_cpu_features
> > > with a new symbol version.
> > 
> > Agreed, from a GNU gABI perspective.
> > 
> > However, for some distributions, this requirement will put hardware
> > enablement for new CPUs on hold until we have reworked our package
> > dependency generation, so that we can express symbol-specific version
> > information.  Debian & downstreams can already do this, with some manual
> > work, but Fedora & downstreams can only express versions on sonames.
> > (Without these changes, we would have to backport the entire GLIBC_2.33
> > symbol set to get __x86_get_cpu_features@GLIBC_2.33, for example.  This
> > is not something we will be able to do in all cases, depending on the
> > other changes that are going in.)
> > 
> > Even then, we can only backport such changes if a glibc release has
> > happened (so that we can be sure that the meaning of the symbol version
> > will not change again).
> > 
> > My proposal, where the index is passed to the function and the function
> > returns the flag word, does not have these issues: old glibcs will
> > simply return 0 flags, and the feature appears unusable/unavailable.
> > This is what already happens with your approach, too, if we use more
> > bits inside the existing array elements.
> > 
> > I'm not entirely opposed to enhancing the RPM dependency generation, but
> > I already tried once and couldn't get it done, and if I fail again, it
> > might seriously impact CPU hardware enablement in Red Hat Enterprise
> > Linux 9.  I hope this explains my reservations about this interface
> > design.
> > 
> 
> Thanks for your detailed explanation.  Here is the revised patch.
> COMMON_CPUID_INDEX_MAX and USABLE_FEATURE_INDEX_MAX are passed to
> __x86_get_cpu_features so that when USABLE_FEATURE_INDEX_MAX or
> COMMON_CPUID_INDEX_MAX are increased to support new processor features,
> __x86_get_cpu_features in the older glibc binaries returns NULL and
> HAS_CPU_FEATURE/CPU_FEATURE_USABLE return falses on the new processor
> feature.  No new symbol version is neeeded.
> 
> Any comments?
> 

Small update:

const struct cpu_features *
__x86_get_cpu_features (unsigned int max, int cpuid)
{
  if (cpuid)
    {
      if (max > COMMON_CPUID_INDEX_MAX)
	return NULL;
    }
  else if (max > USABLE_FEATURE_INDEX_MAX)
    return NULL;
  return &GLRO(dl_x86_cpu_features);
}

Don't return NULL when checking the cpuid array when COMMON_CPUID_INDEX_MAX
is unchanged, but USABLE_FEATURE_INDEX_MAX is changed.

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

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

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

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

enum
{
  /* The integer bit array index for the first set of usable feature
     bits.  */
  USABLE_FEATURE_INDEX_1 = 0,
  /* The current maximum size of the feature integer bit array.  */
  USABLE_FEATURE_INDEX_MAX
};

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

struct cpu_features
{
  struct cpu_features_basic basic;
  unsigned int *usable_p;
  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
};

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

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

Note: Although GCC has __builtin_cpu_supports, it only supports a subset
of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE.  It
doesn't support HAS_CPU_FEATURE.
---
 NEWS                                          |   2 +
 manual/platform.texi                          |  27 +++
 sysdeps/unix/sysv/linux/i386/ld.abilist       |   1 +
 sysdeps/unix/sysv/linux/x86_64/64/ld.abilist  |   1 +
 sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist |   1 +
 sysdeps/x86/Makefile                          |   1 +
 sysdeps/x86/Versions                          |   4 +-
 sysdeps/x86/dl-get-cpu-features.c             |  11 +-
 sysdeps/x86/include/cpu-features.h            | 209 ++++++++++++++++++
 .../{cpu-features.h => sys/platform/x86.h}    | 183 ++-------------
 sysdeps/x86/tst-get-cpu-features.c            |   6 +-
 sysdeps/x86_64/fpu/math-tests-arch.h          |   8 +-
 sysdeps/x86_64/multiarch/test-multiarch.c     |  10 +-
 13 files changed, 286 insertions(+), 178 deletions(-)
 create mode 100644 sysdeps/x86/include/cpu-features.h
 rename sysdeps/x86/{cpu-features.h => sys/platform/x86.h} (77%)

diff --git a/NEWS b/NEWS
index a660fc59a8..ae7d1ece35 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,8 @@ Version 2.32
 
 Major new features:
 
+* Add <sys/platform/x86.h> to provide query macros for x86 CPU features.
+
 * Unicode 12.1.0 Support: Character encoding, character type info, and
   transliteration tables are all updated to Unicode 12.1.0, using
   generator scripts contributed by Mike FABIAN (Red Hat).
diff --git a/manual/platform.texi b/manual/platform.texi
index 504addc956..6c7cad9792 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,29 @@ all threads in the current process.  Setting the
 ordering on only the current thread is necessary.  All other flag bits are
 reserved.
 @end deftypefun
+
+@node X86
+@appendixsec X86-specific Facilities
+
+Facilities specific to X86 that are not specific to a particular
+operating system are declared in @file{sys/platform/x86.h}.
+
+@deftypefun {const struct cpu_features *} __x86_get_cpu_features
+(unsigned int @var{max}, int @var{cpuid})
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Return a pointer to x86 CPU feature structure used by query macros for x86
+CPU features.  If @var{cpuid} is non-zero and @var{max} exceeds
+@code{COMMON_CPUID_INDEX_MAX}, the function returns @code{NULL}.  If
+@var{cpuid} is zero and @var{max} exceeds
+@code{USABLE_FEATURE_INDEX_MAX}, the function returns @code{NULL}.
+@end deftypefun
+
+@deftypefn Macro int HAS_CPU_FEATURE (@var{name})
+This macro returns a nonzero value (true) if the processor has the feature
+@var{name}.
+@end deftypefn
+
+@deftypefn Macro int CPU_FEATURE_USABLE (@var{name})
+This macro returns a nonzero value (true) if the processor has the feature
+@var{name} and the feature is supported by the operating system.
+@end deftypefn
diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
index 0478e22071..1226876689 100644
--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
+++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
@@ -3,3 +3,4 @@ GLIBC_2.1 __libc_stack_end D 0x4
 GLIBC_2.1 _dl_mcount F
 GLIBC_2.3 ___tls_get_addr F
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
index d3cdf7611e..886e57abd5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.2.5 __libc_stack_end D 0x8
 GLIBC_2.2.5 _dl_mcount F
 GLIBC_2.2.5 _r_debug D 0x28
 GLIBC_2.3 __tls_get_addr F
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
index c70bccf782..0d2f8a2cc5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
@@ -2,3 +2,4 @@ GLIBC_2.16 __libc_stack_end D 0x4
 GLIBC_2.16 __tls_get_addr F
 GLIBC_2.16 _dl_mcount F
 GLIBC_2.16 _r_debug D 0x14
+GLIBC_2.32 __x86_get_cpu_features F
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index beab426f67..0e4d132803 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -4,6 +4,7 @@ endif
 
 ifeq ($(subdir),elf)
 sysdep-dl-routines += dl-get-cpu-features
+sysdep_headers += sys/platform/x86.h
 
 tests += tst-get-cpu-features tst-get-cpu-features-static
 tests-static += tst-get-cpu-features-static
diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions
index e02923708e..7e3139dbb1 100644
--- a/sysdeps/x86/Versions
+++ b/sysdeps/x86/Versions
@@ -1,5 +1,5 @@
 ld {
-  GLIBC_PRIVATE {
-    __get_cpu_features;
+  GLIBC_2.32 {
+    __x86_get_cpu_features;
   }
 }
diff --git a/sysdeps/x86/dl-get-cpu-features.c b/sysdeps/x86/dl-get-cpu-features.c
index 9d61cd56be..ba4df1d9e1 100644
--- a/sysdeps/x86/dl-get-cpu-features.c
+++ b/sysdeps/x86/dl-get-cpu-features.c
@@ -18,10 +18,17 @@
 
 #include <ldsodefs.h>
 
-#undef __get_cpu_features
+#undef __x86_get_cpu_features
 
 const struct cpu_features *
-__get_cpu_features (void)
+__x86_get_cpu_features (unsigned int max, int cpuid)
 {
+  if (cpuid)
+    {
+      if (max > COMMON_CPUID_INDEX_MAX)
+	return NULL;
+    }
+  else if (max > USABLE_FEATURE_INDEX_MAX)
+    return NULL;
   return &GLRO(dl_x86_cpu_features);
 }
diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
new file mode 100644
index 0000000000..9424b4a924
--- /dev/null
+++ b/sysdeps/x86/include/cpu-features.h
@@ -0,0 +1,209 @@
+/* Data structure for x86 CPU features.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef	_PRIVATE_CPU_FEATURES_H
+#define	_PRIVATE_CPU_FEATURES_H	1
+
+#ifdef _CPU_FEATURES_H
+# error this should be impossible
+#endif
+
+#ifndef _ISOMAC
+/* Get most of the contents from the public header, but we define a
+   different `struct cpu_features' type for private use.  */
+# define cpu_features		cpu_features_public
+# define __x86_get_cpu_features	__x86_get_cpu_features_public
+#endif
+
+#include <sysdeps/x86/sys/platform/x86.h>
+
+#ifndef _ISOMAC
+
+# undef	cpu_features
+# undef __x86_get_cpu_features
+# define __get_cpu_features()	__x86_get_cpu_features (0, 0)
+
+enum
+{
+  /* The integer bit array index for the first set of preferred feature
+     bits.  */
+  PREFERRED_FEATURE_INDEX_1 = 0,
+  /* The current maximum size of the feature integer bit array.  */
+  PREFERRED_FEATURE_INDEX_MAX
+};
+
+# undef CPU_FEATURES_ARCH_P
+# define CPU_FEATURES_ARCH_P(ptr, name) \
+  ((ptr->feature_##name[index_arch_##name] & (bit_arch_##name)) != 0)
+
+/* HAS_CPU_FEATURE evaluates to true if CPU supports the feature.  */
+# undef HAS_CPU_FEATURE
+# define HAS_CPU_FEATURE(name) \
+  CPU_FEATURES_CPU_P (__x86_get_cpu_features (0, 0), name)
+/* HAS_ARCH_FEATURE evaluates to true if we may use the feature at
+   runtime.  */
+# define HAS_ARCH_FEATURE(name)	\
+  CPU_FEATURES_ARCH_P (__x86_get_cpu_features (0, 0), name)
+/* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
+# undef CPU_FEATURE_USABLE
+# define CPU_FEATURE_USABLE(name) \
+  CPU_FEATURES_ARCH_P (__x86_get_cpu_features (0, 0), name##_Usable)
+
+/* USABLE_FEATURE_INDEX_1.  */
+# define feature_AVX_Usable			usable
+# define feature_AVX2_Usable			usable
+# define feature_AVX512F_Usable			usable
+# define feature_AVX512CD_Usable		usable
+# define feature_AVX512ER_Usable		usable
+# define feature_AVX512PF_Usable		usable
+# define feature_AVX512VL_Usable		usable
+# define feature_AVX512BW_Usable		usable
+# define feature_AVX512DQ_Usable		usable
+# define feature_AVX512_4FMAPS_Usable		usable
+# define feature_AVX512_4VNNIW_Usable		usable
+# define feature_AVX512_BITALG_Usable		usable
+# define feature_AVX512_IFMA_Usable		usable
+# define feature_AVX512_VBMI_Usable		usable
+# define feature_AVX512_VBMI2_Usable		usable
+# define feature_AVX512_VNNI_Usable		usable
+# define feature_AVX512_VPOPCNTDQ_Usable	usable
+# define feature_FMA_Usable			usable
+# define feature_FMA4_Usable			usable
+# define feature_VAES_Usable			usable
+# define feature_VPCLMULQDQ_Usable		usable
+# define feature_XOP_Usable			usable
+# define feature_XSAVEC_Usable			usable
+# define feature_F16C_Usable			usable
+# define feature_AVX512_VP2INTERSECT_Usable	usable
+# define feature_AVX512_BF16_Usable		usable
+# define feature_PKU_Usable			usable
+
+/* PREFERRED_FEATURE_INDEX_1.  */
+# define bit_arch_I586				(1u << 0)
+# define bit_arch_I686				(1u << 1)
+# define bit_arch_Fast_Rep_String		(1u << 2)
+# define bit_arch_Fast_Copy_Backward		(1u << 3)
+# define bit_arch_Fast_Unaligned_Load		(1u << 4)
+# define bit_arch_Fast_Unaligned_Copy		(1u << 5)
+# define bit_arch_Slow_BSF			(1u << 6)
+# define bit_arch_Slow_SSE4_2			(1u << 7)
+# define bit_arch_AVX_Fast_Unaligned_Load	(1u << 8)
+# define bit_arch_Prefer_MAP_32BIT_EXEC		(1u << 9)
+# define bit_arch_Prefer_PMINUB_for_stringop	(1u << 10)
+# define bit_arch_Prefer_No_VZEROUPPER		(1u << 11)
+# define bit_arch_Prefer_ERMS			(1u << 12)
+# define bit_arch_Prefer_FSRM			(1u << 13)
+# define bit_arch_Prefer_No_AVX512		(1u << 14)
+# define bit_arch_MathVec_Prefer_No_AVX512	(1u << 15)
+
+# define index_arch_Fast_Rep_String		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Copy_Backward		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_BSF			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Load		PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_PMINUB_for_stringop 	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Copy		PREFERRED_FEATURE_INDEX_1
+# define index_arch_I586			PREFERRED_FEATURE_INDEX_1
+# define index_arch_I686			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_SSE4_2			PREFERRED_FEATURE_INDEX_1
+# define index_arch_AVX_Fast_Unaligned_Load	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_MAP_32BIT_EXEC	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_VZEROUPPER	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_ERMS			PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_AVX512		PREFERRED_FEATURE_INDEX_1
+# define index_arch_MathVec_Prefer_No_AVX512	PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_FSRM			PREFERRED_FEATURE_INDEX_1
+
+# define feature_Fast_Rep_String		preferred
+# define feature_Fast_Copy_Backward		preferred
+# define feature_Slow_BSF			preferred
+# define feature_Fast_Unaligned_Load		preferred
+# define feature_Prefer_PMINUB_for_stringop 	preferred
+# define feature_Fast_Unaligned_Copy		preferred
+# define feature_I586				preferred
+# define feature_I686				preferred
+# define feature_Slow_SSE4_2			preferred
+# define feature_AVX_Fast_Unaligned_Load	preferred
+# define feature_Prefer_MAP_32BIT_EXEC		preferred
+# define feature_Prefer_No_VZEROUPPER		preferred
+# define feature_Prefer_ERMS			preferred
+# define feature_Prefer_No_AVX512		preferred
+# define feature_MathVec_Prefer_No_AVX512	preferred
+# define feature_Prefer_FSRM			preferred
+
+/* XCR0 Feature flags.  */
+# define bit_XMM_state		(1u << 1)
+# define bit_YMM_state		(1u << 2)
+# define bit_Opmask_state	(1u << 5)
+# define bit_ZMM0_15_state	(1u << 6)
+# define bit_ZMM16_31_state	(1u << 7)
+
+struct cpu_features
+{
+  struct cpu_features_basic basic;
+  unsigned int *usable_p;
+  struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
+  unsigned int usable[USABLE_FEATURE_INDEX_MAX];
+  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
+  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
+     int so that we use
+
+	sub xsave_state_size_offset(%rip) %RSP_LP
+
+     in _dl_runtime_resolve.  */
+  unsigned long int xsave_state_size;
+  /* The full state size for XSAVE when XSAVEC is disabled by
+
+     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
+   */
+  unsigned int xsave_state_full_size;
+  /* Data cache size for use in memory and string routines, typically
+     L1 size.  */
+  unsigned long int data_cache_size;
+  /* Shared cache size for use in memory and string routines, typically
+     L2 or L3 size.  */
+  unsigned long int shared_cache_size;
+  /* Threshold to use non temporal store.  */
+  unsigned long int non_temporal_threshold;
+};
+
+# if defined (_LIBC) && !IS_IN (nonlib)
+/* Unused for x86.  */
+#  define INIT_ARCH()
+#  define __x86_get_cpu_features(max, cpuid) (&GLRO(dl_x86_cpu_features))
+# endif
+
+# ifdef __x86_64__
+#  define HAS_CPUID 1
+# elif (defined __i586__ || defined __pentium__	\
+	|| defined __geode__ || defined __k6__)
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# elif defined __i486__
+#  define HAS_CPUID 0
+#  define HAS_I586 HAS_ARCH_FEATURE (I586)
+#  define HAS_I686 HAS_ARCH_FEATURE (I686)
+# else
+#  define HAS_CPUID 1
+#  define HAS_I586 1
+#  define HAS_I686 1
+# endif
+
+#endif /* !_ISOMAC */
+
+#endif /* include/cpu-features.h */
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/sys/platform/x86.h
similarity index 77%
rename from sysdeps/x86/cpu-features.h
rename to sysdeps/x86/sys/platform/x86.h
index 574f055e0c..62718c3a8d 100644
--- a/sysdeps/x86/cpu-features.h
+++ b/sysdeps/x86/sys/platform/x86.h
@@ -1,4 +1,5 @@
-/* This file is part of the GNU C Library.
+/* Data structure for x86 CPU features.
+   This file is part of the GNU C Library.
    Copyright (C) 2008-2020 Free Software Foundation, Inc.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -15,8 +16,8 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#ifndef cpu_features_h
-#define cpu_features_h
+#ifndef _SYS_PLATFORM_X86_H
+#define _SYS_PLATFORM_X86_H
 
 enum
 {
@@ -27,15 +28,6 @@ enum
   USABLE_FEATURE_INDEX_MAX
 };
 
-enum
-{
-  /* The integer bit array index for the first set of preferred feature
-     bits.  */
-  PREFERRED_FEATURE_INDEX_1 = 0,
-  /* The current maximum size of the feature integer bit array.  */
-  PREFERRED_FEATURE_INDEX_MAX
-};
-
 enum
 {
   COMMON_CPUID_INDEX_1 = 0,
@@ -80,51 +72,30 @@ struct cpu_features
   struct cpu_features_basic basic;
   unsigned int *usable_p;
   struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX];
-  unsigned int usable[USABLE_FEATURE_INDEX_MAX];
-  unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
-  /* The state size for XSAVEC or XSAVE.  The type must be unsigned long
-     int so that we use
-
-	sub xsave_state_size_offset(%rip) %RSP_LP
-
-     in _dl_runtime_resolve.  */
-  unsigned long int xsave_state_size;
-  /* The full state size for XSAVE when XSAVEC is disabled by
-
-     GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
-   */
-  unsigned int xsave_state_full_size;
-  /* Data cache size for use in memory and string routines, typically
-     L1 size.  */
-  unsigned long int data_cache_size;
-  /* Shared cache size for use in memory and string routines, typically
-     L2 or L3 size.  */
-  unsigned long int shared_cache_size;
-  /* Threshold to use non temporal store.  */
-  unsigned long int non_temporal_threshold;
 };
 
-/* Used from outside of glibc to get access to the CPU features
-   structure.  */
-extern const struct cpu_features *__get_cpu_features (void)
+/* Get a pointer to the CPU features structure.  */
+extern const struct cpu_features *__x86_get_cpu_features (unsigned int,
+							  int)
      __attribute__ ((const));
 
-/* Only used directly in cpu-features.c.  */
-# define CPU_FEATURES_CPU_P(ptr, name) \
+#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_##name[index_arch_##name] & (bit_arch_##name)) != 0)
+#define CPU_FEATURES_ARCH_P(ptr, name) \
+  ((ptr->usable_p[index_arch_##name] & (bit_arch_##name)) != 0)
 
 /* HAS_CPU_FEATURE evaluates to true if CPU supports the feature.  */
-#define HAS_CPU_FEATURE(name) \
-  CPU_FEATURES_CPU_P (__get_cpu_features (), name)
-/* HAS_ARCH_FEATURE evaluates to true if we may use the feature at
-   runtime.  */
-# define HAS_ARCH_FEATURE(name) \
-  CPU_FEATURES_ARCH_P (__get_cpu_features (), name)
+#define HAS_CPU_FEATURE(name)					\
+  (__extension__						\
+   ({ const struct cpu_features *__ptr =			\
+	__x86_get_cpu_features (COMMON_CPUID_INDEX_MAX, 1);	\
+      __ptr && CPU_FEATURES_CPU_P (__ptr, name); }))
 /* CPU_FEATURE_USABLE evaluates to true if the feature is usable.  */
-#define CPU_FEATURE_USABLE(name) \
-  HAS_ARCH_FEATURE (name##_Usable)
+#define CPU_FEATURE_USABLE(name)				\
+  (__extension__						\
+   ({ const struct cpu_features *__ptr =			\
+	__x86_get_cpu_features (USABLE_FEATURE_INDEX_MAX, 0);	\
+      __ptr && CPU_FEATURES_ARCH_P (__ptr, name##_Usable); }))
 
 /* Architecture features.  */
 
@@ -185,34 +156,6 @@ extern const struct cpu_features *__get_cpu_features (void)
 #define index_arch_AVX512_BF16_Usable		USABLE_FEATURE_INDEX_1
 #define index_arch_PKU_Usable			USABLE_FEATURE_INDEX_1
 
-#define feature_AVX_Usable			usable
-#define feature_AVX2_Usable			usable
-#define feature_AVX512F_Usable			usable
-#define feature_AVX512CD_Usable			usable
-#define feature_AVX512ER_Usable			usable
-#define feature_AVX512PF_Usable			usable
-#define feature_AVX512VL_Usable			usable
-#define feature_AVX512BW_Usable			usable
-#define feature_AVX512DQ_Usable			usable
-#define feature_AVX512_4FMAPS_Usable		usable
-#define feature_AVX512_4VNNIW_Usable		usable
-#define feature_AVX512_BITALG_Usable		usable
-#define feature_AVX512_IFMA_Usable		usable
-#define feature_AVX512_VBMI_Usable		usable
-#define feature_AVX512_VBMI2_Usable		usable
-#define feature_AVX512_VNNI_Usable		usable
-#define feature_AVX512_VPOPCNTDQ_Usable		usable
-#define feature_FMA_Usable			usable
-#define feature_FMA4_Usable			usable
-#define feature_VAES_Usable			usable
-#define feature_VPCLMULQDQ_Usable		usable
-#define feature_XOP_Usable			usable
-#define feature_XSAVEC_Usable			usable
-#define feature_F16C_Usable			usable
-#define feature_AVX512_VP2INTERSECT_Usable	usable
-#define feature_AVX512_BF16_Usable		usable
-#define feature_PKU_Usable			usable
-
 /* CPU features.  */
 
 /* COMMON_CPUID_INDEX_1.  */
@@ -761,88 +704,4 @@ extern const struct cpu_features *__get_cpu_features (void)
 /* EAX.  */
 #define reg_AVX512_BF16		eax
 
-/* FEATURE_INDEX_2.  */
-#define bit_arch_I586				(1u << 0)
-#define bit_arch_I686				(1u << 1)
-#define bit_arch_Fast_Rep_String		(1u << 2)
-#define bit_arch_Fast_Copy_Backward		(1u << 3)
-#define bit_arch_Fast_Unaligned_Load		(1u << 4)
-#define bit_arch_Fast_Unaligned_Copy		(1u << 5)
-#define bit_arch_Slow_BSF			(1u << 6)
-#define bit_arch_Slow_SSE4_2			(1u << 7)
-#define bit_arch_AVX_Fast_Unaligned_Load	(1u << 8)
-#define bit_arch_Prefer_MAP_32BIT_EXEC		(1u << 9)
-#define bit_arch_Prefer_PMINUB_for_stringop	(1u << 10)
-#define bit_arch_Prefer_No_VZEROUPPER		(1u << 11)
-#define bit_arch_Prefer_ERMS			(1u << 12)
-#define bit_arch_Prefer_FSRM			(1u << 13)
-#define bit_arch_Prefer_No_AVX512		(1u << 14)
-#define bit_arch_MathVec_Prefer_No_AVX512	(1u << 15)
-
-#define index_arch_Fast_Rep_String		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Copy_Backward		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_BSF			PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Load		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_PMINUB_for_stringop 	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Copy		PREFERRED_FEATURE_INDEX_1
-#define index_arch_I586				PREFERRED_FEATURE_INDEX_1
-#define index_arch_I686				PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_SSE4_2			PREFERRED_FEATURE_INDEX_1
-#define index_arch_AVX_Fast_Unaligned_Load	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_MAP_32BIT_EXEC	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_VZEROUPPER		PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_ERMS			PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_AVX512		PREFERRED_FEATURE_INDEX_1
-#define index_arch_MathVec_Prefer_No_AVX512	PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_FSRM			PREFERRED_FEATURE_INDEX_1
-
-#define feature_Fast_Rep_String			preferred
-#define feature_Fast_Copy_Backward		preferred
-#define feature_Slow_BSF			preferred
-#define feature_Fast_Unaligned_Load		preferred
-#define feature_Prefer_PMINUB_for_stringop 	preferred
-#define feature_Fast_Unaligned_Copy		preferred
-#define feature_I586				preferred
-#define feature_I686				preferred
-#define feature_Slow_SSE4_2			preferred
-#define feature_AVX_Fast_Unaligned_Load		preferred
-#define feature_Prefer_MAP_32BIT_EXEC		preferred
-#define feature_Prefer_No_VZEROUPPER		preferred
-#define feature_Prefer_ERMS			preferred
-#define feature_Prefer_No_AVX512		preferred
-#define feature_MathVec_Prefer_No_AVX512	preferred
-#define feature_Prefer_FSRM			preferred
-
-/* XCR0 Feature flags.  */
-#define bit_XMM_state		(1u << 1)
-#define bit_YMM_state		(1u << 2)
-#define bit_Opmask_state	(1u << 5)
-#define bit_ZMM0_15_state	(1u << 6)
-#define bit_ZMM16_31_state	(1u << 7)
-
-# 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]))
-# endif
-
-#ifdef __x86_64__
-# define HAS_CPUID 1
-#elif (defined __i586__ || defined __pentium__	\
-       || defined __geode__ || defined __k6__)
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#elif defined __i486__
-# define HAS_CPUID 0
-# define HAS_I586 HAS_ARCH_FEATURE (I586)
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#else
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 1
-#endif
-
-#endif  /* cpu_features_h */
+#endif  /* _SYS_PLATFORM_X86_H */
diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
index c60918cf00..60a18fed33 100644
--- a/sysdeps/x86/tst-get-cpu-features.c
+++ b/sysdeps/x86/tst-get-cpu-features.c
@@ -1,4 +1,4 @@
-/* Test case for x86 __get_cpu_features interface
+/* Test case for __x86_get_cpu_features interface
    Copyright (C) 2015-2020 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -18,7 +18,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 #include <support/check.h>
 
 #define CHECK_CPU_FEATURE(name)		\
@@ -45,7 +45,7 @@ static const char * const cpu_kinds[] =
 static int
 do_test (void)
 {
-  const struct cpu_features *cpu_features = __get_cpu_features ();
+  const struct cpu_features *cpu_features = __x86_get_cpu_features (0, 0);
 
   switch (cpu_features->basic.kind)
     {
diff --git a/sysdeps/x86_64/fpu/math-tests-arch.h b/sysdeps/x86_64/fpu/math-tests-arch.h
index 435ddad991..cc3c2b0c11 100644
--- a/sysdeps/x86_64/fpu/math-tests-arch.h
+++ b/sysdeps/x86_64/fpu/math-tests-arch.h
@@ -16,7 +16,7 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 
 #if defined REQUIRE_AVX
 
@@ -24,7 +24,7 @@
 # define CHECK_ARCH_EXT                                        \
   do                                                           \
     {                                                          \
-      if (!HAS_ARCH_FEATURE (AVX_Usable)) return;              \
+      if (!CPU_FEATURE_USABLE (AVX)) return;                   \
     }                                                          \
   while (0)
 
@@ -34,7 +34,7 @@
 # define CHECK_ARCH_EXT                                        \
   do                                                           \
     {                                                          \
-      if (!HAS_ARCH_FEATURE (AVX2_Usable)) return;             \
+      if (!CPU_FEATURE_USABLE (AVX2)) return;                  \
     }                                                          \
   while (0)
 
@@ -44,7 +44,7 @@
 # define CHECK_ARCH_EXT                                        \
   do                                                           \
     {                                                          \
-      if (!HAS_ARCH_FEATURE (AVX512F_Usable)) return;          \
+      if (!CPU_FEATURE_USABLE (AVX512F)) return;               \
     }                                                          \
   while (0)
 
diff --git a/sysdeps/x86_64/multiarch/test-multiarch.c b/sysdeps/x86_64/multiarch/test-multiarch.c
index 317373ceda..9feaf057e5 100644
--- a/sysdeps/x86_64/multiarch/test-multiarch.c
+++ b/sysdeps/x86_64/multiarch/test-multiarch.c
@@ -16,7 +16,7 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -75,10 +75,10 @@ do_test (int argc, char **argv)
   int fails;
 
   get_cpuinfo ();
-  fails = check_proc ("avx", HAS_ARCH_FEATURE (AVX_Usable),
-		      "HAS_ARCH_FEATURE (AVX_Usable)");
-  fails += check_proc ("fma4", HAS_ARCH_FEATURE (FMA4_Usable),
-		       "HAS_ARCH_FEATURE (FMA4_Usable)");
+  fails = check_proc ("avx", CPU_FEATURE_USABLE (AVX),
+		      "CPU_FEATURE_USABLE (AVX)");
+  fails += check_proc ("fma4", CPU_FEATURE_USABLE (FMA4),
+		       "CPU_FEATURE_USABLE (FMA4)");
   fails += check_proc ("sse4_2", HAS_CPU_FEATURE (SSE4_2),
 		       "HAS_CPU_FEATURE (SSE4_2)");
   fails += check_proc ("sse4_1", HAS_CPU_FEATURE (SSE4_1)
-- 
2.26.2


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V6: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-25 13:20                                 ` V6: " H.J. Lu
@ 2020-06-26 12:52                                   ` H.J. Lu
  2020-06-26 13:20                                     ` Florian Weimer
  2020-06-29 16:13                                   ` Florian Weimer
  1 sibling, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2020-06-26 12:52 UTC (permalink / raw)
  To: Florian Weimer, H.J. Lu via Libc-alpha, Adhemerval Zanella

On Thu, Jun 25, 2020 at 6:20 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Thu, Jun 25, 2020 at 05:30:59AM -0700, H.J. Lu wrote:
> > On Thu, Jun 25, 2020 at 09:33:26AM +0200, Florian Weimer wrote:
> > > * H. J. Lu via Libc-alpha:
> > >
> > > >> is not expected to be extendable. The macro API is not my favorite way of
> > > >
> > > > We can expand the cpuid array.  We just need to add an alias to
> > > > __x86_get_cpu_features
> > > > with a new symbol version.
> > >
> > > Agreed, from a GNU gABI perspective.
> > >
> > > However, for some distributions, this requirement will put hardware
> > > enablement for new CPUs on hold until we have reworked our package
> > > dependency generation, so that we can express symbol-specific version
> > > information.  Debian & downstreams can already do this, with some manual
> > > work, but Fedora & downstreams can only express versions on sonames.
> > > (Without these changes, we would have to backport the entire GLIBC_2.33
> > > symbol set to get __x86_get_cpu_features@GLIBC_2.33, for example.  This
> > > is not something we will be able to do in all cases, depending on the
> > > other changes that are going in.)
> > >
> > > Even then, we can only backport such changes if a glibc release has
> > > happened (so that we can be sure that the meaning of the symbol version
> > > will not change again).
> > >
> > > My proposal, where the index is passed to the function and the function
> > > returns the flag word, does not have these issues: old glibcs will
> > > simply return 0 flags, and the feature appears unusable/unavailable.
> > > This is what already happens with your approach, too, if we use more
> > > bits inside the existing array elements.
> > >
> > > I'm not entirely opposed to enhancing the RPM dependency generation, but
> > > I already tried once and couldn't get it done, and if I fail again, it
> > > might seriously impact CPU hardware enablement in Red Hat Enterprise
> > > Linux 9.  I hope this explains my reservations about this interface
> > > design.
> > >
> >
> > Thanks for your detailed explanation.  Here is the revised patch.
> > COMMON_CPUID_INDEX_MAX and USABLE_FEATURE_INDEX_MAX are passed to
> > __x86_get_cpu_features so that when USABLE_FEATURE_INDEX_MAX or
> > COMMON_CPUID_INDEX_MAX are increased to support new processor features,
> > __x86_get_cpu_features in the older glibc binaries returns NULL and
> > HAS_CPU_FEATURE/CPU_FEATURE_USABLE return falses on the new processor
> > feature.  No new symbol version is neeeded.
> >
> > Any comments?
> >
>
> Small update:
>
> const struct cpu_features *
> __x86_get_cpu_features (unsigned int max, int cpuid)
> {
>   if (cpuid)
>     {
>       if (max > COMMON_CPUID_INDEX_MAX)
>         return NULL;
>     }
>   else if (max > USABLE_FEATURE_INDEX_MAX)
>     return NULL;
>   return &GLRO(dl_x86_cpu_features);
> }
>
> Don't return NULL when checking the cpuid array when COMMON_CPUID_INDEX_MAX
> is unchanged, but USABLE_FEATURE_INDEX_MAX is changed.
>

Thanks for the feedbacks.  The latest patch:

https://sourceware.org/pipermail/libc-alpha/2020-June/115397.html

can be expanded to detect more CPU features without new symbol
versions.  Macros compiled against newer glibc headers will simply
return zero at run-time with older glibcs.  If there are no further
comments, I will check it in tomorrow.

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V6: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-26 12:52                                   ` H.J. Lu
@ 2020-06-26 13:20                                     ` Florian Weimer
  2020-06-26 13:44                                       ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2020-06-26 13:20 UTC (permalink / raw)
  To: H.J. Lu via Libc-alpha

* H. J. Lu via Libc-alpha:

> Thanks for the feedbacks.  The latest patch:
>
> https://sourceware.org/pipermail/libc-alpha/2020-June/115397.html
>
> can be expanded to detect more CPU features without new symbol
> versions.  Macros compiled against newer glibc headers will simply
> return zero at run-time with older glibcs.  If there are no further
> comments, I will check it in tomorrow.

I can do a review of this patch only on Monday.

We can make this feature a release blocker if you want.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V6: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-26 13:20                                     ` Florian Weimer
@ 2020-06-26 13:44                                       ` H.J. Lu
  0 siblings, 0 replies; 28+ messages in thread
From: H.J. Lu @ 2020-06-26 13:44 UTC (permalink / raw)
  To: Florian Weimer; +Cc: H.J. Lu via Libc-alpha, Adhemerval Zanella

On Fri, Jun 26, 2020 at 6:20 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu via Libc-alpha:
>
> > Thanks for the feedbacks.  The latest patch:
> >
> > https://sourceware.org/pipermail/libc-alpha/2020-June/115397.html
> >
> > can be expanded to detect more CPU features without new symbol
> > versions.  Macros compiled against newer glibc headers will simply
> > return zero at run-time with older glibcs.  If there are no further
> > comments, I will check it in tomorrow.
>
> I can do a review of this patch only on Monday.

Monday is fine.  Thanks.

> We can make this feature a release blocker if you want.
>

I have made it a release blocker.

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V6: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-25 13:20                                 ` V6: " H.J. Lu
  2020-06-26 12:52                                   ` H.J. Lu
@ 2020-06-29 16:13                                   ` Florian Weimer
  2020-06-29 16:44                                     ` H.J. Lu
  1 sibling, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2020-06-29 16:13 UTC (permalink / raw)
  To: H.J. Lu via Libc-alpha

* H. J. Lu via Libc-alpha:

> Small update:
>
> const struct cpu_features *
> __x86_get_cpu_features (unsigned int max, int cpuid)
> {
>   if (cpuid)
>     {
>       if (max > COMMON_CPUID_INDEX_MAX)
> 	return NULL;
>     }
>   else if (max > USABLE_FEATURE_INDEX_MAX)
>     return NULL;
>   return &GLRO(dl_x86_cpu_features);
> }
>
> Don't return NULL when checking the cpuid array when COMMON_CPUID_INDEX_MAX
> is unchanged, but USABLE_FEATURE_INDEX_MAX is changed.

I think these changes address the fundamental technical issues, thanks.

The patch needs to be rebased on top of
4fdd4d41a17dda26c854ed935658154a17d4b906 ("x86: Detect Intel Advanced
Matrix Extensions").

One thing I still dislike (sorry) is the asymmetry between the usable
and feature checks.  For example, why is there are usability check for
VAES, but not for AES?  I believe the reason is that VAES depends on
AVX/AVX2, but AES only depends on SSE2.  But even that suggests to me
that for 32-bit, there should be a usable gate for that (which is false
if SSE2 support has been masked).

I think it would be more consistent to expose the usable/feature
distinction for all features, and carry that over to the internal ABI,
too.  This way, we can give accurate reporting in cases where the
usability turned out to be firmware-dependent in the end (as it happened
with RDRAND).  That would need additional feature-specific work; by
default, we would still report such features as unsupported at the CPU
level.  Having both bits exposed in all cases also protects us against
cases where we need to change the usability detection logic in a later
release.

There is a bit of a tension here regarding agility because new usable
bits will only become set after glibc update.  But I don't see a way to
avoid this, not without teaching programmers to bypass the usable checks
(which leads to bugs, of course).

The interface with the max and cpuid arguments is quite close to the one
I proposed further up-thread.  I still think it has quite a few
advantages.  Should I implement it?  I could have something by the end
of the week, so we should still be able to make the ABI freeze.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V6: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-29 16:13                                   ` Florian Weimer
@ 2020-06-29 16:44                                     ` H.J. Lu
  2020-06-29 16:49                                       ` Florian Weimer
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2020-06-29 16:44 UTC (permalink / raw)
  To: Florian Weimer; +Cc: H.J. Lu via Libc-alpha, Adhemerval Zanella

On Mon, Jun 29, 2020 at 9:14 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu via Libc-alpha:
>
> > Small update:
> >
> > const struct cpu_features *
> > __x86_get_cpu_features (unsigned int max, int cpuid)
> > {
> >   if (cpuid)
> >     {
> >       if (max > COMMON_CPUID_INDEX_MAX)
> >       return NULL;
> >     }
> >   else if (max > USABLE_FEATURE_INDEX_MAX)
> >     return NULL;
> >   return &GLRO(dl_x86_cpu_features);
> > }
> >
> > Don't return NULL when checking the cpuid array when COMMON_CPUID_INDEX_MAX
> > is unchanged, but USABLE_FEATURE_INDEX_MAX is changed.
>
> I think these changes address the fundamental technical issues, thanks.
>
> The patch needs to be rebased on top of
> 4fdd4d41a17dda26c854ed935658154a17d4b906 ("x86: Detect Intel Advanced
> Matrix Extensions").

Yes, I have done that in my local repo.

> One thing I still dislike (sorry) is the asymmetry between the usable
> and feature checks.  For example, why is there are usability check for
> VAES, but not for AES?  I believe the reason is that VAES depends on
> AVX/AVX2, but AES only depends on SSE2.  But even that suggests to me
> that for 32-bit, there should be a usable gate for that (which is false
> if SSE2 support has been masked).

CPU with AES must have SSE2.  I don't think we need explicit check
for SSE2.

> I think it would be more consistent to expose the usable/feature
> distinction for all features, and carry that over to the internal ABI,
> too.  This way, we can give accurate reporting in cases where the
> usability turned out to be firmware-dependent in the end (as it happened
> with RDRAND).  That would need additional feature-specific work; by
> default, we would still report such features as unsupported at the CPU
> level.  Having both bits exposed in all cases also protects us against
> cases where we need to change the usability detection logic in a later
> release.

We can flip the bit on the usable array with a parallel unusable array
 of the cpuid array.  We can set the unusable bit if OS doesn't support
it.

> There is a bit of a tension here regarding agility because new usable
> bits will only become set after glibc update.  But I don't see a way to
> avoid this, not without teaching programmers to bypass the usable checks
> (which leads to bugs, of course).
>
> The interface with the max and cpuid arguments is quite close to the one
> I proposed further up-thread.  I still think it has quite a few
> advantages.  Should I implement it?  I could have something by the end
> of the week, so we should still be able to make the ABI freeze.

Let me rebase and change to the usable array.  We can go from there.

Thanks.

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V6: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-29 16:44                                     ` H.J. Lu
@ 2020-06-29 16:49                                       ` Florian Weimer
  2020-06-30  0:29                                         ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2020-06-29 16:49 UTC (permalink / raw)
  To: H.J. Lu; +Cc: H.J. Lu via Libc-alpha, Adhemerval Zanella

* H. J. Lu:

>> One thing I still dislike (sorry) is the asymmetry between the usable
>> and feature checks.  For example, why is there are usability check for
>> VAES, but not for AES?  I believe the reason is that VAES depends on
>> AVX/AVX2, but AES only depends on SSE2.  But even that suggests to me
>> that for 32-bit, there should be a usable gate for that (which is false
>> if SSE2 support has been masked).
>
> CPU with AES must have SSE2.  I don't think we need explicit check
> for SSE2.

But SSE2 needs operating system support, so we get the usable vs
available distinction this way.  I think.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V6: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-29 16:49                                       ` Florian Weimer
@ 2020-06-30  0:29                                         ` H.J. Lu
  2020-06-30  9:46                                           ` Florian Weimer
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2020-06-30  0:29 UTC (permalink / raw)
  To: Florian Weimer; +Cc: H.J. Lu via Libc-alpha, Adhemerval Zanella

On Mon, Jun 29, 2020 at 9:49 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> >> One thing I still dislike (sorry) is the asymmetry between the usable
> >> and feature checks.  For example, why is there are usability check for
> >> VAES, but not for AES?  I believe the reason is that VAES depends on
> >> AVX/AVX2, but AES only depends on SSE2.  But even that suggests to me
> >> that for 32-bit, there should be a usable gate for that (which is false
> >> if SSE2 support has been masked).
> >
> > CPU with AES must have SSE2.  I don't think we need explicit check
> > for SSE2.
>
> But SSE2 needs operating system support, so we get the usable vs
> available distinction this way.  I think.
>

We don't check if OS supports SSE2.


-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V6: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-30  0:29                                         ` H.J. Lu
@ 2020-06-30  9:46                                           ` Florian Weimer
  2020-06-30 12:19                                             ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2020-06-30  9:46 UTC (permalink / raw)
  To: H.J. Lu; +Cc: H.J. Lu via Libc-alpha, Adhemerval Zanella

* H. J. Lu:

> On Mon, Jun 29, 2020 at 9:49 AM Florian Weimer <fweimer@redhat.com> wrote:
>>
>> * H. J. Lu:
>>
>> >> One thing I still dislike (sorry) is the asymmetry between the usable
>> >> and feature checks.  For example, why is there are usability check for
>> >> VAES, but not for AES?  I believe the reason is that VAES depends on
>> >> AVX/AVX2, but AES only depends on SSE2.  But even that suggests to me
>> >> that for 32-bit, there should be a usable gate for that (which is false
>> >> if SSE2 support has been masked).
>> >
>> > CPU with AES must have SSE2.  I don't think we need explicit check
>> > for SSE2.
>>
>> But SSE2 needs operating system support, so we get the usable vs
>> available distinction this way.  I think.
>>
>
> We don't check if OS supports SSE2.

Isn't this a bug?  Not that it matters much these days, but how did this
work in the beginning?

Thanks,
Florian


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: V6: [PATCH] x86: Install <sys/platform/x86.h> [BZ #26124]
  2020-06-30  9:46                                           ` Florian Weimer
@ 2020-06-30 12:19                                             ` H.J. Lu
  0 siblings, 0 replies; 28+ messages in thread
From: H.J. Lu @ 2020-06-30 12:19 UTC (permalink / raw)
  To: Florian Weimer; +Cc: H.J. Lu via Libc-alpha, Adhemerval Zanella

On Tue, Jun 30, 2020 at 2:46 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> > On Mon, Jun 29, 2020 at 9:49 AM Florian Weimer <fweimer@redhat.com> wrote:
> >>
> >> * H. J. Lu:
> >>
> >> >> One thing I still dislike (sorry) is the asymmetry between the usable
> >> >> and feature checks.  For example, why is there are usability check for
> >> >> VAES, but not for AES?  I believe the reason is that VAES depends on
> >> >> AVX/AVX2, but AES only depends on SSE2.  But even that suggests to me
> >> >> that for 32-bit, there should be a usable gate for that (which is false
> >> >> if SSE2 support has been masked).
> >> >
> >> > CPU with AES must have SSE2.  I don't think we need explicit check
> >> > for SSE2.
> >>
> >> But SSE2 needs operating system support, so we get the usable vs
> >> available distinction this way.  I think.
> >>
> >
> > We don't check if OS supports SSE2.
>
> Isn't this a bug?  Not that it matters much these days, but how did this
> work in the beginning?

For SSE support, there is no straightforward way to detect OS support.
We just assume that the kernel supports SSE.

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2020-06-30 12:19 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-17 19:31 [PATCH] x86: Install <cpu-features.h> [BZ #26124] H.J. Lu
2020-06-17 20:54 ` Joseph Myers
2020-06-18  0:08   ` [PATCH] x86: Install <sys/platform/x86.h> " H.J. Lu
2020-06-18  8:45     ` Florian Weimer
2020-06-18 16:14       ` V2: " H.J. Lu
2020-06-22  9:09         ` Florian Weimer
2020-06-22 20:25           ` V3: " H.J. Lu
2020-06-22 20:41             ` Florian Weimer
2020-06-22 20:53               ` H.J. Lu
2020-06-22 21:14                 ` Florian Weimer
2020-06-22 22:18                   ` H.J. Lu
2020-06-22 23:14                     ` V4: " H.J. Lu
2020-06-24 14:33                       ` Florian Weimer
2020-06-24 20:04                         ` Adhemerval Zanella
2020-06-24 21:10                           ` H.J. Lu
2020-06-25  7:33                             ` Florian Weimer
2020-06-25 12:30                               ` V5: " H.J. Lu
2020-06-25 13:20                                 ` V6: " H.J. Lu
2020-06-26 12:52                                   ` H.J. Lu
2020-06-26 13:20                                     ` Florian Weimer
2020-06-26 13:44                                       ` H.J. Lu
2020-06-29 16:13                                   ` Florian Weimer
2020-06-29 16:44                                     ` H.J. Lu
2020-06-29 16:49                                       ` Florian Weimer
2020-06-30  0:29                                         ` H.J. Lu
2020-06-30  9:46                                           ` Florian Weimer
2020-06-30 12:19                                             ` H.J. Lu
2020-06-24 22:07                           ` V4: " Joseph Myers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).