This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
RFC: Add <sys/platform/x86.h> to glibc 2.29
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- To: GNU C Library <libc-alpha at sourceware dot org>
- Date: Sun, 29 Jul 2018 09:16:23 -0700
- Subject: RFC: Add <sys/platform/x86.h> to glibc 2.29
I am proposing to add <sys/platform/x86.h> to glibc 2.29 to provide
an API to access x86 specific platform features:
enum
{
/* The integer bit array index of architecture feature bits. */
FEATURE_INDEX_1 = 0,
FEATURE_INDEX_2,
/* The current maximum size of the feature integer bit array. */
FEATURE_INDEX_MAX
};
enum
{
COMMON_CPUID_INDEX_1 = 0,
COMMON_CPUID_INDEX_7,
COMMON_CPUID_INDEX_80000001,
COMMON_CPUID_INDEX_D_ECX_1,
COMMON_CPUID_INDEX_80000007,
COMMON_CPUID_INDEX_80000008,
/* Keep the following line at the end. */
COMMON_CPUID_INDEX_MAX
};
enum cpu_features_kind
{
arch_kind_unknown = 0,
arch_kind_intel,
arch_kind_amd,
arch_kind_other
};
struct cpuid_registers
{
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
};
extern enum cpu_features_kind __x86_get_cpu_kind (void)
__attribute__ ((const));
extern const struct cpuid_registers *__x86_get_cpuid_registers
(unsigned int) __attribute__ ((const));
extern unsigned int __x86_get_arch_feature (unsigned int)
__attribute__ ((const));
extern unsigned long long __x86_tsc_to_ns (unsigned long long);
extern unsigned long long __x86_ns_to_tsc (unsigned long long);
/* HAS_* evaluates to true if we may use the feature at runtime. */
#define HAS_CPU_FEATURE(name) \
((__x86_get_cpuid_registers (index_cpu_##name)->reg_##name \
& (bit_cpu_##name)) != 0)
#define HAS_ARCH_FEATURE(name) \
((__x86_get_arch_feature (index_arch_##name) & (bit_arch_##name)) != 0)
Users can use <sys/platform/x86.h> to detect if a CPU feature is
supported at run-time with
HAS_CPU_FEATURE (AVX)
which returns true if glibc detects that AVX is available. Before AVX
can be used, he/she should check
HAS_ARCH_FEATURE (AVX_Usable)
which returns true if glibc detects that AVX is available and usable.
extern unsigned long long __x86_tsc_to_ns (unsigned long long);
extern unsigned long long __x86_ns_to_tsc (unsigned long long);
can be used to convert between TSCs and nanoseconds if
HAS_ARCH_FEATURE (TSC_To_NS_Usable)
returns true.
Backward binary compatibility is provided by:
1. __x86_get_cpu_kind will get a new version if a new CPU kind is added
to cpu_features_kind.
2. __x86_get_cpuid_registers returns a pointer to a cpuid_registers
with all zeros if cpuid index >= COMMON_CPUID_INDEX_MAX.
3. __x86_get_arch_feature returns 0 if architecture index >=
FEATURE_INDEX_MAX.
This means:
1. Applications linked against the new __x86_get_cpu_kind will only
run with the newer libc.so.
2. Applications linked against the new __x86_get_cpuid_registers and
__x86_get_arch_feature will run with the older libc.so. But new
CPU and architecture features won't be detected by the older libc.so.
This program:
https://github.com/hjl-tools/glibc/blob/hjl/platform/master/sysdeps/x86/tst-x86-platform-1.c
may display:
[hjl@gnu-efi-2 build-x86_64-linux]$ ./elf/tst-x86-platform-1
Vendor: Intel
CPU features:
SSE3
PCLMULQDQ
DTES64
MONITOR
DS_CPL
VMX
EST
TM2
SSSE3
SDBG
FMA
CMPXCHG16B
XTPRUPDCTRL
PDCM
PCID
SSE4_1
SSE4_2
X2APIC
MOVBE
POPCOUNT
TSC_DEADLINE
AES
XSAVE
OSXSAVE
AVX
F16C
RDRAND
FPU
VME
DE
PSE
TSC
MSR
PAE
MCE
CX8
APIC
SEP
MTRR
PGE
MCA
CMOV
PAT
PSE_36
DS
ACPI
MMX
FXSR
SSE
SSE2
SS
HTT
TM
PBE
FSGSBASE
TSC_ADJUST
SGX
BMI1
AVX2
BMI2
ERMS
INVPCID
MPX
RDSEED
ADX
SMAP
TRACE
LAHF64_SAHF64
LZCNT
PREFETCHW
SYSCALL_SYSRET
NX
PAGE1GB
RDTSCP
LM
XSAVEOPT
XSAVEC
XGETBV_ECX_1
XSAVES
INVARIANT_TSC
Architecture features:
AVX_Usable
AVX2_Usable
FMA_Usable
XSAVEC_Usable
TSC_To_NS_Usable
[hjl@gnu-efi-2 build-x86_64-linux]$
Any comments?
H.J.