[PATCH v7 107/120] x86/cpuid: Parse leaves backing X86_FEATURE words

"Ahmed S. Darwish" <[email protected]> Thu, 28 May 2026 17:39:09 +0200
Newsgroups dev.linux.lists.x86-cpuid,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Add CPUID parser support for:

    CPUID(0x7)
    CPUID(0x7).1
    CPUID(0xd).1
    CPUID(0x80000001)
    CPUID(0x8000000a)
    CPUID(0x8000001f)
    CPUID(0x80000021)

where one or more of these leaves output registers back the X86_FEATURE
words at <asm/cpufeatures.h>.

Handle CPUID(0x7).1 via a custom reader.  Its availability depends on the
subleaf count reported by CPUID(0x7).0, so check that first.

Do not use a custom reader for CPUID(0xd).1.  Per the Intel SDM regarding
CPUID(0xd)'s subleaf availability: "sub-leafs 0 and 1 are always valid".

Note, this prepares for later changes that will route X86_FEATURE queries
from cpuinfo_x86::x86_capability[] to the system's CPUID tables.

Signed-off-by: Ahmed S. Darwish <[email protected]>
---
 arch/x86/include/asm/cpuid/types.h |  7 +++++++
 arch/x86/kernel/cpu/cpuid_parser.c | 13 +++++++++++++
 arch/x86/kernel/cpu/cpuid_parser.h |  7 +++++++
 3 files changed, 27 insertions(+)

diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index 7671f8d24014..1de66781cb5c 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -214,8 +214,11 @@ struct cpuid_leaves {
 	CPUID_LEAF_N (  0x4,		8  );
 	CPUID_LEAF   (	0x5,		0  );
 	CPUID_LEAF   (	0x6,		0  );
+	CPUID_LEAF   (  0x7,		0  );
+	CPUID_LEAF   (  0x7,		1  );
 	CPUID_LEAF   (	0x9,		0  );
 	CPUID_LEAF   (  0xa,		0  );
+	CPUID_LEAF   (  0xd,		1  );
 	CPUID_LEAF   (	0x12,		0  );
 	CPUID_LEAF   (	0x12,		1  );
 	CPUID_LEAF_N (	0x12,		8  );
@@ -229,6 +232,7 @@ struct cpuid_leaves {
 	CPUID_LEAF   (	0x23,		4  );
 	CPUID_LEAF   (	0x23,		5  );
 	CPUID_LEAF   (  0x80000000,	0  );
+	CPUID_LEAF   (  0x80000001,	0  );
 	CPUID_LEAF   (  0x80000002,	0  );
 	CPUID_LEAF   (  0x80000003,	0  );
 	CPUID_LEAF   (  0x80000004,	0  );
@@ -236,7 +240,10 @@ struct cpuid_leaves {
 	CPUID_LEAF   (  0x80000006,	0  );
 	CPUID_LEAF   (  0x80000007,	0  );
 	CPUID_LEAF   (  0x80000008,	0  );
+	CPUID_LEAF   (  0x8000000a,	0  );
 	CPUID_LEAF_N (  0x8000001d,	8  );
+	CPUID_LEAF   (  0x8000001f,	0  );
+	CPUID_LEAF   (  0x80000021,	0  );
 	CPUID_LEAF   (  0x80000022,	0  );
 	CPUID_LEAF   (  0x80860000,	0  );
 	CPUID_LEAF   (  0x80860001,	0  );
diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c
index 452b5b317e4d..1655e35b6310 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.c
+++ b/arch/x86/kernel/cpu/cpuid_parser.c
@@ -130,6 +130,19 @@ define_cpuid_0x23_subleaf_read_function(3);
 define_cpuid_0x23_subleaf_read_function(4);
 define_cpuid_0x23_subleaf_read_function(5);
 
+static void
+cpuid_read_0x7_1(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output)
+{
+	struct leaf_0x7_0 l7;
+
+	cpuid_read_subleaf(0x7, 0, &l7);
+	if (l7.leaf7_n_subleaves == 0)
+		return;
+
+	cpuid_read_subleaf(e->leaf, e->subleaf, output->regs);
+	output->info->nr_entries = 1;
+}
+
 /*
  * Shared read function for Intel CPUID(0x4) and AMD CPUID(0x8000001d), as both have
  * the same subleaf enumeration logic and register output format.
diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h
index 799714300bfb..123433a4b210 100644
--- a/arch/x86/kernel/cpu/cpuid_parser.h
+++ b/arch/x86/kernel/cpu/cpuid_parser.h
@@ -149,7 +149,10 @@ struct cpuid_parse_entry {
 	CPUID_PARSE_ENTRY   (	0x5,		0,		generic			),	\
 	CPUID_PARSE_ENTRY   (	0x6,		0,		generic			),	\
 	CPUID_PARSE_ENTRY   (	0x9,		0,		0x9			),	\
+	CPUID_PARSE_ENTRY   (	0x7,		0,		generic			),	\
+	CPUID_PARSE_ENTRY   (	0x7,		1,		0x7_1			),	\
 	CPUID_PARSE_ENTRY   (	0xa,		0,		generic			),	\
+	CPUID_PARSE_ENTRY   (	0xd,		1,		generic			),	\
 	CPUID_PARSE_ENTRY   (	0x12,		0,		0x12			),	\
 	CPUID_PARSE_ENTRY   (	0x12,		1,		0x12			),	\
 	CPUID_PARSE_ENTRY_N (	0x12,				sgx_epc_sections	),	\
@@ -163,6 +166,7 @@ struct cpuid_parse_entry {
 	CPUID_PARSE_ENTRY   (	0x23,		4,		0x23_4			),	\
 	CPUID_PARSE_ENTRY   (	0x23,		5,		0x23_5			),	\
 	CPUID_PARSE_ENTRY   (	0x80000000,	0,		0x80000000		),	\
+	CPUID_PARSE_ENTRY   (	0x80000001,	0,		generic			),	\
 	CPUID_PARSE_ENTRY   (	0x80000002,	0,		generic			),	\
 	CPUID_PARSE_ENTRY   (	0x80000003,	0,		generic			),	\
 	CPUID_PARSE_ENTRY   (	0x80000004,	0,		generic			),	\
@@ -170,7 +174,10 @@ struct cpuid_parse_entry {
 	CPUID_PARSE_ENTRY   (	0x80000006,	0,		generic			),	\
 	CPUID_PARSE_ENTRY   (	0x80000007,	0,		generic			),	\
 	CPUID_PARSE_ENTRY   (	0x80000008,	0,		generic			),	\
+	CPUID_PARSE_ENTRY   (	0x8000000a,	0,		generic			),	\
 	CPUID_PARSE_ENTRY_N (	0x8000001d,			deterministic_cache	),	\
+	CPUID_PARSE_ENTRY   (	0x8000001f,	0,		generic			),	\
+	CPUID_PARSE_ENTRY   (	0x80000021,	0,		generic			),	\
 	CPUID_PARSE_ENTRY   (	0x80000022,	0,		generic			),	\
 	CPUID_PARSE_ENTRY   (	0x80860000,	0,		0x80860000		),	\
 	CPUID_PARSE_ENTRY   (	0x80860001,	0,		generic			),	\
-- 
2.54.0