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 <darwi@linutronix.de>
---
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