[PATCH v1 18/26] x86/cpuid: Scan deterministic cache params CPUID leaves

Ahmed S. Darwish posted 26 patches 7 months, 2 weeks ago
[PATCH v1 18/26] x86/cpuid: Scan deterministic cache params CPUID leaves
Posted by Ahmed S. Darwish 7 months, 2 weeks ago
Add CPUID scanner logic for Intel CPUID(0x4) and AMD CPUID(0x8000001d).
Define a single CPUID "deterministic cache" read function for both leaves
as both have the same subleaf cache enumeration logic.

Introduce __define_cpuid_read_function() to avoid duplication between
cpuid_read_generic(), the CPUID scanner default read function, and the
new cpuid_read_deterministic_cache().

Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
 arch/x86/include/asm/cpuid/types.h  |  2 ++
 arch/x86/kernel/cpu/cpuid_scanner.c | 40 ++++++++++++++++++++++++-----
 arch/x86/kernel/cpu/cpuid_scanner.h |  4 ++-
 3 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/cpuid/types.h b/arch/x86/include/asm/cpuid/types.h
index b8e525725def..2ac3d05c3fe4 100644
--- a/arch/x86/include/asm/cpuid/types.h
+++ b/arch/x86/include/asm/cpuid/types.h
@@ -181,7 +181,9 @@ struct cpuid_leaves {
 	CPUID_LEAF(0x0,		0,		1);
 	CPUID_LEAF(0x1,		0,		1);
 	CPUID_LEAF(0x2,		0,		1);
+	CPUID_LEAF(0x4,		0,		8);
 	CPUID_LEAF(0x80000000,	0,		1);
+	CPUID_LEAF(0x8000001d,	0,		8);
 };
 
 /**
diff --git a/arch/x86/kernel/cpu/cpuid_scanner.c b/arch/x86/kernel/cpu/cpuid_scanner.c
index aaee1ede0472..664946ebe675 100644
--- a/arch/x86/kernel/cpu/cpuid_scanner.c
+++ b/arch/x86/kernel/cpu/cpuid_scanner.c
@@ -10,15 +10,43 @@
 
 #include "cpuid_scanner.h"
 
+/**
+ * __define_cpuid_read_function() - Generate a CPUID scanner read function
+ * @_suffix:	Suffix for the generated function name (full name: cpuid_read_@_suffix())
+ * @_leaf_t:	Type to cast the CPUID query output storage pointer
+ * @_leaf:	Name of the CPUID query storage pointer
+ * @_break_c:	Condition to break the CPUID scanning loop, which may reference @_leaf,
+ *		and where @_leaf stores each iteration's CPUID query output.
+ *
+ * Define a CPUID scanner read function according to the requirements stated
+ * at &struct cpuid_scan_entry->read().
+ */
+#define __define_cpuid_read_function(_suffix, _leaf_t, _leaf, _break_c)				\
+static void											\
+cpuid_read_##_suffix(const struct cpuid_scan_entry *e, struct cpuid_read_output *output)	\
+{												\
+	struct _leaf_t *_leaf = (struct _leaf_t *)output->leaf;					\
+												\
+	static_assert(sizeof(*_leaf) == 16);							\
+												\
+	output->info->nr_entries = 0;								\
+	for (int i = 0; i < e->maxcnt; i++, _leaf++, output->info->nr_entries++) {		\
+		cpuid_subleaf(e->leaf, e->subleaf + i, _leaf);					\
+		if (_break_c)									\
+			break;									\
+	}											\
+}
+
 /*
  * Default CPUID scanner read function
  */
-static void cpuid_read_generic(const struct cpuid_scan_entry *e, struct cpuid_read_output *output)
-{
-	output->info->nr_entries = 0;
-	for (int i = 0; i < e->maxcnt; i++, output->leaf++, output->info->nr_entries++)
-		cpuid_subleaf(e->leaf, e->subleaf + i, output->leaf);
-}
+__define_cpuid_read_function(generic, cpuid_regs, ignored, false);
+
+/*
+ * Shared read function for Intel CPUID leaf 0x4 and AMD CPUID leaf 0x8000001d,
+ * as both have the same subleaf enumeration logic and registers output format.
+ */
+__define_cpuid_read_function(deterministic_cache, leaf_0x4_0, leaf, leaf->cache_type == 0);
 
 static void cpuid_read_0x2(const struct cpuid_scan_entry *e, struct cpuid_read_output *output)
 {
diff --git a/arch/x86/kernel/cpu/cpuid_scanner.h b/arch/x86/kernel/cpu/cpuid_scanner.h
index dc1d518c9768..a09110a4c72c 100644
--- a/arch/x86/kernel/cpu/cpuid_scanner.h
+++ b/arch/x86/kernel/cpu/cpuid_scanner.h
@@ -93,7 +93,9 @@ struct cpuid_scan_entry {
 	SCAN_ENTRY(0x0,		0,		generic),			\
 	SCAN_ENTRY(0x1,		0,		generic),			\
 	SCAN_ENTRY(0x2,		0,		0x2),				\
-	SCAN_ENTRY(0x80000000,  0,              0x80000000),
+	SCAN_ENTRY(0x4,		0,		deterministic_cache),		\
+	SCAN_ENTRY(0x80000000,  0,              0x80000000),			\
+	SCAN_ENTRY(0x8000001d,  0,              deterministic_cache),		\
 
 /**
  * struct cpuid_scan_info - Parameters for generic CPUID scan logic
-- 
2.49.0