1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-30 22:43:12 +03:00

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

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

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

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

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

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

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

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

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

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

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

Note: Although GCC has __builtin_cpu_supports, it only supports a subset
of <sys/platform/x86.h> and it is equivalent to CPU_FEATURE_USABLE.  It
doesn't support HAS_CPU_FEATURE.
This commit is contained in:
H.J. Lu
2020-06-29 18:30:54 -07:00
parent a92f4e6299
commit 9620398097
18 changed files with 1176 additions and 247 deletions

1
NEWS
View File

@ -9,6 +9,7 @@ Version 2.33
Major new features: Major new features:
* Add <sys/platform/x86.h> to provide query macros for x86 CPU features.
* Support for the RISC-V ISA running on Linux has been expanded to run on * Support for the RISC-V ISA running on Linux has been expanded to run on
32-bit hardware. This is supported for the following ISA and ABI pairs: 32-bit hardware. This is supported for the following ISA and ABI pairs:

View File

@ -7,6 +7,7 @@
@menu @menu
* PowerPC:: Facilities Specific to the PowerPC Architecture * PowerPC:: Facilities Specific to the PowerPC Architecture
* RISC-V:: Facilities Specific to the RISC-V Architecture * RISC-V:: Facilities Specific to the RISC-V Architecture
* X86:: Facilities Specific to the X86 Architecture
@end menu @end menu
@node PowerPC @node PowerPC
@ -134,3 +135,519 @@ all threads in the current process. Setting the
ordering on only the current thread is necessary. All other flag bits are ordering on only the current thread is necessary. All other flag bits are
reserved. reserved.
@end deftypefun @end deftypefun
@node X86
@appendixsec X86-specific Facilities
Facilities specific to X86 that are not specific to a particular
operating system are declared in @file{sys/platform/x86.h}.
@deftypefun {const struct cpu_features *} __x86_get_cpu_features (unsigned int @var{max})
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
Return a pointer to x86 CPU feature structure used by query macros for x86
CPU features. If @var{max} exceeds @code{COMMON_CPUID_INDEX_MAX} which
is the limit of the CPUID leaves supported by @Theglibc{}, the function
returns @code{NULL}, indicating that the queried processor feature is
unsupported by @Theglibc{} run-time.
@end deftypefun
@deftypefn Macro int HAS_CPU_FEATURE (@var{name})
This macro returns a nonzero value (true) if the processor has the feature
@var{name}.
@end deftypefn
@deftypefn Macro int CPU_FEATURE_USABLE (@var{name})
This macro returns a nonzero value (true) if the processor has the feature
@var{name} and the feature is supported by the operating system.
@end deftypefn
The supported processor features are:
@itemize @bullet
@item
@code{ACPI} -- Thermal Monitor and Software Controlled Clock Facilities.
@item
@code{ADX} -- ADX instruction extensions.
@item
@code{APIC} -- APIC On-Chip.
@item
@code{AES} -- The AES instruction extensions.
@item
@code{AMX_BF16} -- Tile computational operations on bfloat16 numbers.
@item
@code{AMX_INT8} -- Tile computational operations on 8-bit numbers.
@item
@code{AMX_TILE} -- Tile architecture.
@item
@code{ARCH_CAPABILITIES} -- IA32_ARCH_CAPABILITIES MSR.
@item
@code{AVX} -- The AVX instruction extensions.
@item
@code{AVX2} -- The AVX2 instruction extensions.
@item
@code{AVX512_4FMAPS} -- The AVX512_4FMAPS instruction extensions.
@item
@code{AVX512_4VNNIW} -- The AVX512_4VNNIW instruction extensions.
@item
@code{AVX512_BF16} -- The AVX512_BF16 instruction extensions.
@item
@code{AVX512_BITALG} -- The AVX512_BITALG instruction extensions.
@item
@code{AVX512_IFMA} -- The AVX512_IFMA instruction extensions.
@item
@code{AVX512_VBMI} -- The AVX512_VBMI instruction extensions.
@item
@code{AVX512_VBMI2} -- The AVX512_VBMI2 instruction extensions.
@item
@code{AVX512_VNNI} -- The AVX512_VNNI instruction extensions.
@item
@code{AVX512_VP2INTERSECT} -- The AVX512_VP2INTERSECT instruction
extensions.
@item
@code{AVX512_VPOPCNTDQ} -- The AVX512_VPOPCNTDQ instruction extensions.
@item
@code{AVX512BW} -- The AVX512BW instruction extensions.
@item
@code{AVX512CD} -- The AVX512CD instruction extensions.
@item
@code{AVX512ER} -- The AVX512ER instruction extensions.
@item
@code{AVX512DQ} -- The AVX512DQ instruction extensions.
@item
@code{AVX512F} -- The AVX512F instruction extensions.
@item
@code{AVX512PF} -- The AVX512PF instruction extensions.
@item
@code{AVX512VL} -- The AVX512VL instruction extensions.
@item
@code{BMI1} -- BMI1 instructions.
@item
@code{BMI2} -- BMI2 instructions.
@item
@code{CLDEMOTE} -- CLDEMOTE instruction.
@item
@code{CLFLUSHOPT} -- CLFLUSHOPT instruction.
@item
@code{CLFSH} -- CLFLUSH instruction.
@item
@code{CLWB} -- CLWB instruction.
@item
@code{CMOV} -- Conditional Move instructions.
@item
@code{CMPXCHG16B} -- CMPXCHG16B instruction.
@item
@code{CNXT_ID} -- L1 Context ID.
@item
@code{CORE_CAPABILITIES} -- IA32_CORE_CAPABILITIES MSR.
@item
@code{CX8} -- CMPXCHG8B instruction.
@item
@code{DCA} -- Data prefetch from a memory mapped device.
@item
@code{DE} -- Debugging Extensions.
@item
@code{DEPR_FPU_CS_DS} -- Deprecates FPU CS and FPU DS values.
@item
@code{DS} -- Debug Store.
@item
@code{DS_CPL} -- CPL Qualified Debug Store.
@item
@code{DTES64} -- 64-bit DS Area.
@item
@code{EIST} -- Enhanced Intel SpeedStep technology.
@item
@code{ENQCMD} -- Enqueue Stores instructions.
@item
@code{ERMS} -- Enhanced REP MOVSB/STOSB.
@item
@code{F16C} -- 16-bit floating-point conversion instructions.
@item
@code{FMA} -- FMA extensions using YMM state.
@item
@code{FMA4} -- FMA4 instruction extensions.
@item
@code{FPU} -- X87 Floating Point Unit On-Chip.
@item
@code{FSGSBASE} -- RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE instructions.
@item
@code{FSRM} -- Fast Short REP MOV.
@item
@code{FXSR} -- FXSAVE and FXRSTOR instructions.
@item
@code{GFNI} -- GFNI instruction extensions.
@item
@code{HLE} -- HLE instruction extensions.
@item
@code{HTT} -- Max APIC IDs reserved field is Valid.
@item
@code{HYBRID} -- Hybrid processor.
@item
@code{IBRS_IBPB} -- Indirect branch restricted speculation (IBRS) and
the indirect branch predictor barrier (IBPB).
@item
@code{IBT} -- Intel Indirect Branch Tracking instruction extensions.
@item
@code{INVARIANT_TSC} -- Invariant TSC.
@item
@code{INVPCID} -- INVPCID instruction.
@item
@code{L1D_FLUSH} -- IA32_FLUSH_CMD MSR.
@item
@code{LAHF64_SAHF64} -- LAHF/SAHF available in 64-bit mode.
@item
@code{LM} -- Long mode.
@item
@code{LWP} -- Lightweight profiling.
@item
@code{LZCNT} -- LZCNT instruction.
@item
@code{MCA} -- Machine Check Architecture.
@item
@code{MCE} -- Machine Check Exception.
@item
@code{MD_CLEAR} -- MD_CLEAR.
@item
@code{MMX} -- Intel MMX Technology.
@item
@code{MONITOR} -- MONITOR/MWAIT instructions.
@item
@code{MOVBE} -- MOVBE instruction.
@item
@code{MOVDIRI} -- MOVDIRI instruction.
@item
@code{MOVDIR64B} -- MOVDIR64B instruction.
@item
@code{MPX} -- Intel Memory Protection Extensions.
@item
@code{MSR} -- Model Specific Registers RDMSR and WRMSR instructions.
@item
@code{MTRR} -- Memory Type Range Registers.
@item
@code{NX} -- No-execute page protection.
@item
@code{OSPKE} -- OS has set CR4.PKE to enable protection keys.
@item
@code{OSXSAVE} -- The OS has set CR4.OSXSAVE[bit 18] to enable
XSETBV/XGETBV instructions to access XCR0 and to support processor
extended state management using XSAVE/XRSTOR.
@item
@code{PAE} -- Physical Address Extension.
@item
@code{PAGE1GB} -- 1-GByte page.
@item
@code{PAT} -- Page Attribute Table.
@item
@code{PBE} -- Pending Break Enable.
@item
@code{PCID} -- Process-context identifiers.
@item
@code{PCLMULQDQ} -- PCLMULQDQ instruction.
@item
@code{PCONFIG} -- PCONFIG instruction.
@item
@code{PDCM} -- Perfmon and Debug Capability.
@item
@code{PGE} -- Page Global Bit.
@item
@code{PKS} -- Protection keys for supervisor-mode pages.
@item
@code{PKU} -- Protection keys for user-mode pages.
@item
@code{POPCNT} -- POPCNT instruction.
@item
@code{PREFETCHW} -- PREFETCHW instruction.
@item
@code{PREFETCHWT1} -- PREFETCHWT1 instruction.
@item
@code{PSE} -- Page Size Extension.
@item
@code{PSE_36} -- 36-Bit Page Size Extension.
@item
@code{PSN} -- Processor Serial Number.
@item
@code{RDPID} -- RDPID instruction.
@item
@code{RDRAND} -- RDRAND instruction.
@item
@code{RDSEED} -- RDSEED instruction.
@item
@code{RDT_A} -- Intel Resource Director Technology (Intel RDT) Allocation
capability.
@item
@code{RDT_M} -- Intel Resource Director Technology (Intel RDT) Monitoring
capability.
@item
@code{RDTSCP} -- RDTSCP instruction.
@item
@code{RTM} -- RTM instruction extensions.
@item
@code{SDBG} -- IA32_DEBUG_INTERFACE MSR for silicon debug.
@item
@code{SEP} -- SYSENTER and SYSEXIT instructions.
@item
@code{SERIALIZE} -- SERIALIZE instruction.
@item
@code{SGX} -- Intel Software Guard Extensions.
@item
@code{SGX_LC} -- SGX Launch Configuration.
@item
@code{SHA} -- SHA instruction extensions.
@item
@code{SHSTK} -- Intel Shadow Stack instruction extensions.
@item
@code{SMAP} -- Supervisor-Mode Access Prevention.
@item
@code{SMEP} -- Supervisor-Mode Execution Prevention.
@item
@code{SMX} -- Safer Mode Extensions.
@item
@code{SS} -- Self Snoop.
@item
@code{SSBD} -- Speculative Store Bypass Disable (SSBD).
@item
@code{SSE} -- Streaming SIMD Extensions.
@item
@code{SSE2} -- Streaming SIMD Extensions 2.
@item
@code{SSE3} -- Streaming SIMD Extensions 3.
@item
@code{SSE4_1} -- Streaming SIMD Extensions 4.1.
@item
@code{SSE4_2} -- Streaming SIMD Extensions 4.2.
@item
@code{SSE4A} -- SSE4A instruction extensions.
@item
@code{SSSE3} -- Supplemental Streaming SIMD Extensions 3.
@item
@code{STIBP} -- Single thread indirect branch predictors (STIBP).
@item
@code{SVM} -- Secure Virtual Machine.
@item
@code{SYSCALL_SYSRET} -- SYSCALL/SYSRET instructions.
@item
@code{TBM} -- Trailing bit manipulation instructions.
@item
@code{TM} -- Thermal Monitor.
@item
@code{TM2} -- Thermal Monitor 2.
@item
@code{TRACE} -- Intel Processor Trace.
@item
@code{TSC} -- Time Stamp Counter. RDTSC instruction.
@item
@code{TSC_ADJUST} -- IA32_TSC_ADJUST MSR.
@item
@code{TSC_DEADLINE} -- Local APIC timer supports one-shot operation
using a TSC deadline value.
@item
@code{TSXLDTRK} -- TSXLDTRK instructions.
@item
@code{UMIP} -- User-mode instruction prevention.
@item
@code{VAES} -- VAES instruction extensions.
@item
@code{VME} -- Virtual 8086 Mode Enhancements.
@item
@code{VMX} -- Virtual Machine Extensions.
@item
@code{VPCLMULQDQ} -- VPCLMULQDQ instruction.
@item
@code{WAITPKG} -- WAITPKG instruction extensions.
@item
@code{WBNOINVD} -- WBINVD/WBNOINVD instructions.
@item
@code{X2APIC} -- x2APIC.
@item
@code{XFD} -- Extended Feature Disable (XFD).
@item
@code{XGETBV_ECX_1} -- XGETBV with ECX = 1.
@item
@code{XOP} -- XOP instruction extensions.
@item
@code{XSAVE} -- The XSAVE/XRSTOR processor extended states feature, the
XSETBV/XGETBV instructions, and XCR0.
@item
@code{XSAVEC} -- XSAVEC instruction.
@item
@code{XSAVEOPT} -- XSAVEOPT instruction.
@item
@code{XSAVES} -- XSAVES/XRSTORS instructions.
@item
@code{XTPRUPDCTRL} -- xTPR Update Control.
@end itemize
You could query if a processor supports @code{AVX} with:
@smallexample
#include <sys/platform/x86.h>
int
support_avx (void)
@{
return HAS_CPU_FEATURE (AVX);
@}
@end smallexample
and if @code{AVX} is usable with:
@smallexample
#include <sys/platform/x86.h>
int
usable_avx (void)
@{
return CPU_FEATURE_USABLE (AVX);
@}
@end smallexample

View File

@ -1,7 +1,3 @@
ifeq ($(subdir),csu)
tests += test-multiarch
endif
ifeq ($(subdir),string) ifeq ($(subdir),string)
gen-as-const-headers += locale-defines.sym gen-as-const-headers += locale-defines.sym
sysdep_routines += bzero-sse2 memset-sse2 memcpy-ssse3 mempcpy-ssse3 \ sysdep_routines += bzero-sse2 memset-sse2 memcpy-ssse3 mempcpy-ssse3 \

View File

@ -1 +0,0 @@
#include <sysdeps/x86_64/multiarch/test-multiarch.c>

View File

@ -3,3 +3,4 @@ GLIBC_2.1 __libc_stack_end D 0x4
GLIBC_2.1 _dl_mcount F GLIBC_2.1 _dl_mcount F
GLIBC_2.3 ___tls_get_addr F GLIBC_2.3 ___tls_get_addr F
GLIBC_2.3 __tls_get_addr F GLIBC_2.3 __tls_get_addr F
GLIBC_2.33 __x86_get_cpu_features F

View File

@ -2,3 +2,4 @@ GLIBC_2.2.5 __libc_stack_end D 0x8
GLIBC_2.2.5 _dl_mcount F GLIBC_2.2.5 _dl_mcount F
GLIBC_2.2.5 _r_debug D 0x28 GLIBC_2.2.5 _r_debug D 0x28
GLIBC_2.3 __tls_get_addr F GLIBC_2.3 __tls_get_addr F
GLIBC_2.33 __x86_get_cpu_features F

View File

@ -2,3 +2,4 @@ GLIBC_2.16 __libc_stack_end D 0x4
GLIBC_2.16 __tls_get_addr F GLIBC_2.16 __tls_get_addr F
GLIBC_2.16 _dl_mcount F GLIBC_2.16 _dl_mcount F
GLIBC_2.16 _r_debug D 0x14 GLIBC_2.16 _r_debug D 0x14
GLIBC_2.33 __x86_get_cpu_features F

View File

@ -4,8 +4,10 @@ endif
ifeq ($(subdir),elf) ifeq ($(subdir),elf)
sysdep-dl-routines += dl-get-cpu-features sysdep-dl-routines += dl-get-cpu-features
sysdep_headers += sys/platform/x86.h
tests += tst-get-cpu-features tst-get-cpu-features-static tests += tst-get-cpu-features tst-get-cpu-features-static \
tst-cpu-features-cpuinfo tst-cpu-features-supports
tests-static += tst-get-cpu-features-static tests-static += tst-get-cpu-features-static
endif endif

View File

@ -1,5 +1,5 @@
ld { ld {
GLIBC_PRIVATE { GLIBC_2.33 {
__get_cpu_features; __x86_get_cpu_features;
} }
} }

View File

@ -18,10 +18,12 @@
#include <ldsodefs.h> #include <ldsodefs.h>
#undef __get_cpu_features #undef __x86_get_cpu_features
const struct 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); return &GLRO(dl_x86_cpu_features);
} }

View File

@ -0,0 +1,183 @@
/* Data structure for x86 CPU features.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _PRIVATE_CPU_FEATURES_H
#define _PRIVATE_CPU_FEATURES_H 1
#ifdef _CPU_FEATURES_H
# error this should be impossible
#endif
#ifndef _ISOMAC
/* Get most of the contents from the public header, but we define a
different `struct cpu_features' type for private use. */
# define cpu_features cpu_features_public
# define __x86_get_cpu_features __x86_get_cpu_features_public
#endif
#include <sysdeps/x86/sys/platform/x86.h>
#ifndef _ISOMAC
# undef cpu_features
# undef __x86_get_cpu_features
# define __get_cpu_features() __x86_get_cpu_features (0)
enum
{
/* The integer bit array index for the first set of preferred feature
bits. */
PREFERRED_FEATURE_INDEX_1 = 0,
/* The current maximum size of the feature integer bit array. */
PREFERRED_FEATURE_INDEX_MAX
};
/* Only used directly in cpu-features.c. */
# define CPU_FEATURE_SET(ptr, name) \
ptr->features[index_cpu_##name].usable.reg_##name |= bit_cpu_##name;
# define CPU_FEATURE_UNSET(ptr, name) \
ptr->features[index_cpu_##name].usable.reg_##name &= ~bit_cpu_##name;
# define CPU_FEATURE_SET_USABLE(ptr, name) \
ptr->features[index_cpu_##name].usable.reg_##name \
|= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name;
# define CPU_FEATURE_PREFERRED_P(ptr, name) \
((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0)
# define CPU_FEATURE_CPU_P(ptr, name) \
CPU_FEATURE_CHECK_P (ptr, name, cpuid)
/* HAS_CPU_FEATURE evaluates to true if CPU supports the feature. */
# undef HAS_CPU_FEATURE
# define HAS_CPU_FEATURE(name) \
CPU_FEATURE_CPU_P (__x86_get_cpu_features (0), name)
/* CPU_FEATURE_USABLE evaluates to true if the feature is usable. */
# undef CPU_FEATURE_USABLE
# define CPU_FEATURE_USABLE(name) \
CPU_FEATURE_USABLE_P (__x86_get_cpu_features (0), name)
/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at
runtime. */
# define CPU_FEATURE_PREFERRED(name) \
CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name)
# define CPU_FEATURES_CPU_P(ptr, name) \
CPU_FEATURE_CPU_P (ptr, name)
# define CPU_FEATURES_ARCH_P(ptr, name) \
CPU_FEATURE_PREFERRED_P (ptr, name)
# define HAS_ARCH_FEATURE(name) \
CPU_FEATURE_PREFERRED (name)
/* PREFERRED_FEATURE_INDEX_1. */
# define bit_arch_I586 (1u << 0)
# define bit_arch_I686 (1u << 1)
# define bit_arch_Fast_Rep_String (1u << 2)
# define bit_arch_Fast_Copy_Backward (1u << 3)
# define bit_arch_Fast_Unaligned_Load (1u << 4)
# define bit_arch_Fast_Unaligned_Copy (1u << 5)
# define bit_arch_Slow_BSF (1u << 6)
# define bit_arch_Slow_SSE4_2 (1u << 7)
# define bit_arch_AVX_Fast_Unaligned_Load (1u << 8)
# define bit_arch_Prefer_MAP_32BIT_EXEC (1u << 9)
# define bit_arch_Prefer_PMINUB_for_stringop (1u << 10)
# define bit_arch_Prefer_No_VZEROUPPER (1u << 11)
# define bit_arch_Prefer_ERMS (1u << 12)
# define bit_arch_Prefer_FSRM (1u << 13)
# define bit_arch_Prefer_No_AVX512 (1u << 14)
# define bit_arch_MathVec_Prefer_No_AVX512 (1u << 15)
# define index_arch_Fast_Rep_String PREFERRED_FEATURE_INDEX_1
# define index_arch_Fast_Copy_Backward PREFERRED_FEATURE_INDEX_1
# define index_arch_Slow_BSF PREFERRED_FEATURE_INDEX_1
# define index_arch_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1
# define index_arch_Prefer_PMINUB_for_stringop PREFERRED_FEATURE_INDEX_1
# define index_arch_Fast_Unaligned_Copy PREFERRED_FEATURE_INDEX_1
# define index_arch_I586 PREFERRED_FEATURE_INDEX_1
# define index_arch_I686 PREFERRED_FEATURE_INDEX_1
# define index_arch_Slow_SSE4_2 PREFERRED_FEATURE_INDEX_1
# define index_arch_AVX_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1
# define index_arch_Prefer_MAP_32BIT_EXEC PREFERRED_FEATURE_INDEX_1
# define index_arch_Prefer_No_VZEROUPPER PREFERRED_FEATURE_INDEX_1
# define index_arch_Prefer_ERMS PREFERRED_FEATURE_INDEX_1
# define index_arch_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1
# define index_arch_MathVec_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1
# define index_arch_Prefer_FSRM PREFERRED_FEATURE_INDEX_1
/* XCR0 Feature flags. */
# define bit_XMM_state (1u << 1)
# define bit_YMM_state (1u << 2)
# define bit_Opmask_state (1u << 5)
# define bit_ZMM0_15_state (1u << 6)
# define bit_ZMM16_31_state (1u << 7)
# define bit_XTILECFG_state (1u << 17)
# define bit_XTILEDATA_state (1u << 18)
struct cpu_features
{
struct cpu_features_basic basic;
struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
/* The state size for XSAVEC or XSAVE. The type must be unsigned long
int so that we use
sub xsave_state_size_offset(%rip) %RSP_LP
in _dl_runtime_resolve. */
unsigned long int xsave_state_size;
/* The full state size for XSAVE when XSAVEC is disabled by
GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC
*/
unsigned int xsave_state_full_size;
/* Data cache size for use in memory and string routines, typically
L1 size. */
unsigned long int data_cache_size;
/* Shared cache size for use in memory and string routines, typically
L2 or L3 size. */
unsigned long int shared_cache_size;
/* Threshold to use non temporal store. */
unsigned long int non_temporal_threshold;
/* Threshold to use "rep movsb". */
unsigned long int rep_movsb_threshold;
/* Threshold to use "rep stosb". */
unsigned long int rep_stosb_threshold;
};
# if defined (_LIBC) && !IS_IN (nonlib)
/* Unused for x86. */
# define INIT_ARCH()
# define __x86_get_cpu_features(max) (&GLRO(dl_x86_cpu_features))
# endif
# ifdef __x86_64__
# define HAS_CPUID 1
# elif (defined __i586__ || defined __pentium__ \
|| defined __geode__ || defined __k6__)
# define HAS_CPUID 1
# define HAS_I586 1
# define HAS_I686 HAS_ARCH_FEATURE (I686)
# elif defined __i486__
# define HAS_CPUID 0
# define HAS_I586 HAS_ARCH_FEATURE (I586)
# define HAS_I686 HAS_ARCH_FEATURE (I686)
# else
# define HAS_CPUID 1
# define HAS_I586 1
# define HAS_I686 1
# endif
#endif /* !_ISOMAC */
#endif /* include/cpu-features.h */

View File

@ -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. Copyright (C) 2008-2020 Free Software Foundation, Inc.
The GNU C Library is free software; you can redistribute it and/or 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 License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */ <https://www.gnu.org/licenses/>. */
#ifndef cpu_features_h #ifndef _SYS_PLATFORM_X86_H
#define cpu_features_h #define _SYS_PLATFORM_X86_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
};
enum enum
{ {
@ -76,73 +68,32 @@ struct cpu_features
{ {
struct cpu_features_basic basic; struct cpu_features_basic basic;
struct cpuid_features features[COMMON_CPUID_INDEX_MAX]; struct cpuid_features features[COMMON_CPUID_INDEX_MAX];
unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX];
/* The state size for XSAVEC or XSAVE. The type must be unsigned long
int so that we use
sub xsave_state_size_offset(%rip) %RSP_LP
in _dl_runtime_resolve. */
unsigned long int xsave_state_size;
/* The full state size for XSAVE when XSAVEC is disabled by
GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC
*/
unsigned int xsave_state_full_size;
/* Data cache size for use in memory and string routines, typically
L1 size. */
unsigned long int data_cache_size;
/* Shared cache size for use in memory and string routines, typically
L2 or L3 size. */
unsigned long int shared_cache_size;
/* Threshold to use non temporal store. */
unsigned long int non_temporal_threshold;
/* Threshold to use "rep movsb". */
unsigned long int rep_movsb_threshold;
/* Threshold to use "rep stosb". */
unsigned long int rep_stosb_threshold;
}; };
/* Used from outside of glibc to get access to the CPU features /* Get a pointer to the CPU features structure. */
structure. */ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
extern const struct cpu_features *__get_cpu_features (void)
__attribute__ ((const)); __attribute__ ((const));
/* Only used directly in cpu-features.c. */
#define CPU_FEATURE_CHECK_P(ptr, name, check) \ #define CPU_FEATURE_CHECK_P(ptr, name, check) \
((ptr->features[index_cpu_##name].check.reg_##name \ ((ptr->features[index_cpu_##name].check.reg_##name \
& bit_cpu_##name) != 0) & bit_cpu_##name) != 0)
#define CPU_FEATURE_SET(ptr, name) \
ptr->features[index_cpu_##name].usable.reg_##name |= bit_cpu_##name;
#define CPU_FEATURE_UNSET(ptr, name) \
ptr->features[index_cpu_##name].usable.reg_##name &= ~bit_cpu_##name;
#define CPU_FEATURE_SET_USABLE(ptr, name) \
ptr->features[index_cpu_##name].usable.reg_##name \
|= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name;
#define CPU_FEATURE_PREFERRED_P(ptr, name) \
((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0)
#define CPU_FEATURE_CPU_P(ptr, name) \ #define CPU_FEATURE_CPU_P(ptr, name) \
CPU_FEATURE_CHECK_P (ptr, name, cpuid) CPU_FEATURE_CHECK_P (ptr, name, cpuid)
#define CPU_FEATURE_USABLE_P(ptr, name) \ #define CPU_FEATURE_USABLE_P(ptr, name) \
CPU_FEATURE_CHECK_P (ptr, name, usable) CPU_FEATURE_CHECK_P (ptr, name, usable)
/* HAS_CPU_FEATURE evaluates to true if CPU supports the feature. */ /* HAS_CPU_FEATURE evaluates to true if CPU supports the feature. */
#define HAS_CPU_FEATURE(name) \ #define HAS_CPU_FEATURE(name) \
CPU_FEATURE_CPU_P (__get_cpu_features (), 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. */ /* CPU_FEATURE_USABLE evaluates to true if the feature is usable. */
#define CPU_FEATURE_USABLE(name) \ #define CPU_FEATURE_USABLE(name) \
CPU_FEATURE_USABLE_P (__get_cpu_features (), name) (__extension__ \
/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at ({ const struct cpu_features *__ptr = \
runtime. */ __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX); \
#define CPU_FEATURE_PREFERRED(name) \ __ptr && CPU_FEATURE_USABLE_P (__ptr, 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)
/* CPU features. */ /* CPU features. */
@ -787,71 +738,4 @@ extern const struct cpu_features *__get_cpu_features (void)
/* EAX. */ /* EAX. */
#define reg_AVX512_BF16 eax #define reg_AVX512_BF16 eax
/* FEATURE_INDEX_2. */ #endif /* _SYS_PLATFORM_X86_H */
#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 */

View File

@ -0,0 +1,250 @@
/* Test CPU feature data against /proc/cpuinfo.
This file is part of the GNU C Library.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <sys/platform/x86.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char *cpu_flags;
/* Search for flags in /proc/cpuinfo and store line
in cpu_flags. */
void
get_cpuinfo (void)
{
FILE *f;
char *line = NULL;
size_t len = 0;
ssize_t read;
f = fopen ("/proc/cpuinfo", "r");
if (f == NULL)
{
printf ("cannot open /proc/cpuinfo\n");
exit (1);
}
while ((read = getline (&line, &len, f)) != -1)
{
if (strncmp (line, "flags", 5) == 0)
{
cpu_flags = strdup (line);
break;
}
}
fclose (f);
free (line);
}
int
check_proc (const char *proc_name, int flag, int usable, const char *name)
{
int found = 0;
printf ("Checking %s:\n", name);
if (!usable)
{
printf (" %s: insufficient usable info, skipped\n", name);
return 0;
}
printf (" %s: %d\n", name, flag);
if (strstr (cpu_flags, proc_name) != NULL)
found = 1;
printf (" cpuinfo (%s): %d\n", proc_name, found);
if (found != flag)
printf (" *** failure ***\n");
return (found != flag);
}
#define CHECK_PROC(str, name) \
check_proc (#str, HAS_CPU_FEATURE (name), CPU_FEATURE_USABLE (name), \
"HAS_CPU_FEATURE (" #name ")");
static int
do_test (int argc, char **argv)
{
int fails = 0;
get_cpuinfo ();
fails += CHECK_PROC (acpi, ACPI);
fails += CHECK_PROC (adx, ADX);
fails += CHECK_PROC (apic, APIC);
fails += CHECK_PROC (aes, AES);
fails += CHECK_PROC (amx_bf16, AMX_BF16);
fails += CHECK_PROC (amx_int8, AMX_INT8);
fails += CHECK_PROC (amx_tile, AMX_TILE);
fails += CHECK_PROC (arch_capabilities, ARCH_CAPABILITIES);
fails += CHECK_PROC (avx, AVX);
fails += CHECK_PROC (avx2, AVX2);
fails += CHECK_PROC (avx512_4fmaps, AVX512_4FMAPS);
fails += CHECK_PROC (avx512_4vnniw, AVX512_4VNNIW);
fails += CHECK_PROC (avx512_bf16, AVX512_BF16);
fails += CHECK_PROC (avx512_bitalg, AVX512_BITALG);
fails += CHECK_PROC (avx512ifma, AVX512_IFMA);
fails += CHECK_PROC (avx512_vbmi, AVX512_VBMI);
fails += CHECK_PROC (avx512_vbmi2, AVX512_VBMI2);
fails += CHECK_PROC (avx512_vnni, AVX512_VNNI);
fails += CHECK_PROC (avx512_vp2intersect, AVX512_VP2INTERSECT);
fails += CHECK_PROC (avx512_vpopcntdq, AVX512_VPOPCNTDQ);
fails += CHECK_PROC (avx512bw, AVX512BW);
fails += CHECK_PROC (avx512cd, AVX512CD);
fails += CHECK_PROC (avx512er, AVX512ER);
fails += CHECK_PROC (avx512dq, AVX512DQ);
fails += CHECK_PROC (avx512f, AVX512F);
fails += CHECK_PROC (avx512pf, AVX512PF);
fails += CHECK_PROC (avx512vl, AVX512VL);
fails += CHECK_PROC (bmi1, BMI1);
fails += CHECK_PROC (bmi2, BMI2);
fails += CHECK_PROC (cldemote, CLDEMOTE);
fails += CHECK_PROC (clflushopt, CLFLUSHOPT);
fails += CHECK_PROC (clflush, CLFSH);
fails += CHECK_PROC (clwb, CLWB);
fails += CHECK_PROC (cmov, CMOV);
fails += CHECK_PROC (cx16, CMPXCHG16B);
fails += CHECK_PROC (cnxt_id, CNXT_ID);
fails += CHECK_PROC (core_capabilities, CORE_CAPABILITIES);
fails += CHECK_PROC (cx8, CX8);
fails += CHECK_PROC (dca, DCA);
fails += CHECK_PROC (de, DE);
fails += CHECK_PROC (zero_fcs_fds, DEPR_FPU_CS_DS);
fails += CHECK_PROC (ds, DS);
fails += CHECK_PROC (ds_cpl, DS_CPL);
fails += CHECK_PROC (dtes64, DTES64);
fails += CHECK_PROC (est, EIST);
fails += CHECK_PROC (enqcmd, ENQCMD);
fails += CHECK_PROC (erms, ERMS);
fails += CHECK_PROC (f16c, F16C);
fails += CHECK_PROC (fma, FMA);
fails += CHECK_PROC (fma4, FMA4);
fails += CHECK_PROC (fpu, FPU);
fails += CHECK_PROC (fsgsbase, FSGSBASE);
fails += CHECK_PROC (fsrm, FSRM);
fails += CHECK_PROC (fxsr, FXSR);
fails += CHECK_PROC (gfni, GFNI);
fails += CHECK_PROC (hle, HLE);
fails += CHECK_PROC (ht, HTT);
fails += CHECK_PROC (hybrid, HYBRID);
fails += CHECK_PROC (ibrs, IBRS_IBPB);
fails += CHECK_PROC (ibt, IBT);
fails += CHECK_PROC (invariant_tsc, INVARIANT_TSC);
fails += CHECK_PROC (invpcid, INVPCID);
fails += CHECK_PROC (flush_l1d, L1D_FLUSH);
fails += CHECK_PROC (lahf_lm, LAHF64_SAHF64);
fails += CHECK_PROC (lm, LM);
fails += CHECK_PROC (lwp, LWP);
fails += CHECK_PROC (abm, LZCNT);
fails += CHECK_PROC (mca, MCA);
fails += CHECK_PROC (mce, MCE);
fails += CHECK_PROC (md_clear, MD_CLEAR);
fails += CHECK_PROC (mmx, MMX);
fails += CHECK_PROC (monitor, MONITOR);
fails += CHECK_PROC (movbe, MOVBE);
fails += CHECK_PROC (movdiri, MOVDIRI);
fails += CHECK_PROC (movdir64b, MOVDIR64B);
fails += CHECK_PROC (mpx, MPX);
fails += CHECK_PROC (msr, MSR);
fails += CHECK_PROC (mtrr, MTRR);
fails += CHECK_PROC (nx, NX);
fails += CHECK_PROC (ospke, OSPKE);
#if 0
/* NB: /proc/cpuinfo doesn't report this feature. */
fails += CHECK_PROC (osxsave, OSXSAVE);
#endif
fails += CHECK_PROC (pae, PAE);
fails += CHECK_PROC (pdpe1gb, PAGE1GB);
fails += CHECK_PROC (pat, PAT);
fails += CHECK_PROC (pbe, PBE);
fails += CHECK_PROC (pcid, PCID);
fails += CHECK_PROC (pclmulqdq, PCLMULQDQ);
fails += CHECK_PROC (pconfig, PCONFIG);
fails += CHECK_PROC (pdcm, PDCM);
fails += CHECK_PROC (pge, PGE);
fails += CHECK_PROC (pks, PKS);
fails += CHECK_PROC (pku, PKU);
fails += CHECK_PROC (popcnt, POPCNT);
fails += CHECK_PROC (3dnowprefetch, PREFETCHW);
fails += CHECK_PROC (prefetchwt1, PREFETCHWT1);
fails += CHECK_PROC (pse, PSE);
fails += CHECK_PROC (pse36, PSE_36);
fails += CHECK_PROC (psn, PSN);
fails += CHECK_PROC (rdpid, RDPID);
fails += CHECK_PROC (rdrand, RDRAND);
fails += CHECK_PROC (rdseed, RDSEED);
fails += CHECK_PROC (rdt_a, RDT_A);
fails += CHECK_PROC (cqm, RDT_M);
fails += CHECK_PROC (rdtscp, RDTSCP);
fails += CHECK_PROC (rtm, RTM);
fails += CHECK_PROC (sdbg, SDBG);
fails += CHECK_PROC (sep, SEP);
fails += CHECK_PROC (serialize, SERIALIZE);
fails += CHECK_PROC (sgx, SGX);
fails += CHECK_PROC (sgx_lc, SGX_LC);
fails += CHECK_PROC (sha_ni, SHA);
fails += CHECK_PROC (shstk, SHSTK);
fails += CHECK_PROC (smap, SMAP);
fails += CHECK_PROC (smep, SMEP);
fails += CHECK_PROC (smx, SMX);
fails += CHECK_PROC (ss, SS);
fails += CHECK_PROC (ssbd, SSBD);
fails += CHECK_PROC (sse, SSE);
fails += CHECK_PROC (sse2, SSE2);
fails += CHECK_PROC (sse3, SSE3);
fails += CHECK_PROC (sse4_1, SSE4_1);
fails += CHECK_PROC (sse4_2, SSE4_2);
fails += CHECK_PROC (sse4a, SSE4A);
fails += CHECK_PROC (ssse3, SSSE3);
fails += CHECK_PROC (stibp, STIBP);
fails += CHECK_PROC (svm, SVM);
#ifdef __x86_64__
/* NB: SYSCALL_SYSRET is 64-bit only. */
fails += CHECK_PROC (syscall, SYSCALL_SYSRET);
#endif
fails += CHECK_PROC (tbm, TBM);
fails += CHECK_PROC (tm, TM);
fails += CHECK_PROC (tm2, TM2);
fails += CHECK_PROC (intel_pt, TRACE);
fails += CHECK_PROC (tsc, TSC);
fails += CHECK_PROC (tsc_adjust, TSC_ADJUST);
fails += CHECK_PROC (tsc_deadline, TSC_DEADLINE);
fails += CHECK_PROC (tsxldtrk, TSXLDTRK);
fails += CHECK_PROC (umip, UMIP);
fails += CHECK_PROC (vaes, VAES);
fails += CHECK_PROC (vme, VME);
fails += CHECK_PROC (vmx, VMX);
fails += CHECK_PROC (vpclmulqdq, VPCLMULQDQ);
fails += CHECK_PROC (waitpkg, WAITPKG);
fails += CHECK_PROC (wbnoinvd, WBNOINVD);
fails += CHECK_PROC (x2apic, X2APIC);
fails += CHECK_PROC (xfd, XFD);
fails += CHECK_PROC (xgetbv1, XGETBV_ECX_1);
fails += CHECK_PROC (xop, XOP);
fails += CHECK_PROC (xsave, XSAVE);
fails += CHECK_PROC (xsavec, XSAVEC);
fails += CHECK_PROC (xsaveopt, XSAVEOPT);
fails += CHECK_PROC (xsaves, XSAVES);
fails += CHECK_PROC (xtpr, XTPRUPDCTRL);
printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails);
return (fails != 0);
}
#include "../../../test-skeleton.c"

View File

@ -0,0 +1,192 @@
/* Test CPU feature data against __builtin_cpu_supports.
This file is part of the GNU C Library.
Copyright (C) 2020 Free Software Foundation, Inc.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <sys/platform/x86.h>
#include <stdio.h>
int
check_supports (int supports, int usable, const char *supports_name,
const char *name)
{
printf ("Checking %s:\n", name);
printf (" %s: %d\n", name, usable);
printf (" __builtin_cpu_supports (%s): %d\n",
supports_name, supports);
if ((supports != 0) != (usable != 0))
{
printf (" *** failure ***\n");
return 1;
}
return 0;
}
#define CHECK_SUPPORTS(str, name) \
check_supports (__builtin_cpu_supports (#str), \
CPU_FEATURE_USABLE (name), \
#str, "HAS_CPU_FEATURE (" #name ")");
static int
do_test (int argc, char **argv)
{
int fails = 0;
#if __GNUC_PREREQ (11, 0)
fails += CHECK_SUPPORTS (adx, ADX);
#endif
#if __GNUC_PREREQ (6, 0)
fails += CHECK_SUPPORTS (aes, AES);
#endif
#if __GNUC_PREREQ (11, 1)
fails += CHECK_SUPPORTS (amx_bf16, AMX_BF16);
fails += CHECK_SUPPORTS (amx_int8, AMX_INT8);
fails += CHECK_SUPPORTS (amx_tile, AMX_TILE);
#endif
fails += CHECK_SUPPORTS (avx, AVX);
fails += CHECK_SUPPORTS (avx2, AVX2);
#if __GNUC_PREREQ (7, 0)
fails += CHECK_SUPPORTS (avx5124fmaps, AVX512_4FMAPS);
fails += CHECK_SUPPORTS (avx5124vnniw, AVX512_4VNNIW);
#endif
#if __GNUC_PREREQ (10, 0)
fails += CHECK_SUPPORTS (avx512bf16, AVX512_BF16);
#endif
#if __GNUC_PREREQ (8, 0)
fails += CHECK_SUPPORTS (avx512bitalg, AVX512_BITALG);
#endif
#if __GNUC_PREREQ (6, 0)
fails += CHECK_SUPPORTS (avx512ifma, AVX512_IFMA);
fails += CHECK_SUPPORTS (avx512vbmi, AVX512_VBMI);
#endif
#if __GNUC_PREREQ (8, 0)
fails += CHECK_SUPPORTS (avx512vbmi2, AVX512_VBMI2);
fails += CHECK_SUPPORTS (avx512vnni, AVX512_VNNI);
#endif
#if __GNUC_PREREQ (10, 0)
fails += CHECK_SUPPORTS (avx512vp2intersect, AVX512_VP2INTERSECT);
#endif
#if __GNUC_PREREQ (7, 0)
fails += CHECK_SUPPORTS (avx512vpopcntdq, AVX512_VPOPCNTDQ);
#endif
#if __GNUC_PREREQ (6, 0)
fails += CHECK_SUPPORTS (avx512bw, AVX512BW);
fails += CHECK_SUPPORTS (avx512cd, AVX512CD);
fails += CHECK_SUPPORTS (avx512er, AVX512ER);
fails += CHECK_SUPPORTS (avx512dq, AVX512DQ);
#endif
#if __GNUC_PREREQ (5, 0)
fails += CHECK_SUPPORTS (avx512f, AVX512F);
#endif
#if __GNUC_PREREQ (6, 0)
fails += CHECK_SUPPORTS (avx512pf, AVX512PF);
fails += CHECK_SUPPORTS (avx512vl, AVX512VL);
#endif
#if __GNUC_PREREQ (5, 0)
fails += CHECK_SUPPORTS (bmi, BMI1);
fails += CHECK_SUPPORTS (bmi2, BMI2);
#endif
#if __GNUC_PREREQ (11, 0)
fails += CHECK_SUPPORTS (cldemote, CLDEMOTE);
fails += CHECK_SUPPORTS (clflushopt, CLFLUSHOPT);
fails += CHECK_SUPPORTS (clwb, CLWB);
#endif
fails += CHECK_SUPPORTS (cmov, CMOV);
#if __GNUC_PREREQ (11, 0)
fails += CHECK_SUPPORTS (cmpxchg16b, CMPXCHG16B);
fails += CHECK_SUPPORTS (cmpxchg8b, CX8);
fails += CHECK_SUPPORTS (enqcmd, ENQCMD);
fails += CHECK_SUPPORTS (f16c, F16C);
#endif
#if __GNUC_PREREQ (4, 9)
fails += CHECK_SUPPORTS (fma, FMA);
fails += CHECK_SUPPORTS (fma4, FMA4);
#endif
#if __GNUC_PREREQ (11, 0)
fails += CHECK_SUPPORTS (fsgsbase, FSGSBASE);
fails += CHECK_SUPPORTS (fxsave, FXSR);
#endif
#if __GNUC_PREREQ (8, 0)
fails += CHECK_SUPPORTS (gfni, GFNI);
#endif
#if __GNUC_PREREQ (11, 0)
fails += CHECK_SUPPORTS (hle, HLE);
fails += CHECK_SUPPORTS (ibt, IBT);
fails += CHECK_SUPPORTS (lahf_lm, LAHF64_SAHF64);
fails += CHECK_SUPPORTS (lm, LM);
fails += CHECK_SUPPORTS (lwp, LWP);
fails += CHECK_SUPPORTS (lzcnt, LZCNT);
#endif
fails += CHECK_SUPPORTS (mmx, MMX);
#if __GNUC_PREREQ (11, 0)
fails += CHECK_SUPPORTS (movbe, MOVBE);
fails += CHECK_SUPPORTS (movdiri, MOVDIRI);
fails += CHECK_SUPPORTS (movdir64b, MOVDIR64B);
fails += CHECK_SUPPORTS (osxsave, OSXSAVE);
fails += CHECK_SUPPORTS (pconfig, PCONFIG);
fails += CHECK_SUPPORTS (pku, PKU);
#endif
fails += CHECK_SUPPORTS (popcnt, POPCNT);
#if __GNUC_PREREQ (11, 0)
fails += CHECK_SUPPORTS (prefetchwt1, PREFETCHWT1);
fails += CHECK_SUPPORTS (rdpid, RDPID);
fails += CHECK_SUPPORTS (rdrnd, RDRAND);
fails += CHECK_SUPPORTS (rdseed, RDSEED);
fails += CHECK_SUPPORTS (rtm, RTM);
fails += CHECK_SUPPORTS (serialize, SERIALIZE);
fails += CHECK_SUPPORTS (sha, SHA);
fails += CHECK_SUPPORTS (shstk, SHSTK);
#endif
fails += CHECK_SUPPORTS (sse, SSE);
fails += CHECK_SUPPORTS (sse2, SSE2);
fails += CHECK_SUPPORTS (sse3, SSE3);
fails += CHECK_SUPPORTS (sse4.1, SSE4_1);
fails += CHECK_SUPPORTS (sse4.2, SSE4_2);
#if __GNUC_PREREQ (4, 9)
fails += CHECK_SUPPORTS (sse4a, SSE4A);
#endif
fails += CHECK_SUPPORTS (ssse3, SSSE3);
#if __GNUC_PREREQ (11, 0)
fails += CHECK_SUPPORTS (tbm, TBM);
fails += CHECK_SUPPORTS (tsxldtrk, TSXLDTRK);
fails += CHECK_SUPPORTS (vaes, VAES);
#endif
#if __GNUC_PREREQ (8, 0)
fails += CHECK_SUPPORTS (vpclmulqdq, VPCLMULQDQ);
#endif
#if __GNUC_PREREQ (11, 0)
fails += CHECK_SUPPORTS (waitpkg, WAITPKG);
fails += CHECK_SUPPORTS (wbnoinvd, WBNOINVD);
#endif
#if __GNUC_PREREQ (4, 9)
fails += CHECK_SUPPORTS (xop, XOP);
#endif
#if __GNUC_PREREQ (11, 0)
fails += CHECK_SUPPORTS (xsave, XSAVE);
fails += CHECK_SUPPORTS (xsavec, XSAVEC);
fails += CHECK_SUPPORTS (xsaveopt, XSAVEOPT);
fails += CHECK_SUPPORTS (xsaves, XSAVES);
#endif
printf ("%d differences between __builtin_cpu_supports and glibc code.\n",
fails);
return (fails != 0);
}
#include "../../../test-skeleton.c"

View File

@ -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. Copyright (C) 2015-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
@ -18,7 +18,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <cpu-features.h> #include <sys/platform/x86.h>
#include <support/check.h> #include <support/check.h>
#define CHECK_CPU_FEATURE(name) \ #define CHECK_CPU_FEATURE(name) \
@ -45,7 +45,7 @@ static const char * const cpu_kinds[] =
static int static int
do_test (void) 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) switch (cpu_features->basic.kind)
{ {

View File

@ -16,7 +16,7 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */ <https://www.gnu.org/licenses/>. */
#include <cpu-features.h> #include <sys/platform/x86.h>
#if defined REQUIRE_AVX #if defined REQUIRE_AVX

View File

@ -1,7 +1,3 @@
ifeq ($(subdir),csu)
tests += test-multiarch
endif
ifeq ($(subdir),string) ifeq ($(subdir),string)
sysdep_routines += strncat-c stpncpy-c strncpy-c \ sysdep_routines += strncat-c stpncpy-c strncpy-c \

View File

@ -1,96 +0,0 @@
/* Test CPU feature data.
This file is part of the GNU C Library.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <cpu-features.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char *cpu_flags;
/* Search for flags in /proc/cpuinfo and store line
in cpu_flags. */
void
get_cpuinfo (void)
{
FILE *f;
char *line = NULL;
size_t len = 0;
ssize_t read;
f = fopen ("/proc/cpuinfo", "r");
if (f == NULL)
{
printf ("cannot open /proc/cpuinfo\n");
exit (1);
}
while ((read = getline (&line, &len, f)) != -1)
{
if (strncmp (line, "flags", 5) == 0)
{
cpu_flags = strdup (line);
break;
}
}
fclose (f);
free (line);
}
int
check_proc (const char *proc_name, int flag, const char *name)
{
int found = 0;
printf ("Checking %s:\n", name);
printf (" init-arch %d\n", flag);
if (strstr (cpu_flags, proc_name) != NULL)
found = 1;
printf (" cpuinfo (%s) %d\n", proc_name, found);
if (found != flag)
printf (" *** failure ***\n");
return (found != flag);
}
static int
do_test (int argc, char **argv)
{
int fails;
get_cpuinfo ();
fails = check_proc ("avx", CPU_FEATURE_USABLE (AVX),
"CPU_FEATURE_USABLE (AVX)");
fails += check_proc ("fma4", CPU_FEATURE_USABLE (FMA4),
"CPU_FEATURE_USABLE (FMA4)");
fails += check_proc ("sse4_2", CPU_FEATURE_USABLE (SSE4_2),
"CPU_FEATURE_USABLE (SSE4_2)");
fails += check_proc ("sse4_1", CPU_FEATURE_USABLE (SSE4_1)
, "CPU_FEATURE_USABLE (SSE4_1)");
fails += check_proc ("ssse3", CPU_FEATURE_USABLE (SSSE3),
"CPU_FEATURE_USABLE (SSSE3)");
fails += check_proc ("popcnt", CPU_FEATURE_USABLE (POPCNT),
"CPU_FEATURE_USABLE (POPCNT)");
printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails);
return (fails != 0);
}
#include "../../../test-skeleton.c"