V7: [PATCH 2/2] x86: Install <sys/platform/x86.h> [BZ #26124]
Commit Message
Install <sys/platform/x86.h> so that programmers can do
#if __has_include(<sys/platform/x86.h>)
#include <sys/platform/x86.h>
#endif
...
if (CPU_FEATURE_USABLE (SSE2))
...
if (CPU_FEATURE_USABLE (AVX2))
...
<sys/platform/x86.h> exports only:
enum
{
COMMON_CPUID_INDEX_1 = 0,
COMMON_CPUID_INDEX_7,
COMMON_CPUID_INDEX_80000001,
COMMON_CPUID_INDEX_D_ECX_1,
COMMON_CPUID_INDEX_80000007,
COMMON_CPUID_INDEX_80000008,
COMMON_CPUID_INDEX_7_ECX_1,
/* Keep the following line at the end. */
COMMON_CPUID_INDEX_MAX
};
struct cpuid_features
{
struct cpuid_registers cpuid;
struct cpuid_registers usable;
};
struct cpu_features
{
struct cpu_features_basic basic;
struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
};
/* Get a pointer to the CPU features structure. */
extern const struct cpu_features *__x86_get_cpu_features
(unsigned int max) __attribute__ ((const));
Since all feature checks are done through macros, programs compiled with
a newer <sys/platform/x86.h> are compatible with the older glibc binaries
as long as the layout of struct cpu_features is identical. The features
array can be expanded with backward binary compatibility for both .o and
.so files. When COMMON_CPUID_INDEX_MAX is increased to support new
processor features, __x86_get_cpu_features in the older glibc binaries
returns NULL and HAS_CPU_FEATURE/CPU_FEATURE_USABLE return falses on the
new processor feature. No new symbol version is neeeded.
Both CPU_FEATURE_USABLE and HAS_CPU_FEATURE are provided. HAS_CPU_FEATURE
can be used to identify processor features.
Note: Although GCC has __builtin_cpu_supports, it only supports a subset
of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE. It
doesn't support HAS_CPU_FEATURE.
---
NEWS | 2 +
manual/platform.texi | 24 +++
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 | 6 +-
sysdeps/x86/include/cpu-features.h | 179 ++++++++++++++++++
.../{cpu-features.h => sys/platform/x86.h} | 146 ++------------
sysdeps/x86/tst-get-cpu-features.c | 6 +-
sysdeps/x86_64/fpu/math-tests-arch.h | 2 +-
sysdeps/x86_64/multiarch/test-multiarch.c | 2 +-
13 files changed, 237 insertions(+), 138 deletions(-)
create mode 100644 sysdeps/x86/include/cpu-features.h
rename sysdeps/x86/{cpu-features.h => sys/platform/x86.h} (79%)
Comments
On Mon, Jun 29, 2020 at 9:35 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> Install <sys/platform/x86.h> so that programmers can do
>
> #if __has_include(<sys/platform/x86.h>)
> #include <sys/platform/x86.h>
> #endif
> ...
>
> if (CPU_FEATURE_USABLE (SSE2))
> ...
> if (CPU_FEATURE_USABLE (AVX2))
> ...
>
> <sys/platform/x86.h> exports only:
>
> enum
> {
> COMMON_CPUID_INDEX_1 = 0,
> COMMON_CPUID_INDEX_7,
> COMMON_CPUID_INDEX_80000001,
> COMMON_CPUID_INDEX_D_ECX_1,
> COMMON_CPUID_INDEX_80000007,
> COMMON_CPUID_INDEX_80000008,
> COMMON_CPUID_INDEX_7_ECX_1,
> /* Keep the following line at the end. */
> COMMON_CPUID_INDEX_MAX
> };
>
> struct cpuid_features
> {
> struct cpuid_registers cpuid;
> struct cpuid_registers usable;
> };
>
> struct cpu_features
> {
> struct cpu_features_basic basic;
> struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
> };
>
> /* Get a pointer to the CPU features structure. */
> extern const struct cpu_features *__x86_get_cpu_features
> (unsigned int max) __attribute__ ((const));
>
> Since all feature checks are done through macros, programs compiled with
> a newer <sys/platform/x86.h> are compatible with the older glibc binaries
> as long as the layout of struct cpu_features is identical. The features
> array can be expanded with backward binary compatibility for both .o and
> .so files. When COMMON_CPUID_INDEX_MAX is increased to support new
> processor features, __x86_get_cpu_features in the older glibc binaries
> returns NULL and HAS_CPU_FEATURE/CPU_FEATURE_USABLE return falses on the
> new processor feature. No new symbol version is neeeded.
>
> Both CPU_FEATURE_USABLE and HAS_CPU_FEATURE are provided. HAS_CPU_FEATURE
> can be used to identify processor features.
>
> Note: Although GCC has __builtin_cpu_supports, it only supports a subset
> of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE. It
> doesn't support HAS_CPU_FEATURE.
https://sourceware.org/pipermail/libc-alpha/2020-June/115546.html
On Wed, Jul 15, 2020 at 7:55 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, Jun 29, 2020 at 9:35 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > Install <sys/platform/x86.h> so that programmers can do
> >
> > #if __has_include(<sys/platform/x86.h>)
> > #include <sys/platform/x86.h>
> > #endif
> > ...
> >
> > if (CPU_FEATURE_USABLE (SSE2))
> > ...
> > if (CPU_FEATURE_USABLE (AVX2))
> > ...
> >
> > <sys/platform/x86.h> exports only:
> >
> > enum
> > {
> > COMMON_CPUID_INDEX_1 = 0,
> > COMMON_CPUID_INDEX_7,
> > COMMON_CPUID_INDEX_80000001,
> > COMMON_CPUID_INDEX_D_ECX_1,
> > COMMON_CPUID_INDEX_80000007,
> > COMMON_CPUID_INDEX_80000008,
> > COMMON_CPUID_INDEX_7_ECX_1,
> > /* Keep the following line at the end. */
> > COMMON_CPUID_INDEX_MAX
> > };
> >
> > struct cpuid_features
> > {
> > struct cpuid_registers cpuid;
> > struct cpuid_registers usable;
> > };
> >
> > struct cpu_features
> > {
> > struct cpu_features_basic basic;
> > struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
> > };
> >
> > /* Get a pointer to the CPU features structure. */
> > extern const struct cpu_features *__x86_get_cpu_features
> > (unsigned int max) __attribute__ ((const));
> >
> > Since all feature checks are done through macros, programs compiled with
> > a newer <sys/platform/x86.h> are compatible with the older glibc binaries
> > as long as the layout of struct cpu_features is identical. The features
> > array can be expanded with backward binary compatibility for both .o and
> > .so files. When COMMON_CPUID_INDEX_MAX is increased to support new
> > processor features, __x86_get_cpu_features in the older glibc binaries
> > returns NULL and HAS_CPU_FEATURE/CPU_FEATURE_USABLE return falses on the
> > new processor feature. No new symbol version is neeeded.
> >
> > Both CPU_FEATURE_USABLE and HAS_CPU_FEATURE are provided. HAS_CPU_FEATURE
> > can be used to identify processor features.
> >
> > Note: Although GCC has __builtin_cpu_supports, it only supports a subset
> > of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE. It
> > doesn't support HAS_CPU_FEATURE.
>
> https://sourceware.org/pipermail/libc-alpha/2020-June/115546.html
>
The first patch has been checked into master branch. The second patch is at:
https://sourceware.org/pipermail/libc-alpha/2020-June/115547.html
On 6/30/20 12:35 AM, H.J. Lu via Libc-alpha wrote:
> Install <sys/platform/x86.h> so that programmers can do
>
> #if __has_include(<sys/platform/x86.h>)
> #include <sys/platform/x86.h>
> #endif
> ...
>
> if (CPU_FEATURE_USABLE (SSE2))
> ...
> if (CPU_FEATURE_USABLE (AVX2))
> ...
>
> <sys/platform/x86.h> exports only:
>
> enum
> {
> COMMON_CPUID_INDEX_1 = 0,
> COMMON_CPUID_INDEX_7,
> COMMON_CPUID_INDEX_80000001,
> COMMON_CPUID_INDEX_D_ECX_1,
> COMMON_CPUID_INDEX_80000007,
> COMMON_CPUID_INDEX_80000008,
> COMMON_CPUID_INDEX_7_ECX_1,
> /* Keep the following line at the end. */
> COMMON_CPUID_INDEX_MAX
> };
>
> struct cpuid_features
> {
> struct cpuid_registers cpuid;
> struct cpuid_registers usable;
> };
>
> struct cpu_features
> {
> struct cpu_features_basic basic;
> struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
> };
>
> /* Get a pointer to the CPU features structure. */
> extern const struct cpu_features *__x86_get_cpu_features
> (unsigned int max) __attribute__ ((const));
>
> Since all feature checks are done through macros, programs compiled with
> a newer <sys/platform/x86.h> are compatible with the older glibc binaries
> as long as the layout of struct cpu_features is identical. The features
> array can be expanded with backward binary compatibility for both .o and
> .so files. When COMMON_CPUID_INDEX_MAX is increased to support new
> processor features, __x86_get_cpu_features in the older glibc binaries
> returns NULL and HAS_CPU_FEATURE/CPU_FEATURE_USABLE return falses on the
> new processor feature. No new symbol version is neeeded.
>
> Both CPU_FEATURE_USABLE and HAS_CPU_FEATURE are provided. HAS_CPU_FEATURE
> can be used to identify processor features.
>
> Note: Although GCC has __builtin_cpu_supports, it only supports a subset
> of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE. It
> doesn't support HAS_CPU_FEATURE.
I'm not sure this is ready for 2.32. I think we need to spend more time
writing how a user would use these and including them in the manual (and
contributing that to the linux man pages project which I can help with).
I also want to double check that this mechanism is really backwards and
forwards compatible and probably add some tests.
This code is going to get used by a lot of developers and x86_64 has
a very large installed user base. I'd like to see a little more review
for this and make sure we get it right. Likewise increase the quality
of the test coverage and use /proc/cpuinfo and __builtin_cpu_supports
to get that coverage.
Are you OK with waiting for when 2.33 opens to commit this? I can set
aside review time in August for this.
> ---
> NEWS | 2 +
> manual/platform.texi | 24 +++
> 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 | 6 +-
> sysdeps/x86/include/cpu-features.h | 179 ++++++++++++++++++
> .../{cpu-features.h => sys/platform/x86.h} | 146 ++------------
> sysdeps/x86/tst-get-cpu-features.c | 6 +-
> sysdeps/x86_64/fpu/math-tests-arch.h | 2 +-
> sysdeps/x86_64/multiarch/test-multiarch.c | 2 +-
> 13 files changed, 237 insertions(+), 138 deletions(-)
> create mode 100644 sysdeps/x86/include/cpu-features.h
> rename sysdeps/x86/{cpu-features.h => sys/platform/x86.h} (79%)
>
> 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..97727d656a 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,26 @@ 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}.
You need to explain what COMMON_CPUID_INDEX_* values are and how they
relate to the CPUID instruction.
You need to also explain what all the feature values are what they
mean.
> +
> +@deftypefun {const struct cpu_features *} __x86_get_cpu_features (unsigned int @var{max})
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +Return a pointer to x86 CPU feature structure used by query macros for x86
> +CPU features. If @var{max} exceeds @code{COMMON_CPUID_INDEX_MAX}, the
> +function returns @code{NULL}.
This needs to explain why this is important.
I'd like to see this manual express the following:
* Raising the max indicates you are requesting an increasing number of
CPUID categories will be queried and returned.
* If the max you indicate is higher than supported by the runtime then
you'll get a NULL.
We should have a short example snippet of code.
> +@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..5f9e46b0c6 100644
> --- a/sysdeps/x86/dl-get-cpu-features.c
> +++ b/sysdeps/x86/dl-get-cpu-features.c
> @@ -18,10 +18,12 @@
>
> #include <ldsodefs.h>
>
> -#undef __get_cpu_features
> +#undef __x86_get_cpu_features
>
> const struct cpu_features *
> -__get_cpu_features (void)
> +__x86_get_cpu_features (unsigned int max)
> {
> + if (max > COMMON_CPUID_INDEX_MAX)
> + return NULL;
> return &GLRO(dl_x86_cpu_features);
> }
> diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
> new file mode 100644
> index 0000000000..0f85b5b2dc
> --- /dev/null
> +++ b/sysdeps/x86/include/cpu-features.h
> @@ -0,0 +1,179 @@
> +/* Data structure for x86 CPU features.
> + Copyright (C) 2020 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _PRIVATE_CPU_FEATURES_H
> +#define _PRIVATE_CPU_FEATURES_H 1
> +
> +#ifdef _CPU_FEATURES_H
> +# error this should be impossible
> +#endif
> +
> +#ifndef _ISOMAC
> +/* Get most of the contents from the public header, but we define a
> + different `struct cpu_features' type for private use. */
> +# define cpu_features cpu_features_public
> +# define __x86_get_cpu_features __x86_get_cpu_features_public
> +#endif
> +
> +#include <sysdeps/x86/sys/platform/x86.h>
> +
> +#ifndef _ISOMAC
> +
> +# undef cpu_features
> +# undef __x86_get_cpu_features
> +# define __get_cpu_features() __x86_get_cpu_features (0)
> +
> +enum
> +{
> + /* The integer bit array index for the first set of preferred feature
> + bits. */
> + PREFERRED_FEATURE_INDEX_1 = 0,
> + /* The current maximum size of the feature integer bit array. */
> + PREFERRED_FEATURE_INDEX_MAX
> +};
> +
> +/* Only used directly in cpu-features.c. */
> +# define CPU_FEATURE_SET(ptr, name, check) \
> + ptr->features[index_cpu_##name].check.reg_##name |= bit_cpu_##name;
> +# define CPU_FEATURE_UNSET(ptr, name, check) \
> + ptr->features[index_cpu_##name].check.reg_##name &= ~bit_cpu_##name;
> +# define CPU_FEATURE_SET_USABLE(ptr, name) \
> + ptr->features[index_cpu_##name].usable.reg_##name \
> + |= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name;
> +# define CPU_FEATURE_PREFERRED_P(ptr, name) \
> + ((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0)
> +# define CPU_FEATURE_CPU_P(ptr, name) \
> + CPU_FEATURE_CHECK_P (ptr, name, cpuid)
> +
> +/* HAS_CPU_FEATURE evaluates to true if CPU supports the feature. */
> +# undef HAS_CPU_FEATURE
> +# define HAS_CPU_FEATURE(name) \
> + CPU_FEATURE_CPU_P (__x86_get_cpu_features (0), name)
> +/* CPU_FEATURE_USABLE evaluates to true if the feature is usable. */
> +# undef CPU_FEATURE_USABLE
> +# define CPU_FEATURE_USABLE(name) \
> + CPU_FEATURE_USABLE_P (__x86_get_cpu_features (0), name)
> +/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at
> + runtime. */
> +# define CPU_FEATURE_PREFERRED(name) \
> + CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name)
> +
> +# define CPU_FEATURES_CPU_P(ptr, name) \
> + CPU_FEATURE_CPU_P (ptr, name)
> +# define CPU_FEATURES_ARCH_P(ptr, name) \
> + CPU_FEATURE_PREFERRED_P (ptr, name)
> +# define HAS_ARCH_FEATURE(name) \
> + CPU_FEATURE_PREFERRED (name)
> +
> +/* PREFERRED_FEATURE_INDEX_1. */
> +# define bit_arch_I586 (1u << 0)
> +# define bit_arch_I686 (1u << 1)
> +# define bit_arch_Fast_Rep_String (1u << 2)
> +# define bit_arch_Fast_Copy_Backward (1u << 3)
> +# define bit_arch_Fast_Unaligned_Load (1u << 4)
> +# define bit_arch_Fast_Unaligned_Copy (1u << 5)
> +# define bit_arch_Slow_BSF (1u << 6)
> +# define bit_arch_Slow_SSE4_2 (1u << 7)
> +# define bit_arch_AVX_Fast_Unaligned_Load (1u << 8)
> +# define bit_arch_Prefer_MAP_32BIT_EXEC (1u << 9)
> +# define bit_arch_Prefer_PMINUB_for_stringop (1u << 10)
> +# define bit_arch_Prefer_No_VZEROUPPER (1u << 11)
> +# define bit_arch_Prefer_ERMS (1u << 12)
> +# define bit_arch_Prefer_FSRM (1u << 13)
> +# define bit_arch_Prefer_No_AVX512 (1u << 14)
> +# define bit_arch_MathVec_Prefer_No_AVX512 (1u << 15)
> +
> +# define index_arch_Fast_Rep_String PREFERRED_FEATURE_INDEX_1
> +# define index_arch_Fast_Copy_Backward PREFERRED_FEATURE_INDEX_1
> +# define index_arch_Slow_BSF PREFERRED_FEATURE_INDEX_1
> +# define index_arch_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1
> +# define index_arch_Prefer_PMINUB_for_stringop PREFERRED_FEATURE_INDEX_1
> +# define index_arch_Fast_Unaligned_Copy PREFERRED_FEATURE_INDEX_1
> +# define index_arch_I586 PREFERRED_FEATURE_INDEX_1
> +# define index_arch_I686 PREFERRED_FEATURE_INDEX_1
> +# define index_arch_Slow_SSE4_2 PREFERRED_FEATURE_INDEX_1
> +# define index_arch_AVX_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1
> +# define index_arch_Prefer_MAP_32BIT_EXEC PREFERRED_FEATURE_INDEX_1
> +# define index_arch_Prefer_No_VZEROUPPER PREFERRED_FEATURE_INDEX_1
> +# define index_arch_Prefer_ERMS PREFERRED_FEATURE_INDEX_1
> +# define index_arch_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1
> +# define index_arch_MathVec_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1
> +# define index_arch_Prefer_FSRM PREFERRED_FEATURE_INDEX_1
> +
> +/* XCR0 Feature flags. */
> +# define bit_XMM_state (1u << 1)
> +# define bit_YMM_state (1u << 2)
> +# define bit_Opmask_state (1u << 5)
> +# define bit_ZMM0_15_state (1u << 6)
> +# define bit_ZMM16_31_state (1u << 7)
> +# define bit_XTILECFG_state (1u << 17)
> +# define bit_XTILEDATA_state (1u << 18)
> +
> +struct cpu_features
> +{
> + struct cpu_features_basic basic;
> + struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
> + unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
> + /* The state size for XSAVEC or XSAVE. The type must be unsigned long
> + int so that we use
> +
> + sub xsave_state_size_offset(%rip) %RSP_LP
> +
> + in _dl_runtime_resolve. */
> + unsigned long int xsave_state_size;
> + /* The full state size for XSAVE when XSAVEC is disabled by
> +
> + GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_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) (&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 79%
> rename from sysdeps/x86/cpu-features.h
> rename to sysdeps/x86/sys/platform/x86.h
> index d3e930befc..6a1357b715 100644
> --- a/sysdeps/x86/cpu-features.h
> +++ b/sysdeps/x86/sys/platform/x86.h
> @@ -1,4 +1,5 @@
> -/* This file is part of the GNU C Library.
> +/* Data structure for x86 CPU features.
> + This file is part of the GNU C Library.
> Copyright (C) 2008-2020 Free Software Foundation, Inc.
>
> The GNU C Library is free software; you can redistribute it and/or
> @@ -15,17 +16,8 @@
> License along with the GNU C Library; if not, see
> <https://www.gnu.org/licenses/>. */
>
> -#ifndef cpu_features_h
> -#define cpu_features_h
> -
> -enum
> -{
> - /* The integer bit array index for the first set of preferred feature
> - bits. */
> - PREFERRED_FEATURE_INDEX_1 = 0,
> - /* The current maximum size of the feature integer bit array. */
> - PREFERRED_FEATURE_INDEX_MAX
> -};
> +#ifndef _SYS_PLATFORM_X86_H
> +#define _SYS_PLATFORM_X86_H
>
> enum
> {
> @@ -76,69 +68,32 @@ struct cpu_features
> {
> struct cpu_features_basic basic;
> struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
> - unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
> - /* The state size for XSAVEC or XSAVE. The type must be unsigned long
> - int so that we use
> -
> - sub xsave_state_size_offset(%rip) %RSP_LP
> -
> - in _dl_runtime_resolve. */
> - unsigned long int xsave_state_size;
> - /* The full state size for XSAVE when XSAVEC is disabled by
> -
> - GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_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)
> __attribute__ ((const));
>
> -/* Only used directly in cpu-features.c. */
> #define CPU_FEATURE_CHECK_P(ptr, name, check) \
> ((ptr->features[index_cpu_##name].check.reg_##name \
> & bit_cpu_##name) != 0)
> -#define CPU_FEATURE_SET(ptr, name, check) \
> - ptr->features[index_cpu_##name].check.reg_##name |= bit_cpu_##name;
> -#define CPU_FEATURE_UNSET(ptr, name, check) \
> - ptr->features[index_cpu_##name].check.reg_##name &= ~bit_cpu_##name;
> -#define CPU_FEATURE_SET_USABLE(ptr, name) \
> - ptr->features[index_cpu_##name].usable.reg_##name \
> - |= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name;
> -#define CPU_FEATURE_PREFERRED_P(ptr, name) \
> - ((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0)
> #define CPU_FEATURE_CPU_P(ptr, name) \
> CPU_FEATURE_CHECK_P (ptr, name, cpuid)
> #define CPU_FEATURE_USABLE_P(ptr, name) \
> CPU_FEATURE_CHECK_P (ptr, name, usable)
>
> /* HAS_CPU_FEATURE evaluates to true if CPU supports the feature. */
> -#define HAS_CPU_FEATURE(name) \
> - CPU_FEATURE_CPU_P (__get_cpu_features (), name)
> +#define HAS_CPU_FEATURE(name) \
> + (__extension__ \
> + ({ const struct cpu_features *__ptr = \
> + __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX); \
> + __ptr && CPU_FEATURE_CPU_P (__ptr, name); }))
> /* CPU_FEATURE_USABLE evaluates to true if the feature is usable. */
> -#define CPU_FEATURE_USABLE(name) \
> - CPU_FEATURE_USABLE_P (__get_cpu_features (), name)
> -/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at
> - runtime. */
> -#define CPU_FEATURE_PREFERRED(name) \
> - CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name)
> -
> -#define CPU_FEATURES_CPU_P(ptr, name) \
> - CPU_FEATURE_CPU_P (ptr, name)
> -#define CPU_FEATURES_ARCH_P(ptr, name) \
> - CPU_FEATURE_PREFERRED_P (ptr, name)
> -#define HAS_ARCH_FEATURE(name) \
> - CPU_FEATURE_PREFERRED (name)
> +#define CPU_FEATURE_USABLE(name) \
> + (__extension__ \
> + ({ const struct cpu_features *__ptr = \
> + __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX); \
> + __ptr && CPU_FEATURE_USABLE_P (__ptr, name); }))
>
> /* CPU features. */
>
> @@ -697,71 +652,4 @@ extern const struct cpu_features *__get_cpu_features (void)
> /* EAX. */
> #define reg_AVX512_BF16 eax
>
> -/* FEATURE_INDEX_2. */
> -#define bit_arch_I586 (1u << 0)
> -#define bit_arch_I686 (1u << 1)
> -#define bit_arch_Fast_Rep_String (1u << 2)
> -#define bit_arch_Fast_Copy_Backward (1u << 3)
> -#define bit_arch_Fast_Unaligned_Load (1u << 4)
> -#define bit_arch_Fast_Unaligned_Copy (1u << 5)
> -#define bit_arch_Slow_BSF (1u << 6)
> -#define bit_arch_Slow_SSE4_2 (1u << 7)
> -#define bit_arch_AVX_Fast_Unaligned_Load (1u << 8)
> -#define bit_arch_Prefer_MAP_32BIT_EXEC (1u << 9)
> -#define bit_arch_Prefer_PMINUB_for_stringop (1u << 10)
> -#define bit_arch_Prefer_No_VZEROUPPER (1u << 11)
> -#define bit_arch_Prefer_ERMS (1u << 12)
> -#define bit_arch_Prefer_FSRM (1u << 13)
> -#define bit_arch_Prefer_No_AVX512 (1u << 14)
> -#define bit_arch_MathVec_Prefer_No_AVX512 (1u << 15)
> -
> -#define index_arch_Fast_Rep_String PREFERRED_FEATURE_INDEX_1
> -#define index_arch_Fast_Copy_Backward PREFERRED_FEATURE_INDEX_1
> -#define index_arch_Slow_BSF PREFERRED_FEATURE_INDEX_1
> -#define index_arch_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1
> -#define index_arch_Prefer_PMINUB_for_stringop PREFERRED_FEATURE_INDEX_1
> -#define index_arch_Fast_Unaligned_Copy PREFERRED_FEATURE_INDEX_1
> -#define index_arch_I586 PREFERRED_FEATURE_INDEX_1
> -#define index_arch_I686 PREFERRED_FEATURE_INDEX_1
> -#define index_arch_Slow_SSE4_2 PREFERRED_FEATURE_INDEX_1
> -#define index_arch_AVX_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1
> -#define index_arch_Prefer_MAP_32BIT_EXEC PREFERRED_FEATURE_INDEX_1
> -#define index_arch_Prefer_No_VZEROUPPER PREFERRED_FEATURE_INDEX_1
> -#define index_arch_Prefer_ERMS PREFERRED_FEATURE_INDEX_1
> -#define index_arch_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1
> -#define index_arch_MathVec_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1
> -#define index_arch_Prefer_FSRM PREFERRED_FEATURE_INDEX_1
> -
> -/* XCR0 Feature flags. */
> -#define bit_XMM_state (1u << 1)
> -#define bit_YMM_state (1u << 2)
> -#define bit_Opmask_state (1u << 5)
> -#define bit_ZMM0_15_state (1u << 6)
> -#define bit_ZMM16_31_state (1u << 7)
> -#define bit_XTILECFG_state (1u << 17)
> -#define bit_XTILEDATA_state (1u << 18)
> -
> -# if defined (_LIBC) && !IS_IN (nonlib)
> -/* Unused for x86. */
> -# define INIT_ARCH()
> -# define __get_cpu_features() (&GLRO(dl_x86_cpu_features))
> -# endif
> -
> -#ifdef __x86_64__
> -# define HAS_CPUID 1
> -#elif (defined __i586__ || defined __pentium__ \
> - || defined __geode__ || defined __k6__)
> -# define HAS_CPUID 1
> -# define HAS_I586 1
> -# define HAS_I686 HAS_ARCH_FEATURE (I686)
> -#elif defined __i486__
> -# define HAS_CPUID 0
> -# define HAS_I586 HAS_ARCH_FEATURE (I586)
> -# define HAS_I686 HAS_ARCH_FEATURE (I686)
> -#else
> -# define HAS_CPUID 1
> -# define HAS_I586 1
> -# define HAS_I686 1
> -#endif
> -
> -#endif /* cpu_features_h */
> +#endif /* _SYS_PLATFORM_X86_H */
> diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
> index 4f0ec8315a..46350a4230 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
We need to improve the quality of this test.
The test should:
* Check if the compiler supports __builtin_cpu_support
* Cross check __builtin_cpu_support values against HAS_CPU_FEATURE
and CPU_FEATURE_USABLE results.
I would also like to see a Linux-specific variant that uses
/proc/cpuinfo "flags" to cross check all the viable flags against
the __builtin_cpu_support and HAS_CPU_FEATURE/CPU_FEATURE_SUABLE
results.
I want this to be bullet-proof and not something we can change
accidentally without seeing failures.
I understand that we have fallbacks to the non-optimized paths
in the user code, but those fallbacks often have serious negative
performance consequences that can be so slow as to cause serious
application issues.
> Copyright (C) 2015-2020 Free Software Foundation, Inc.
> This file is part of the GNU C Library.
>
> @@ -18,7 +18,7 @@
>
> #include <stdlib.h>
> #include <stdio.h>
> -#include <cpu-features.h>
> +#include <sys/platform/x86.h>
> #include <support/check.h>
>
> #define CHECK_CPU_FEATURE(name) \
> @@ -45,7 +45,7 @@ static const char * const cpu_kinds[] =
> static int
> do_test (void)
> {
> - const struct cpu_features *cpu_features = __get_cpu_features ();
> + const struct cpu_features *cpu_features = __x86_get_cpu_features (0);
>
> switch (cpu_features->basic.kind)
> {
> diff --git a/sysdeps/x86_64/fpu/math-tests-arch.h b/sysdeps/x86_64/fpu/math-tests-arch.h
> index 33ea763de2..cc3c2b0c11 100644
> --- a/sysdeps/x86_64/fpu/math-tests-arch.h
> +++ b/sysdeps/x86_64/fpu/math-tests-arch.h
> @@ -16,7 +16,7 @@
> License along with the GNU C Library; if not, see
> <https://www.gnu.org/licenses/>. */
>
> -#include <cpu-features.h>
> +#include <sys/platform/x86.h>
>
> #if defined REQUIRE_AVX
>
> diff --git a/sysdeps/x86_64/multiarch/test-multiarch.c b/sysdeps/x86_64/multiarch/test-multiarch.c
> index 7b1fa6811c..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>
>
@@ -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).
@@ -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,26 @@ all threads in the current process. Setting the
ordering on only the current thread is necessary. All other flag bits are
reserved.
@end deftypefun
+
+@node X86
+@appendixsec X86-specific Facilities
+
+Facilities specific to X86 that are not specific to a particular
+operating system are declared in @file{sys/platform/x86.h}.
+
+@deftypefun {const struct cpu_features *} __x86_get_cpu_features (unsigned int @var{max})
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Return a pointer to x86 CPU feature structure used by query macros for x86
+CPU features. If @var{max} exceeds @code{COMMON_CPUID_INDEX_MAX}, 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -1,5 +1,5 @@
ld {
- GLIBC_PRIVATE {
- __get_cpu_features;
+ GLIBC_2.32 {
+ __x86_get_cpu_features;
}
}
@@ -18,10 +18,12 @@
#include <ldsodefs.h>
-#undef __get_cpu_features
+#undef __x86_get_cpu_features
const struct cpu_features *
-__get_cpu_features (void)
+__x86_get_cpu_features (unsigned int max)
{
+ if (max > COMMON_CPUID_INDEX_MAX)
+ return NULL;
return &GLRO(dl_x86_cpu_features);
}
new file mode 100644
@@ -0,0 +1,179 @@
+/* Data structure for x86 CPU features.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _PRIVATE_CPU_FEATURES_H
+#define _PRIVATE_CPU_FEATURES_H 1
+
+#ifdef _CPU_FEATURES_H
+# error this should be impossible
+#endif
+
+#ifndef _ISOMAC
+/* Get most of the contents from the public header, but we define a
+ different `struct cpu_features' type for private use. */
+# define cpu_features cpu_features_public
+# define __x86_get_cpu_features __x86_get_cpu_features_public
+#endif
+
+#include <sysdeps/x86/sys/platform/x86.h>
+
+#ifndef _ISOMAC
+
+# undef cpu_features
+# undef __x86_get_cpu_features
+# define __get_cpu_features() __x86_get_cpu_features (0)
+
+enum
+{
+ /* The integer bit array index for the first set of preferred feature
+ bits. */
+ PREFERRED_FEATURE_INDEX_1 = 0,
+ /* The current maximum size of the feature integer bit array. */
+ PREFERRED_FEATURE_INDEX_MAX
+};
+
+/* Only used directly in cpu-features.c. */
+# define CPU_FEATURE_SET(ptr, name, check) \
+ ptr->features[index_cpu_##name].check.reg_##name |= bit_cpu_##name;
+# define CPU_FEATURE_UNSET(ptr, name, check) \
+ ptr->features[index_cpu_##name].check.reg_##name &= ~bit_cpu_##name;
+# define CPU_FEATURE_SET_USABLE(ptr, name) \
+ ptr->features[index_cpu_##name].usable.reg_##name \
+ |= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name;
+# define CPU_FEATURE_PREFERRED_P(ptr, name) \
+ ((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0)
+# define CPU_FEATURE_CPU_P(ptr, name) \
+ CPU_FEATURE_CHECK_P (ptr, name, cpuid)
+
+/* HAS_CPU_FEATURE evaluates to true if CPU supports the feature. */
+# undef HAS_CPU_FEATURE
+# define HAS_CPU_FEATURE(name) \
+ CPU_FEATURE_CPU_P (__x86_get_cpu_features (0), name)
+/* CPU_FEATURE_USABLE evaluates to true if the feature is usable. */
+# undef CPU_FEATURE_USABLE
+# define CPU_FEATURE_USABLE(name) \
+ CPU_FEATURE_USABLE_P (__x86_get_cpu_features (0), name)
+/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at
+ runtime. */
+# define CPU_FEATURE_PREFERRED(name) \
+ CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name)
+
+# define CPU_FEATURES_CPU_P(ptr, name) \
+ CPU_FEATURE_CPU_P (ptr, name)
+# define CPU_FEATURES_ARCH_P(ptr, name) \
+ CPU_FEATURE_PREFERRED_P (ptr, name)
+# define HAS_ARCH_FEATURE(name) \
+ CPU_FEATURE_PREFERRED (name)
+
+/* PREFERRED_FEATURE_INDEX_1. */
+# define bit_arch_I586 (1u << 0)
+# define bit_arch_I686 (1u << 1)
+# define bit_arch_Fast_Rep_String (1u << 2)
+# define bit_arch_Fast_Copy_Backward (1u << 3)
+# define bit_arch_Fast_Unaligned_Load (1u << 4)
+# define bit_arch_Fast_Unaligned_Copy (1u << 5)
+# define bit_arch_Slow_BSF (1u << 6)
+# define bit_arch_Slow_SSE4_2 (1u << 7)
+# define bit_arch_AVX_Fast_Unaligned_Load (1u << 8)
+# define bit_arch_Prefer_MAP_32BIT_EXEC (1u << 9)
+# define bit_arch_Prefer_PMINUB_for_stringop (1u << 10)
+# define bit_arch_Prefer_No_VZEROUPPER (1u << 11)
+# define bit_arch_Prefer_ERMS (1u << 12)
+# define bit_arch_Prefer_FSRM (1u << 13)
+# define bit_arch_Prefer_No_AVX512 (1u << 14)
+# define bit_arch_MathVec_Prefer_No_AVX512 (1u << 15)
+
+# define index_arch_Fast_Rep_String PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Copy_Backward PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_BSF PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_PMINUB_for_stringop PREFERRED_FEATURE_INDEX_1
+# define index_arch_Fast_Unaligned_Copy PREFERRED_FEATURE_INDEX_1
+# define index_arch_I586 PREFERRED_FEATURE_INDEX_1
+# define index_arch_I686 PREFERRED_FEATURE_INDEX_1
+# define index_arch_Slow_SSE4_2 PREFERRED_FEATURE_INDEX_1
+# define index_arch_AVX_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_MAP_32BIT_EXEC PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_VZEROUPPER PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_ERMS PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1
+# define index_arch_MathVec_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1
+# define index_arch_Prefer_FSRM PREFERRED_FEATURE_INDEX_1
+
+/* XCR0 Feature flags. */
+# define bit_XMM_state (1u << 1)
+# define bit_YMM_state (1u << 2)
+# define bit_Opmask_state (1u << 5)
+# define bit_ZMM0_15_state (1u << 6)
+# define bit_ZMM16_31_state (1u << 7)
+# define bit_XTILECFG_state (1u << 17)
+# define bit_XTILEDATA_state (1u << 18)
+
+struct cpu_features
+{
+ struct cpu_features_basic basic;
+ struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
+ unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
+ /* The state size for XSAVEC or XSAVE. The type must be unsigned long
+ int so that we use
+
+ sub xsave_state_size_offset(%rip) %RSP_LP
+
+ in _dl_runtime_resolve. */
+ unsigned long int xsave_state_size;
+ /* The full state size for XSAVE when XSAVEC is disabled by
+
+ GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_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) (&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 */
similarity index 79%
rename from sysdeps/x86/cpu-features.h
rename to sysdeps/x86/sys/platform/x86.h
@@ -1,4 +1,5 @@
-/* This file is part of the GNU C Library.
+/* Data structure for x86 CPU features.
+ This file is part of the GNU C Library.
Copyright (C) 2008-2020 Free Software Foundation, Inc.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,17 +16,8 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#ifndef cpu_features_h
-#define cpu_features_h
-
-enum
-{
- /* The integer bit array index for the first set of preferred feature
- bits. */
- PREFERRED_FEATURE_INDEX_1 = 0,
- /* The current maximum size of the feature integer bit array. */
- PREFERRED_FEATURE_INDEX_MAX
-};
+#ifndef _SYS_PLATFORM_X86_H
+#define _SYS_PLATFORM_X86_H
enum
{
@@ -76,69 +68,32 @@ struct cpu_features
{
struct cpu_features_basic basic;
struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
- unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
- /* The state size for XSAVEC or XSAVE. The type must be unsigned long
- int so that we use
-
- sub xsave_state_size_offset(%rip) %RSP_LP
-
- in _dl_runtime_resolve. */
- unsigned long int xsave_state_size;
- /* The full state size for XSAVE when XSAVEC is disabled by
-
- GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_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)
__attribute__ ((const));
-/* Only used directly in cpu-features.c. */
#define CPU_FEATURE_CHECK_P(ptr, name, check) \
((ptr->features[index_cpu_##name].check.reg_##name \
& bit_cpu_##name) != 0)
-#define CPU_FEATURE_SET(ptr, name, check) \
- ptr->features[index_cpu_##name].check.reg_##name |= bit_cpu_##name;
-#define CPU_FEATURE_UNSET(ptr, name, check) \
- ptr->features[index_cpu_##name].check.reg_##name &= ~bit_cpu_##name;
-#define CPU_FEATURE_SET_USABLE(ptr, name) \
- ptr->features[index_cpu_##name].usable.reg_##name \
- |= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name;
-#define CPU_FEATURE_PREFERRED_P(ptr, name) \
- ((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0)
#define CPU_FEATURE_CPU_P(ptr, name) \
CPU_FEATURE_CHECK_P (ptr, name, cpuid)
#define CPU_FEATURE_USABLE_P(ptr, name) \
CPU_FEATURE_CHECK_P (ptr, name, usable)
/* HAS_CPU_FEATURE evaluates to true if CPU supports the feature. */
-#define HAS_CPU_FEATURE(name) \
- CPU_FEATURE_CPU_P (__get_cpu_features (), name)
+#define HAS_CPU_FEATURE(name) \
+ (__extension__ \
+ ({ const struct cpu_features *__ptr = \
+ __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX); \
+ __ptr && CPU_FEATURE_CPU_P (__ptr, name); }))
/* CPU_FEATURE_USABLE evaluates to true if the feature is usable. */
-#define CPU_FEATURE_USABLE(name) \
- CPU_FEATURE_USABLE_P (__get_cpu_features (), name)
-/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at
- runtime. */
-#define CPU_FEATURE_PREFERRED(name) \
- CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name)
-
-#define CPU_FEATURES_CPU_P(ptr, name) \
- CPU_FEATURE_CPU_P (ptr, name)
-#define CPU_FEATURES_ARCH_P(ptr, name) \
- CPU_FEATURE_PREFERRED_P (ptr, name)
-#define HAS_ARCH_FEATURE(name) \
- CPU_FEATURE_PREFERRED (name)
+#define CPU_FEATURE_USABLE(name) \
+ (__extension__ \
+ ({ const struct cpu_features *__ptr = \
+ __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX); \
+ __ptr && CPU_FEATURE_USABLE_P (__ptr, name); }))
/* CPU features. */
@@ -697,71 +652,4 @@ extern const struct cpu_features *__get_cpu_features (void)
/* EAX. */
#define reg_AVX512_BF16 eax
-/* FEATURE_INDEX_2. */
-#define bit_arch_I586 (1u << 0)
-#define bit_arch_I686 (1u << 1)
-#define bit_arch_Fast_Rep_String (1u << 2)
-#define bit_arch_Fast_Copy_Backward (1u << 3)
-#define bit_arch_Fast_Unaligned_Load (1u << 4)
-#define bit_arch_Fast_Unaligned_Copy (1u << 5)
-#define bit_arch_Slow_BSF (1u << 6)
-#define bit_arch_Slow_SSE4_2 (1u << 7)
-#define bit_arch_AVX_Fast_Unaligned_Load (1u << 8)
-#define bit_arch_Prefer_MAP_32BIT_EXEC (1u << 9)
-#define bit_arch_Prefer_PMINUB_for_stringop (1u << 10)
-#define bit_arch_Prefer_No_VZEROUPPER (1u << 11)
-#define bit_arch_Prefer_ERMS (1u << 12)
-#define bit_arch_Prefer_FSRM (1u << 13)
-#define bit_arch_Prefer_No_AVX512 (1u << 14)
-#define bit_arch_MathVec_Prefer_No_AVX512 (1u << 15)
-
-#define index_arch_Fast_Rep_String PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Copy_Backward PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_BSF PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_PMINUB_for_stringop PREFERRED_FEATURE_INDEX_1
-#define index_arch_Fast_Unaligned_Copy PREFERRED_FEATURE_INDEX_1
-#define index_arch_I586 PREFERRED_FEATURE_INDEX_1
-#define index_arch_I686 PREFERRED_FEATURE_INDEX_1
-#define index_arch_Slow_SSE4_2 PREFERRED_FEATURE_INDEX_1
-#define index_arch_AVX_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_MAP_32BIT_EXEC PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_VZEROUPPER PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_ERMS PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1
-#define index_arch_MathVec_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1
-#define index_arch_Prefer_FSRM PREFERRED_FEATURE_INDEX_1
-
-/* XCR0 Feature flags. */
-#define bit_XMM_state (1u << 1)
-#define bit_YMM_state (1u << 2)
-#define bit_Opmask_state (1u << 5)
-#define bit_ZMM0_15_state (1u << 6)
-#define bit_ZMM16_31_state (1u << 7)
-#define bit_XTILECFG_state (1u << 17)
-#define bit_XTILEDATA_state (1u << 18)
-
-# if defined (_LIBC) && !IS_IN (nonlib)
-/* Unused for x86. */
-# define INIT_ARCH()
-# define __get_cpu_features() (&GLRO(dl_x86_cpu_features))
-# endif
-
-#ifdef __x86_64__
-# define HAS_CPUID 1
-#elif (defined __i586__ || defined __pentium__ \
- || defined __geode__ || defined __k6__)
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#elif defined __i486__
-# define HAS_CPUID 0
-# define HAS_I586 HAS_ARCH_FEATURE (I586)
-# define HAS_I686 HAS_ARCH_FEATURE (I686)
-#else
-# define HAS_CPUID 1
-# define HAS_I586 1
-# define HAS_I686 1
-#endif
-
-#endif /* cpu_features_h */
+#endif /* _SYS_PLATFORM_X86_H */
@@ -1,4 +1,4 @@
-/* Test case for x86 __get_cpu_features interface
+/* Test case for __x86_get_cpu_features interface
Copyright (C) 2015-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -18,7 +18,7 @@
#include <stdlib.h>
#include <stdio.h>
-#include <cpu-features.h>
+#include <sys/platform/x86.h>
#include <support/check.h>
#define CHECK_CPU_FEATURE(name) \
@@ -45,7 +45,7 @@ static const char * const cpu_kinds[] =
static int
do_test (void)
{
- const struct cpu_features *cpu_features = __get_cpu_features ();
+ const struct cpu_features *cpu_features = __x86_get_cpu_features (0);
switch (cpu_features->basic.kind)
{
@@ -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
@@ -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>