[PATCH v6 32/90] x86/cpuid: Introduce parsed CPUID(0x2) API

Ahmed S. Darwish posted 90 patches 6 days, 16 hours ago
[PATCH v6 32/90] x86/cpuid: Introduce parsed CPUID(0x2) API
Posted by Ahmed S. Darwish 6 days, 16 hours ago
Add a new iterator, for_each_parsed_cpuid_0x2_desc(), for retrieving parsed
CPUID(0x2) entries as 1-byte descriptors.

This new macro is aimed to replace for_each_cpuid_0x2_desc(), which
operates on directly queried CPUID data instead.

Assert that the passed "regs" are the same size as "union leaf_0x2_regs".
Use a size equivalence check, instead of a typeof() check, to give callers
the freedom to either pass a "struct cpuid_regs" pointer or a "struct
leaf_0x2_0" pointer; where both can returned by the parsed CPUID API at
<asm/cpuid/api.h>.  This size comparison matches what other kernel CPUID
APIs do; e.g. cpuid_read() and cpuid_read_subleaf() at <asm/cpuid/api.h>.

Put the size equivalence check inside a GNU statement expression, ({..})
so that it can be placed inside the macro's loop initialization.

Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
 arch/x86/include/asm/cpuid/api.h | 43 ++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h
index 3d5a0d4918cc..a55a28e9f0f6 100644
--- a/arch/x86/include/asm/cpuid/api.h
+++ b/arch/x86/include/asm/cpuid/api.h
@@ -528,6 +528,49 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void)
 	__cpuid_table_nr_filled_subleaves(&(_cpuinfo)->cpuid, _leaf, n);	\
 })
 
+/*
+ * Convenience leaf-specific functions (using parsed CPUID data):
+ */
+
+/*
+ * CPUID(0x2)
+ */
+
+/**
+ * for_each_parsed_cpuid_0x2_desc() - Iterator for parsed CPUID(0x2) descriptors
+ * @_regs:   Leaf 0x2 register output, as returned by cpuid_leaf_raw()
+ * @_ptr:  u8 pointer, for macro internal use only
+ * @_desc:  Pointer to parsed descriptor information at each iteration
+ *
+ * Loop over the 1-byte descriptors in the passed CPUID(0x2) output registers
+ * @_regs.  Provide the parsed information for each descriptor through @_desc.
+ *
+ * To handle cache-specific descriptors, switch on @_desc->c_type.  For TLB
+ * descriptors, switch on @_desc->t_type.
+ *
+ * Example usage for cache descriptors::
+ *
+ *	const struct leaf_0x2_table *desc;
+ *	const struct cpuid_regs *regs;
+ *	const u8 *ptr;
+ *
+ *	regs = cpuid_leaf_raw(c, 0x2);
+ *	if (!regs) {
+ *		// Handle error
+ *	}
+ *
+ *	for_each_parsed_cpuid_0x2_desc(regs, ptr, desc) {
+ *		switch (desc->c_type) {
+ *			...
+ *		}
+ *	}
+ */
+#define for_each_parsed_cpuid_0x2_desc(_regs, _ptr, _desc)				\
+	for (({ static_assert(sizeof(*_regs) == sizeof(union leaf_0x2_regs)); }),	\
+	     _ptr = &((const union leaf_0x2_regs *)(_regs))->desc[1];			\
+	     _ptr < &((const union leaf_0x2_regs *)(_regs))->desc[16] && (_desc = &cpuid_0x2_table[*_ptr]);\
+	     _ptr++)
+
 /*
  * CPUID parser exported APIs:
  */
-- 
2.53.0