[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250815070227.19981-17-darwi@linutronix.de>
Date: Fri, 15 Aug 2025 09:02:09 +0200
From: "Ahmed S. Darwish" <darwi@...utronix.de>
To: Borislav Petkov <bp@...en8.de>,
Ingo Molnar <mingo@...hat.com>,
Dave Hansen <dave.hansen@...ux.intel.com>
Cc: Thomas Gleixner <tglx@...utronix.de>,
Andrew Cooper <andrew.cooper3@...rix.com>,
"H. Peter Anvin" <hpa@...or.com>,
David Woodhouse <dwmw2@...radead.org>,
Sean Christopherson <seanjc@...gle.com>,
Peter Zijlstra <peterz@...radead.org>,
Sohil Mehta <sohil.mehta@...el.com>,
John Ogness <john.ogness@...utronix.de>,
x86@...nel.org,
x86-cpuid@...ts.linux.dev,
LKML <linux-kernel@...r.kernel.org>,
"Ahmed S. Darwish" <darwi@...utronix.de>
Subject: [PATCH v4 16/34] x86/cpuid: Parse CPUID(0x2)
Add CPUID(0x2) support to the CPUID parser.
Query CPUID(0x2) only for Intel, Centaur, and Zhaoxin. Such vendor
information was extracted from the kernel's boot code, given that
kernel/cpu/cacheinfo.c :: init_intel_cacheinfo()
is called by
kernel/cpu/intel.c cpu_dev.c_x86_vendor = X86_VENDOR_INTEL
kernel/cpu/centaur.c cpu_dev.c_x86_vendor = X86_VENDOR_CENTAUR
kernel/cpu/zhaoxin.c cpu_dev.c_x86_vendor = X86_VENDOR_ZHAOXIN
At the CPUID leaf output table, keep CPUID(0x2) marked as invalidif the
whole leaf, or all of its output registers separately, were malformed.
Note, the cpuid_leaf_0x2() logic at <asm/cpuid/api.h> will be removed
once all CPUID(0x2) call sites are transformed to the new CPUID model.
References: fe78079ec07f ("x86/cpu: Introduce and use CPUID leaf 0x2 parsing helpers")
Signed-off-by: Ahmed S. Darwish <darwi@...utronix.de>
---
arch/x86/include/asm/cpuid/types.h | 1 +
arch/x86/kernel/cpu/cpuid_parser.c | 35 ++++++++++++++++++++++++++++++
arch/x86/kernel/cpu/cpuid_parser.h | 2 ++
3 files changed, 38 insertions(+)
diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index d0f0e6a8a457..7bbf0671cb95 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -215,6 +215,7 @@ struct cpuid_leaves {
/* leaf subleaf count */
CPUID_LEAF(0x0, 0, 1);
CPUID_LEAF(0x1, 0, 1);
+ CPUID_LEAF(0x2, 0, 1);
CPUID_LEAF(0x80000000, 0, 1);
};
diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c
index 3942ea2526f2..f3dffdd43779 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.c
+++ b/arch/x86/kernel/cpu/cpuid_parser.c
@@ -31,6 +31,41 @@ static void cpuid_read_generic(const struct cpuid_parse_entry *e, struct cpuid_r
cpuid_read_subleaf(e->leaf, e->subleaf + i, output->regs);
}
+static void cpuid_read_0x2(const struct cpuid_parse_entry *e, struct cpuid_read_output *output)
+{
+ union leaf_0x2_regs *regs = (union leaf_0x2_regs *)output->regs;
+ struct leaf_0x2_0 *l = (struct leaf_0x2_0 *)output->regs;
+ int invalid_regs = 0;
+
+ /*
+ * All Intel CPUs must report an iteration count of 1. For broken hardware,
+ * keep the leaf marked as invalid at the CPUID table.
+ */
+ cpuid_read_subleaf(e->leaf, e->subleaf, l);
+ if (l->iteration_count != 0x01)
+ return;
+
+ /*
+ * The most significant bit (MSB) of each CPUID(0x2) register must be clear.
+ * If a register is malformed, replace its 1-byte descriptors with NULL.
+ */
+ for (int i = 0; i < 4; i++) {
+ if (regs->reg[i].invalid) {
+ regs->regv[i] = 0;
+ invalid_regs++;
+ }
+ }
+
+ /*
+ * If all of the CPUID(0x2) output registers were malformed, keep the leaf
+ * marked as invalid at the CPUID table.
+ */
+ if (invalid_regs == 4)
+ return;
+
+ output->info->nr_entries = 1;
+}
+
static void cpuid_read_0x80000000(const struct cpuid_parse_entry *e, struct cpuid_read_output *output)
{
struct leaf_0x80000000_0 *l = (struct leaf_0x80000000_0 *)output->regs;
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index 1be5c323d5eb..0e3ac9a7700d 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -127,6 +127,7 @@ struct cpuid_parse_entry {
*/
#define CPUID_COMMON_PARSE_ENTRIES \
/* Leaf Subleaf Reader function */ \
+ CPUID_PARSE_ENTRY(0x2, 0, 0x2), \
CPUID_PARSE_ENTRY(0x80000000, 0, 0x80000000), \
/*
@@ -160,5 +161,6 @@ struct cpuid_vendor_entry {
#define CPUID_VENDOR_ENTRIES \
/* Leaf Vendor list */ \
+ CPUID_VENDOR_ENTRY(0x2, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR_ZHAOXIN),\
#endif /* _ARCH_X86_CPUID_PARSER_H */
--
2.50.1
Powered by blists - more mailing lists