mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 11:33:28 +02:00
tools/x86/kcpuid: Use <cpuid.h> intrinsics
Use the __cpuid_count() intrinsic, provided by GCC and LLVM, instead of rolling a manual version. Both of the kernel's minimum required GCC version (5.1) and LLVM version (13.0.1) supports it, and it is heavily used across standard Linux user-space tooling. This also makes the CPUID call sites more readable. Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de> Signed-off-by: Ingo Molnar <mingo@kernel.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Link: https://lore.kernel.org/r/20250324142042.29010-11-darwi@linutronix.de
This commit is contained in:
parent
0a8f12ccd2
commit
c479a84488
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <cpuid.h>
|
||||
#include <err.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
|
|
@ -86,16 +87,16 @@ static u32 user_index = 0xFFFFFFFF;
|
|||
static u32 user_sub = 0xFFFFFFFF;
|
||||
static int flines;
|
||||
|
||||
static inline void cpuid(u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
|
||||
{
|
||||
/* ecx is often an input as well as an output. */
|
||||
asm volatile("cpuid"
|
||||
: "=a" (*eax),
|
||||
"=b" (*ebx),
|
||||
"=c" (*ecx),
|
||||
"=d" (*edx)
|
||||
: "0" (*eax), "2" (*ecx));
|
||||
}
|
||||
/*
|
||||
* Force using <cpuid.h> __cpuid_count() instead of __cpuid(). The
|
||||
* latter leaves ECX uninitialized, which can break CPUID queries.
|
||||
*/
|
||||
|
||||
#define cpuid(leaf, a, b, c, d) \
|
||||
__cpuid_count(leaf, 0, a, b, c, d)
|
||||
|
||||
#define cpuid_count(leaf, subleaf, a, b, c, d) \
|
||||
__cpuid_count(leaf, subleaf, a, b, c, d)
|
||||
|
||||
static inline bool has_subleafs(u32 f)
|
||||
{
|
||||
|
|
@ -195,12 +196,7 @@ struct cpuid_range *setup_cpuid_range(u32 input_eax)
|
|||
u32 max_func, idx_func;
|
||||
u32 eax, ebx, ecx, edx;
|
||||
|
||||
eax = input_eax;
|
||||
ebx = ecx = edx = 0;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
|
||||
max_func = eax;
|
||||
idx_func = (max_func & 0xffff) + 1;
|
||||
cpuid(input_eax, max_func, ebx, ecx, edx);
|
||||
|
||||
range = malloc(sizeof(struct cpuid_range));
|
||||
if (!range)
|
||||
|
|
@ -211,6 +207,7 @@ struct cpuid_range *setup_cpuid_range(u32 input_eax)
|
|||
else
|
||||
range->is_ext = false;
|
||||
|
||||
idx_func = (max_func & 0xffff) + 1;
|
||||
range->funcs = malloc(sizeof(struct cpuid_func) * idx_func);
|
||||
if (!range->funcs)
|
||||
err(EXIT_FAILURE, NULL);
|
||||
|
|
@ -222,9 +219,7 @@ struct cpuid_range *setup_cpuid_range(u32 input_eax)
|
|||
u32 max_subleaf = MAX_SUBLEAF_NUM;
|
||||
bool allzero;
|
||||
|
||||
eax = f;
|
||||
ecx = 0;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
cpuid(f, eax, ebx, ecx, edx);
|
||||
|
||||
allzero = cpuid_store(range, f, 0, eax, ebx, ecx, edx);
|
||||
if (allzero)
|
||||
|
|
@ -251,9 +246,7 @@ struct cpuid_range *setup_cpuid_range(u32 input_eax)
|
|||
max_subleaf = 5;
|
||||
|
||||
for (u32 subleaf = 1; subleaf < max_subleaf; subleaf++) {
|
||||
eax = f;
|
||||
ecx = subleaf;
|
||||
cpuid(&eax, &ebx, &ecx, &edx);
|
||||
cpuid_count(f, subleaf, eax, ebx, ecx, edx);
|
||||
|
||||
allzero = cpuid_store(range, f, subleaf, eax, ebx, ecx, edx);
|
||||
if (allzero)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user