mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-09 14:50:05 +00:00
WIP CPUID consistency checks
This commit is contained in:
parent
815c048269
commit
11db7b454a
@ -15,6 +15,12 @@ gen-as-const-headers += sigaltstack-offsets.sym
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),elf)
|
||||
sysdep-dl-routines += dl-x86_probes
|
||||
shared-only-routines += dl-x86_probes
|
||||
# Used internally by dl-x86_cpu_feature_diagnostics.c.
|
||||
CFLAGS-dl-catch.os += $(rtld-early-cflags)
|
||||
CFLAGS-rtld-__longjmp.os += $(rtld-early-cflags)
|
||||
|
||||
ifeq (yes,$(enable-x86-isa-level))
|
||||
tests += \
|
||||
tst-glibc-hwcaps-2 \
|
||||
|
227
sysdeps/unix/sysv/linux/x86_64/dl-x86_cpu_feature_diagnostics.c
Normal file
227
sysdeps/unix/sysv/linux/x86_64/dl-x86_cpu_feature_diagnostics.c
Normal file
@ -0,0 +1,227 @@
|
||||
/* CPU diagnostics probing. Linux/x86-64 version.
|
||||
Copyright (C) 2024 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/>. */
|
||||
|
||||
#include <cpu-features.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sysdep.h>
|
||||
|
||||
static void
|
||||
_dl_x86_probe (struct x86_cpu_feature_diagnostics *diag, bool reported,
|
||||
void (*probe) (void))
|
||||
{
|
||||
if (reported)
|
||||
diag->reported |= 1ULL << diag->count;
|
||||
|
||||
/* Use fork/waitid for crash handling. This is simpler than using
|
||||
signal handling: it does not need global data to communicate with
|
||||
the handler, nor building out-of-line helper functions to the
|
||||
baseline ISA, and it avoids dealing differences in sigset_t size. */
|
||||
long int ret = INTERNAL_SYSCALL_CALL (fork);
|
||||
if (ret == 0)
|
||||
{
|
||||
/* New process that runs the probe. This may trigger a crash. */
|
||||
probe ();
|
||||
|
||||
INTERNAL_SYSCALL_CALL (exit_group, 0);
|
||||
}
|
||||
else if (ret > 0)
|
||||
{
|
||||
siginfo_t si;
|
||||
ret = INTERNAL_SYSCALL_CALL (waitid, P_PID, ret, &si, WEXITED, NULL);
|
||||
if (ret >=0 && si.si_status == 0)
|
||||
/* Probe was successful. */
|
||||
diag->probed |= 1ULL << diag->count;
|
||||
}
|
||||
|
||||
++diag->count;
|
||||
}
|
||||
|
||||
void
|
||||
_dl_x86_cpu_feature_diagnostics_run (const struct cpu_features *cpu_features,
|
||||
struct x86_cpu_feature_diagnostics *diag)
|
||||
{
|
||||
/* x86-64-v2 features. */
|
||||
extern void _dl_x86_probe_cmpxchg16b (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, CMPXCHG16B),
|
||||
_dl_x86_probe_cmpxchg16b);
|
||||
|
||||
extern void _dl_x86_probe_sahf (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, LAHF64_SAHF64),
|
||||
_dl_x86_probe_sahf);
|
||||
|
||||
extern void _dl_x86_probe_popcnt (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, POPCNT),
|
||||
_dl_x86_probe_popcnt);
|
||||
|
||||
extern void _dl_x86_probe_sse3 (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, SSE3),
|
||||
_dl_x86_probe_sse3);
|
||||
|
||||
extern void _dl_x86_probe_sse4_1 (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, SSE4_1),
|
||||
_dl_x86_probe_sse4_1);
|
||||
|
||||
extern void _dl_x86_probe_sse4_2 (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, SSE4_2),
|
||||
_dl_x86_probe_sse4_2);
|
||||
|
||||
extern void _dl_x86_probe_ssse3 (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, SSSE3),
|
||||
_dl_x86_probe_ssse3);
|
||||
|
||||
/* x86-64-v3 features. */
|
||||
extern void _dl_x86_probe_avx (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX),
|
||||
_dl_x86_probe_avx);
|
||||
|
||||
/* AVX probe using xmm registers. */
|
||||
extern void _dl_x86_probe_avx_xmm (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX),
|
||||
_dl_x86_probe_avx_xmm);
|
||||
|
||||
extern void _dl_x86_probe_avx2 (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX2),
|
||||
_dl_x86_probe_avx2);
|
||||
|
||||
extern void _dl_x86_probe_bmi1 (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, BMI1),
|
||||
_dl_x86_probe_bmi1);
|
||||
|
||||
/* Alternative BMI1 probe. Perhaps harder to mask. */
|
||||
extern void _dl_x86_probe_bmi1_tzcnt (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, BMI1),
|
||||
_dl_x86_probe_bmi1_tzcnt);
|
||||
|
||||
extern void _dl_x86_probe_bmi2 (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, BMI2),
|
||||
_dl_x86_probe_bmi2);
|
||||
|
||||
extern void _dl_x86_probe_f16c (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, F16C),
|
||||
_dl_x86_probe_f16c);
|
||||
|
||||
extern void _dl_x86_probe_fma (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, FMA),
|
||||
_dl_x86_probe_fma);
|
||||
|
||||
/* FMA4 is not part of x86-64-v3, but may produce a useful hint. */
|
||||
extern void _dl_x86_probe_fma4 (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, FMA4),
|
||||
_dl_x86_probe_fma4);
|
||||
|
||||
extern void _dl_x86_probe_lzcnt (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, LZCNT),
|
||||
_dl_x86_probe_lzcnt);
|
||||
|
||||
extern void _dl_x86_probe_movbe (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, MOVBE),
|
||||
_dl_x86_probe_movbe);
|
||||
|
||||
extern void _dl_x86_probe_osxsave (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, OSXSAVE),
|
||||
_dl_x86_probe_osxsave);
|
||||
|
||||
/* x86-64-v4 features. */
|
||||
extern void _dl_x86_probe_avx512f (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX512F),
|
||||
_dl_x86_probe_avx512f);
|
||||
|
||||
extern void _dl_x86_probe_avx512bw (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX512BW),
|
||||
_dl_x86_probe_avx512bw);
|
||||
|
||||
extern void _dl_x86_probe_avx512bw_ymm (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX512BW),
|
||||
_dl_x86_probe_avx512bw_ymm);
|
||||
|
||||
extern void _dl_x86_probe_avx512cd (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX512CD),
|
||||
_dl_x86_probe_avx512cd);
|
||||
|
||||
extern void _dl_x86_probe_avx512cd_ymm0 (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX512CD),
|
||||
_dl_x86_probe_avx512cd_ymm0);
|
||||
|
||||
extern void _dl_x86_probe_avx512vl (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX512VL),
|
||||
_dl_x86_probe_avx512vl);
|
||||
|
||||
/* Other CPU features, not part of microarchitecture levels. */
|
||||
extern void _dl_x86_probe_adx (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, ADX),
|
||||
_dl_x86_probe_adx);
|
||||
|
||||
extern void _dl_x86_probe_aes (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AES),
|
||||
_dl_x86_probe_aes);
|
||||
|
||||
extern void _dl_x86_probe_aes_avx (void) attribute_hidden;
|
||||
_dl_x86_probe (diag,
|
||||
CPU_FEATURE_USABLE_P (cpu_features, AES)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, AVX),
|
||||
_dl_x86_probe_aes_avx);
|
||||
|
||||
extern void _dl_x86_probe_vaes (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, VAES),
|
||||
_dl_x86_probe_vaes);
|
||||
|
||||
extern void _dl_x86_probe_sha (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, SHA),
|
||||
_dl_x86_probe_sha);
|
||||
|
||||
extern void _dl_x86_probe_avx512_vbmi (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX512_VBMI),
|
||||
_dl_x86_probe_avx512_vbmi);
|
||||
|
||||
extern void _dl_x86_probe_avx512_vbmi_xmm (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX512_VBMI),
|
||||
_dl_x86_probe_avx512_vbmi_xmm);
|
||||
|
||||
extern void _dl_x86_probe_avx512_vbmi2 (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX512_VBMI2),
|
||||
_dl_x86_probe_avx512_vbmi2);
|
||||
|
||||
extern void _dl_x86_probe_avx512_vbmi2_xmm (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX512_VBMI2),
|
||||
_dl_x86_probe_avx512_vbmi2_xmm);
|
||||
|
||||
extern void _dl_x86_probe_avx_vnni (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX_VNNI),
|
||||
_dl_x86_probe_avx_vnni);
|
||||
|
||||
extern void _dl_x86_probe_avx512_vnni (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX512_VNNI),
|
||||
_dl_x86_probe_avx512_vnni);
|
||||
|
||||
extern void _dl_x86_probe_avx512_ifma (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, AVX512_IFMA),
|
||||
_dl_x86_probe_avx512_ifma);
|
||||
|
||||
serialize
|
||||
tpause
|
||||
ptwrite
|
||||
xsusldtrk
|
||||
clmul
|
||||
crc32
|
||||
|
||||
extern void _dl_x86_probe_apx_f (void) attribute_hidden;
|
||||
_dl_x86_probe (diag, CPU_FEATURE_USABLE_P (cpu_features, APX_F),
|
||||
_dl_x86_probe_apx_f);
|
||||
}
|
274
sysdeps/unix/sysv/linux/x86_64/dl-x86_probes.S
Normal file
274
sysdeps/unix/sysv/linux/x86_64/dl-x86_probes.S
Normal file
@ -0,0 +1,274 @@
|
||||
/* Diagnostics probes for the x86 CPU family. Generic version.
|
||||
Copyright (C) 2024 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/>. */
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
ENTRY (_dl_x86_probe_cmpxchg16b)
|
||||
xorl %eax, %eax
|
||||
movq %rax, -8(%rsp)
|
||||
movq %rax, -16(%rsp)
|
||||
xorl %edx, %edx
|
||||
cmpxchg16b -8(%rsp)
|
||||
ret
|
||||
END (_dl_x86_probe_cmpxchg16b)
|
||||
|
||||
ENTRY (_dl_x86_probe_sahf)
|
||||
xorl %eax, %eax
|
||||
sahf
|
||||
ret
|
||||
END (_dl_x86_probe_sahf)
|
||||
|
||||
ENTRY (_dl_x86_probe_popcnt)
|
||||
xorl %eax, %eax
|
||||
popcnt %eax, %eax
|
||||
ret
|
||||
END (_dl_x86_probe_popcnt)
|
||||
|
||||
ENTRY (_dl_x86_probe_sse3)
|
||||
pxor %xmm0, %xmm0
|
||||
addsubpd %xmm0, %xmm0
|
||||
ret
|
||||
END (_dl_x86_probe_sse3)
|
||||
|
||||
ENTRY (_dl_x86_probe_sse4_1)
|
||||
pxor %xmm0, %xmm0
|
||||
blendpd $1, %xmm0, %xmm0
|
||||
ret
|
||||
END (_dl_x86_probe_sse4_1)
|
||||
|
||||
ENTRY (_dl_x86_probe_sse4_2)
|
||||
pxor %xmm0, %xmm0
|
||||
pcmpestri $0, %xmm0, %xmm0
|
||||
ret
|
||||
END (_dl_x86_probe_sse4_2)
|
||||
|
||||
ENTRY (_dl_x86_probe_ssse3)
|
||||
pxor %xmm0, %xmm0
|
||||
phaddd %xmm0, %xmm0
|
||||
ret
|
||||
END (_dl_x86_probe_ssse3)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx)
|
||||
vzeroall
|
||||
ret
|
||||
END (_dl_x86_probe_avx)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx_xmm)
|
||||
pxor %xmm0, %xmm0
|
||||
pxor %xmm1, %xmm1
|
||||
vpxor %xmm0, %xmm1, %xmm2
|
||||
ret
|
||||
END (_dl_x86_probe_avx_xmm)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx2)
|
||||
vpxor %ymm0, %ymm0, %ymm0
|
||||
vpermd %ymm0, %ymm0, %ymm0
|
||||
ret
|
||||
END (_dl_x86_probe_avx2)
|
||||
|
||||
ENTRY (_dl_x86_probe_bmi1)
|
||||
xorl %eax, %eax
|
||||
andnl %eax, %eax, %eax
|
||||
ret
|
||||
END (_dl_x86_probe_bmi1)
|
||||
|
||||
ENTRY (_dl_x86_probe_bmi1_tzcnt)
|
||||
xorl %eax, %eax
|
||||
/* Executes as bsfl if unsupported. */
|
||||
tzcntl %eax, %eax
|
||||
cmp $32, %eax
|
||||
jne 1f
|
||||
ret
|
||||
1:
|
||||
ud2
|
||||
END (_dl_x86_probe_bmi1_tzcnt)
|
||||
|
||||
ENTRY (_dl_x86_probe_bmi2)
|
||||
xorl %eax, %eax
|
||||
bzhil %eax, %eax, %eax
|
||||
ret
|
||||
END (_dl_x86_probe_bmi2)
|
||||
|
||||
ENTRY (_dl_x86_probe_f16c)
|
||||
pxor %xmm0, %xmm0
|
||||
vcvtph2ps %xmm0, %xmm0
|
||||
ret
|
||||
END (_dl_x86_probe_f16c)
|
||||
|
||||
ENTRY (_dl_x86_probe_fma)
|
||||
pxor %xmm0, %xmm0
|
||||
vfmadd132pd %xmm0, %xmm0, %xmm0
|
||||
ret
|
||||
END (_dl_x86_probe_fma)
|
||||
|
||||
ENTRY (_dl_x86_probe_fma4)
|
||||
pxor %xmm0, %xmm0
|
||||
vfmaddpd %xmm0, %xmm0, %xmm0, %xmm0
|
||||
ret
|
||||
END (_dl_x86_probe_fma4)
|
||||
|
||||
ENTRY (_dl_x86_probe_lzcnt)
|
||||
xorl %eax, %eax
|
||||
/* Executes as bsrl if unsupported. */
|
||||
lzcntl %eax, %eax
|
||||
cmp $32, %eax
|
||||
jne 1f
|
||||
ret
|
||||
1:
|
||||
ud2
|
||||
END (_dl_x86_probe_lzcnt)
|
||||
|
||||
ENTRY (_dl_x86_probe_movbe)
|
||||
movbeq (%rsp), %rax
|
||||
ret
|
||||
1:
|
||||
ud2
|
||||
END (_dl_x86_probe_movbe)
|
||||
|
||||
ENTRY (_dl_x86_probe_osxsave)
|
||||
xorl %ecx, %ecx
|
||||
xgetbv
|
||||
ret
|
||||
END (_dl_x86_probe_osxsave)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512f)
|
||||
xorl %eax, %eax
|
||||
kmovw %eax, %k0
|
||||
ret
|
||||
END (_dl_x86_probe_avx512f)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512bw)
|
||||
vpxorq %zmm0, %zmm0, %zmm0
|
||||
vdbpsadbw $0, %zmm0, %zmm0, %zmm0
|
||||
ret
|
||||
END (_dl_x86_probe_avx512bw)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512bw_ymm)
|
||||
vpxorq %ymm0, %ymm0, %ymm0
|
||||
vdbpsadbw $0, %ymm0, %ymm0, %ymm0
|
||||
ret
|
||||
END (_dl_x86_probe_avx512bw)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512cd)
|
||||
vpxorq %zmm0, %zmm0, %zmm0
|
||||
vplzcntd %zmm0, %zmm0
|
||||
ret
|
||||
END (_dl_x86_probe_avx512cd)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512cd_ymm0)
|
||||
vpxorq %ymm0, %ymm0, %ymm0
|
||||
vplzcntd %ymm0, %ymm0
|
||||
ret
|
||||
END (_dl_x86_probe_avx512cd_ymm0)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512dq)
|
||||
vpxorq %zmm0, %zmm0, %zmm0
|
||||
vpmullq %zmm0, %zmm0, %zmm0
|
||||
ret
|
||||
END (_dl_x86_probe_avx512dq)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512dq_ymm0)
|
||||
vpxorq %ymm0, %ymm0, %ymm0
|
||||
vpmulld %ymm0, %ymm0, %ymm0
|
||||
ret
|
||||
END (_dl_x86_probe_avx512dq_ymm0)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512vl)
|
||||
xorl %eax, %eax
|
||||
vpbroadcastq %rax, %xmm1
|
||||
ret
|
||||
END (_dl_x86_probe_avx512vl)
|
||||
|
||||
ENTRY (_dl_x86_probe_adx)
|
||||
xorl %eax, %eax
|
||||
adcxl %eax, %eax
|
||||
ret
|
||||
END (_dl_x86_probe_adx)
|
||||
|
||||
ENTRY (_dl_x86_probe_aes)
|
||||
pxor %xmm0, %xmm0
|
||||
aesenc %xmm0, %xmm0
|
||||
ret
|
||||
END (_dl_x86_probe_aes)
|
||||
|
||||
ENTRY (_dl_x86_probe_aes_avx)
|
||||
pxor %xmm0, %xmm0
|
||||
vaesenc %xmm0, %xmm0, %xmm0
|
||||
ret
|
||||
END (_dl_x86_probe_aes_avx)
|
||||
|
||||
ENTRY (_dl_x86_probe_vaes)
|
||||
vpxor %ymm0, %ymm0, %ymm0
|
||||
vaesenc %ymm0, %ymm0, %ymm0
|
||||
ret
|
||||
END (_dl_x86_probe_vaes)
|
||||
|
||||
ENTRY (_dl_x86_probe_sha)
|
||||
pxor %xmm0, %xmm0
|
||||
sha1rnds4 $0, %xmm0, %xmm0
|
||||
ret
|
||||
END (_dl_x86_probe_sha)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512_vbmi)
|
||||
vpxorq %zmm0, %zmm0, %zmm0
|
||||
vpermb %zmm0, %zmm0, %zmm0
|
||||
ret
|
||||
END (_dl_x86_probe_avx512_vbmi)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512_vbmi_xmm)
|
||||
pxor %xmm0, %xmm0
|
||||
vpermb %xmm0, %xmm0, %xmm0
|
||||
ret
|
||||
END (_dl_x86_probe_avx512_vbmi_xmm)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512_vbmi2)
|
||||
vpxorq %zmm0, %zmm0, %zmm0
|
||||
vpshrdd $1, %zmm0, %zmm0, %zmm0
|
||||
ret
|
||||
END (_dl_x86_probe_avx512_vbmi2)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512_vbmi2_xmm)
|
||||
pxor %xmm0, %xmm0
|
||||
vpshrdd $1, %xmm0, %xmm0, %xmm0
|
||||
ret
|
||||
END (_dl_x86_probe_avx512_vbmi2_xmm)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx_vnni)
|
||||
pxor %xmm0, %xmm0
|
||||
/* Default is to use EVEX encoding. */
|
||||
/* {vex} vpdpbusd %xmm0, %xmm0, %xmm0 */
|
||||
.byte 0xc4, 0xe2, 0x79, 0x50, 0xc0
|
||||
ret
|
||||
END (_dl_x86_probe_avx_vnni)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512_vnni)
|
||||
vpxorq %zmm0, %zmm0, %zmm0
|
||||
vpdpbusd %zmm0, %zmm0, %zmm0
|
||||
ret
|
||||
END (_dl_x86_probe_avx512_vnni)
|
||||
|
||||
ENTRY (_dl_x86_probe_avx512_ifma)
|
||||
vpxorq %zmm0, %zmm0, %zmm0
|
||||
vpmadd52luq %zmm0, %zmm0, %zmm0
|
||||
ret
|
||||
END (_dl_x86_probe_avx512_ifma)
|
||||
|
||||
ENTRY (_dl_x86_probe_apx_f)
|
||||
.byte 0x62, 0xf4, 0x7c, 0x18, 0x01, 0xff /* add %edi, %edi, %eax */
|
||||
ret
|
||||
END (_dl_x86_probe_apx_f)
|
@ -0,0 +1,34 @@
|
||||
# CPU diagnostics probing. Generating documentatable for t he manual
|
||||
# Copyright (C) 2024 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/>.
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
path, = sys.argv[1:]
|
||||
|
||||
RE_PROBE = re.compile('^\s+_dl_x86_probe_([a-z0-9_]+)\);$')
|
||||
|
||||
bit = 1
|
||||
with open(path) as inp:
|
||||
for line in inp:
|
||||
m = RE_PROBE.match(line)
|
||||
if m:
|
||||
name = m.group(1)
|
||||
print('@item 0x{:08x}:{:08x}'.format(bit >> 32, bit & 0xffffffff))
|
||||
print('@code{' + name + '}')
|
||||
bit *= 2
|
@ -4,7 +4,11 @@ endif
|
||||
|
||||
ifeq ($(subdir),elf)
|
||||
sysdep_routines += get-cpuid-feature-leaf
|
||||
sysdep-dl-routines += dl-get-cpu-features
|
||||
sysdep-dl-routines += \
|
||||
dl-get-cpu-features \
|
||||
dl-x86_cpu_feature_diagnostics \
|
||||
# sysdep-dl-routines
|
||||
shared-only-routines += dl-x86_cpu_feature_diagnostics
|
||||
sysdep_headers += \
|
||||
bits/platform/features.h \
|
||||
bits/platform/x86.h \
|
||||
@ -12,6 +16,7 @@ sysdep_headers += \
|
||||
# sysdep_headers
|
||||
|
||||
CFLAGS-dl-get-cpu-features.os += $(rtld-early-cflags)
|
||||
CFLAGS-dl-x86_cpu_feature_diagnostics.os += $(rtld-early-cflags)
|
||||
CFLAGS-get-cpuid-feature-leaf.o += $(no-stack-protector)
|
||||
|
||||
tests += \
|
||||
|
@ -51,6 +51,14 @@ print_cpu_feature_preferred (const char *label, unsigned int flag)
|
||||
_dl_printf("x86.cpu_features.preferred.%s=0x%x\n", label, flag);
|
||||
}
|
||||
|
||||
static void
|
||||
_dl_x86_cpu_feature_diagnostics_print (const char *label,
|
||||
unsigned long long int value)
|
||||
{
|
||||
_dl_printf("x86.diagnostics.");
|
||||
_dl_diagnostics_print_labeled_value (label, value);
|
||||
}
|
||||
|
||||
void
|
||||
_dl_diagnostics_cpu (void)
|
||||
{
|
||||
@ -132,6 +140,17 @@ _dl_diagnostics_cpu (void)
|
||||
== sizeof (*cpu_features),
|
||||
"last cpu_features field has been printed");
|
||||
|
||||
{
|
||||
struct x86_cpu_feature_diagnostics diag;
|
||||
_dl_x86_cpu_feature_diagnostics_init (&diag);
|
||||
_dl_x86_cpu_feature_diagnostics_run (cpu_features, &diag);
|
||||
_dl_x86_cpu_feature_diagnostics_print ("count", diag.count);
|
||||
_dl_x86_cpu_feature_diagnostics_print ("reported", diag.reported);
|
||||
_dl_x86_cpu_feature_diagnostics_print ("probed", diag.probed);
|
||||
_dl_x86_cpu_feature_diagnostics_print ("filtered",
|
||||
diag.probed & ~diag.reported);
|
||||
}
|
||||
|
||||
_dl_diagnostics_cpuid ();
|
||||
}
|
||||
|
||||
|
@ -33,14 +33,20 @@ void (*const __x86_cpu_features_p) (void) attribute_hidden
|
||||
= __x86_cpu_features;
|
||||
|
||||
_Noreturn static void __attribute__ ((unused))
|
||||
_dl_x86_init_cpu_failure (const struct cpu_features *cpu_features, int level)
|
||||
_dl_x86_init_cpu_failure (const struct cpu_features *cpu_features,
|
||||
const char *label)
|
||||
{
|
||||
if (level == 5)
|
||||
_dl_fatal_printf ("\
|
||||
Fatal glibc error: CPU does not support APX\n");
|
||||
else
|
||||
_dl_fatal_printf ("\
|
||||
Fatal glibc error: CPU does not support x86-64-v%d\n", level);
|
||||
struct x86_cpu_feature_diagnostics diag;
|
||||
_dl_x86_cpu_feature_diagnostics_init (&diag);
|
||||
_dl_x86_cpu_feature_diagnostics_run (cpu_features, &diag);
|
||||
|
||||
_dl_fatal_printf ("\
|
||||
Fatal glibc error: CPU does not support %s [%u 0x%x:%x 0x%x:%x]\n",
|
||||
label, diag.count,
|
||||
(unsigned int) (diag.reported >> 32),
|
||||
(unsigned int) diag.reported,
|
||||
(unsigned int) (diag.probed >> 32),
|
||||
(unsigned int) diag.probed);
|
||||
}
|
||||
|
||||
void
|
||||
@ -58,23 +64,23 @@ _dl_x86_init_cpu_features (void)
|
||||
&& defined GCCMACRO__SSE3__ && defined GCCMACRO__SSSE3__ \
|
||||
&& defined GCCMACRO__SSE4_1__ && defined GCCMACRO__SSE4_2__
|
||||
if (!(cpu_features->isa_1 & GNU_PROPERTY_X86_ISA_1_V2))
|
||||
_dl_x86_init_cpu_failure (cpu_features, 2);
|
||||
_dl_x86_init_cpu_failure (cpu_features, "x86-64-v2");
|
||||
# if defined GCCMACRO__AVX__ && defined GCCMACRO__AVX2__ \
|
||||
&& defined GCCMACRO__F16C__ && defined GCCMACRO__FMA__ \
|
||||
&& defined GCCMACRO__LZCNT__ && defined HAVE_X86_MOVBE
|
||||
if (!(cpu_features->isa_1 & GNU_PROPERTY_X86_ISA_1_V3))
|
||||
_dl_x86_init_cpu_failure (cpu_features, 3);
|
||||
_dl_x86_init_cpu_failure (cpu_features, "x86-64-v3");
|
||||
# if defined GCCMACRO__AVX512F__ && defined GCCMACRO__AVX512BW__ \
|
||||
&& defined GCCMACRO__AVX512CD__ && defined GCCMACRO__AVX512DQ__ \
|
||||
&& defined GCCMACRO__AVX512VL__
|
||||
if (!(cpu_features->isa_1 & GNU_PROPERTY_X86_ISA_1_V4))
|
||||
_dl_x86_init_cpu_failure (cpu_features, 4);
|
||||
_dl_x86_init_cpu_failure (cpu_features, "x86-64-v4");
|
||||
# endif /* ISA level 4 */
|
||||
# endif /* ISA level 3 */
|
||||
# endif /* ISA level 2 */
|
||||
# ifdef GCCMACRO__APX_F__
|
||||
if (!CPU_FEATURE_USABLE_P (cpu_features, APX_F))
|
||||
_dl_x86_init_cpu_failure (cpu_features, 5);
|
||||
_dl_x86_init_cpu_failure (cpu_features, "APX");
|
||||
# endif
|
||||
# endif /* IS_IN (rtld) */
|
||||
}
|
||||
|
26
sysdeps/x86/dl-x86_cpu_feature_diagnostics.c
Normal file
26
sysdeps/x86/dl-x86_cpu_feature_diagnostics.c
Normal file
@ -0,0 +1,26 @@
|
||||
/* CPU diagnostics probing. Generic x86 version.
|
||||
Copyright (C) 2024 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/>. */
|
||||
|
||||
#include <cpu-features
|
||||
|
||||
/* The generic version does not have any probes. */
|
||||
void
|
||||
_dl_x86_cpu_feature_diagnostics_run (const struct cpu_features *cpu_features,
|
||||
struct x86_cpu_feature_diagnostics *diag)
|
||||
{
|
||||
}
|
@ -987,6 +987,29 @@ extern const struct cpu_features *_dl_x86_get_cpu_features (void)
|
||||
|
||||
#define __get_cpu_features() _dl_x86_get_cpu_features()
|
||||
|
||||
/* Used to store diagnostic information for startup failure reporting.
|
||||
See _dl_x86_init_cpu_failure in sysdeps/x86/dl-diagnostics-cpu.c. */
|
||||
struct x86_cpu_feature_diagnostics
|
||||
{
|
||||
unsigned int count; /* Bits recorded. */
|
||||
unsigned long long int reported; /* From CPUID. */
|
||||
unsigned long long int probed; /* From execution probing. */
|
||||
};
|
||||
|
||||
/* Initialize *DIAG prior to the diagnostics run below. */
|
||||
static inline void
|
||||
_dl_x86_cpu_feature_diagnostics_init (struct x86_cpu_feature_diagnostics *diag)
|
||||
{
|
||||
diag->count = 0;
|
||||
diag->reported = 0;
|
||||
diag->probed = 0;
|
||||
}
|
||||
|
||||
/* Updated the diagnostics with CPUID and execution probing information. */
|
||||
void _dl_x86_cpu_feature_diagnostics_run (const struct cpu_features *,
|
||||
struct x86_cpu_feature_diagnostics *)
|
||||
attribute_hidden;
|
||||
|
||||
#if defined (_LIBC) && !IS_IN (nonlib)
|
||||
/* Unused for x86. */
|
||||
# define INIT_ARCH()
|
||||
|
Loading…
Reference in New Issue
Block a user