[PATCH v6 63/90] x86/cpuid: Parse CPUID(0x23)
"Ahmed S. Darwish" <[email protected]> Fri, 27 Mar 2026 03:16:17 +0100
| Newsgroups | dev.linux.lists.x86-cpuid,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Parse Intel PMU CPUID(0x23), and all its known subleaves. This allows converting their call sites to the CPUID API next. Note, for all subleaves, make sure that subleaf 0 declares their support beforehand. Signed-off-by: Ahmed S. Darwish <[email protected]> --- arch/x86/include/asm/cpuid/types.h | 6 +++++ arch/x86/kernel/cpu/cpuid_parser.c | 37 ++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/cpuid_parser.h | 7 ++++++ 3 files changed, 50 insertions(+) diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h index 128898d4434b..70ccd52a6848 100644 --- a/arch/x86/include/asm/cpuid/types.h +++ b/arch/x86/include/asm/cpuid/types.h @@ -215,6 +215,12 @@ struct cpuid_leaves { CPUID_LEAF ( 0xa, 0 ); CPUID_LEAF ( 0x1c, 0 ); CPUID_LEAF ( 0x16, 0 ); + CPUID_LEAF ( 0x23, 0 ); + CPUID_LEAF ( 0x23, 1 ); + CPUID_LEAF ( 0x23, 2 ); + CPUID_LEAF ( 0x23, 3 ); + CPUID_LEAF ( 0x23, 4 ); + CPUID_LEAF ( 0x23, 5 ); CPUID_LEAF ( 0x80000000, 0 ); CPUID_LEAF ( 0x80000002, 0 ); CPUID_LEAF ( 0x80000003, 0 ); diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c index 99507e99d8d9..de11fb4116f2 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.c +++ b/arch/x86/kernel/cpu/cpuid_parser.c @@ -105,6 +105,43 @@ cpuid_read_0x2(const struct cpuid_parse_entry *e, const struct cpuid_read_output */ define_cpuid_read_function(deterministic_cache, leaf_0x4_n, l, l->cache_type == 0); +static bool cpuid_0x23_has_subleaf(u32 subleaf) +{ + struct leaf_0x23_0 l; + + cpuid_read_subleaf(0x23, 0, &l); + + if (subleaf == 1) + return l.counters_subleaf; + if (subleaf == 2) + return l.acr_subleaf; + if (subleaf == 3) + return l.events_subleaf; + if (subleaf == 4) + return l.pebs_caps_subleaf; + if (subleaf == 5) + return l.pebs_subleaf; + + return false; +} + +#define define_cpuid_0x23_subleaf_read_function(subl) \ +static void \ +cpuid_read_0x23_##subl(const struct cpuid_parse_entry *e, const struct cpuid_read_output *output) \ +{ \ + if (!cpuid_0x23_has_subleaf(subl)) \ + return; \ + \ + cpuid_read_subleaf(e->leaf, e->subleaf, output->regs); \ + output->info->nr_entries = 1; \ +} + +define_cpuid_0x23_subleaf_read_function(1); +define_cpuid_0x23_subleaf_read_function(2); +define_cpuid_0x23_subleaf_read_function(3); +define_cpuid_0x23_subleaf_read_function(4); +define_cpuid_0x23_subleaf_read_function(5); + /* * Define an extended range CPUID read function * diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h index 8e147e7223e0..46f06792afb1 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.h +++ b/arch/x86/kernel/cpu/cpuid_parser.h @@ -149,6 +149,12 @@ struct cpuid_parse_entry { CPUID_PARSE_ENTRY ( 0xa, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x1c, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x16, 0, generic ), \ + CPUID_PARSE_ENTRY ( 0x23, 0, generic ), \ + CPUID_PARSE_ENTRY ( 0x23, 1, 0x23_1 ), \ + CPUID_PARSE_ENTRY ( 0x23, 2, 0x23_2 ), \ + CPUID_PARSE_ENTRY ( 0x23, 3, 0x23_3 ), \ + CPUID_PARSE_ENTRY ( 0x23, 4, 0x23_4 ), \ + CPUID_PARSE_ENTRY ( 0x23, 5, 0x23_5 ), \ CPUID_PARSE_ENTRY ( 0x80000000, 0, 0x80000000 ), \ CPUID_PARSE_ENTRY ( 0x80000002, 0, generic ), \ CPUID_PARSE_ENTRY ( 0x80000003, 0, generic ), \ @@ -203,6 +209,7 @@ struct cpuid_vendor_entry { CPUID_VENDOR_ENTRY(0xa, X86_VENDOR_INTEL, X86_VENDOR_CENTAUR, X86_VENDOR_ZHAOXIN),\ CPUID_VENDOR_ENTRY(0x16, X86_VENDOR_INTEL), \ CPUID_VENDOR_ENTRY(0x1c, X86_VENDOR_INTEL), \ + CPUID_VENDOR_ENTRY(0x23, X86_VENDOR_INTEL), \ CPUID_VENDOR_ENTRY(0x8000001d, X86_VENDOR_AMD, X86_VENDOR_HYGON), \ CPUID_VENDOR_ENTRY(0x80860000, X86_VENDOR_TRANSMETA), \ CPUID_VENDOR_ENTRY(0x80860001, X86_VENDOR_TRANSMETA), \ -- 2.53.0