[PATCH v2 18/27] x86/cpuid: Parse deterministic cache parameters CPUID leaves
"Ahmed S. Darwish" <[email protected]>
| Newsgroups | dev.linux.lists.x86-cpuid,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Add CPUID parser logic for Intel CPUID(0x4) and AMD CPUID(0x8000001d). Define a single cpuid_read_deterministic_cache() parsing function for both leaves, as both have the same subleaf cache enumeration logic. Introduce __define_cpuid_read_function() macro to avoid code duplication between cpuid_read_generic(), the CPUID parser's default read function, and the new cpuid_read_deterministic_cache() one. Signed-off-by: Ahmed S. Darwish <[email protected]> --- arch/x86/include/asm/cpuid/types.h | 2 ++ arch/x86/kernel/cpu/cpuid_parser.c | 40 +++++++++++++++++++++++++----- arch/x86/kernel/cpu/cpuid_parser.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 7bbf0671cb95..89c399629e58 100644 --- a/arch/x86/include/asm/cpuid/types.h +++ b/arch/x86/include/asm/cpuid/types.h @@ -216,7 +216,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_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c index 4b960b23cab4..1f3b4cd6b411 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.c +++ b/arch/x86/kernel/cpu/cpuid_parser.c @@ -14,15 +14,43 @@ #include "cpuid_parser.h" +/** + * __define_cpuid_read_function() - Generate a CPUID parser 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 parsing loop, which may reference @_leaf, and + * where @_leaf stores each iteration's CPUID query output. + * + * Define a CPUID parser read function according to the requirements stated at + * &struct cpuid_parse_entry->read(). + */ +#define __define_cpuid_read_function(_suffix, _leaf_t, _leaf, _break_c) \ +static void \ +cpuid_read_##_suffix(const struct cpuid_parse_entry *e, struct cpuid_read_output *output) \ +{ \ + struct _leaf_t *_leaf = (struct _leaf_t *)output->regs; \ + \ + static_assert(sizeof(*_leaf) == 16); \ + \ + output->info->nr_entries = 0; \ + for (int i = 0; i < e->maxcnt; i++, _leaf++, output->info->nr_entries++) { \ + cpuid_read_subleaf(e->leaf, e->subleaf + i, _leaf); \ + if (_break_c) \ + break; \ + } \ +} + /* * Default CPUID parser read function */ -static void cpuid_read_generic(const struct cpuid_parse_entry *e, struct cpuid_read_output *output) -{ - output->info->nr_entries = 0; - for (int i = 0; i < e->maxcnt; i++, output->regs++, output->info->nr_entries++) - cpuid_read_subleaf(e->leaf, e->subleaf + i, output->regs); -} +__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_parse_entry *e, struct cpuid_read_output *output) { diff --git a/arch/x86/kernel/cpu/cpuid_parser.h b/arch/x86/kernel/cpu/cpuid_parser.h index 3178e760e2b3..c79c77547a1d 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.h +++ b/arch/x86/kernel/cpu/cpuid_parser.h @@ -97,7 +97,9 @@ struct cpuid_parse_entry { CPUID_PARSE_ENTRY(0x0, 0, generic), \ CPUID_PARSE_ENTRY(0x1, 0, generic), \ CPUID_PARSE_ENTRY(0x2, 0, 0x2), \ - CPUID_PARSE_ENTRY(0x80000000, 0, 0x80000000), + CPUID_PARSE_ENTRY(0x4, 0, deterministic_cache), \ + CPUID_PARSE_ENTRY(0x80000000, 0, 0x80000000), \ + CPUID_PARSE_ENTRY(0x8000001d, 0, deterministic_cache), extern const struct cpuid_parse_entry cpuid_common_parse_entries[]; extern const int cpuid_common_parse_entries_size; -- 2.49.0