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

From: Ahmed S. Darwish

Date: Thu May 28 2026 - 12:18:44 EST


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 <darwi@xxxxxxxxxxxxx>
---
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