[PATCH v1 18/26] x86/cpuid: Scan deterministic cache params CPUID leaves
"Ahmed S. Darwish" <[email protected]>
| Newsgroups | dev.linux.lists.x86-cpuid,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> --- 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