[PATCH v2 25/27] x86/cpuid: Add CPUID parser table rescan support
"Ahmed S. Darwish" <[email protected]>
| Newsgroups | dev.linux.lists.x86-cpuid,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Add CPUID table(s) rescan support through cpuid_parser_rescan_cpu(). This will be needed for handling events that can change the system CPUID state; e.g. disabing the Processor Serial Number (PSN) or performing a late microcode update. Call sites in need of CPUID table rescan will be updated next. Signed-off-by: Ahmed S. Darwish <[email protected]> --- arch/x86/include/asm/cpuid/api.h | 1 + arch/x86/kernel/cpu/cpuid_parser.c | 42 +++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/cpuid/api.h b/arch/x86/include/asm/cpuid/api.h index 82d36d210930..235f1a05792a 100644 --- a/arch/x86/include/asm/cpuid/api.h +++ b/arch/x86/include/asm/cpuid/api.h @@ -519,5 +519,6 @@ static inline bool cpuid_amd_hygon_has_l3_cache(void) */ void cpuid_parser_scan_cpu(struct cpuinfo_x86 *c); +void cpuid_parser_rescan_cpu(struct cpuinfo_x86 *c); #endif /* _ASM_X86_CPUID_API_H */ diff --git a/arch/x86/kernel/cpu/cpuid_parser.c b/arch/x86/kernel/cpu/cpuid_parser.c index 1f3b4cd6b411..b7a44026ab1a 100644 --- a/arch/x86/kernel/cpu/cpuid_parser.c +++ b/arch/x86/kernel/cpu/cpuid_parser.c @@ -156,6 +156,30 @@ cpuid_fill_table(struct cpuid_table *t, const struct cpuid_parse_entry entries[] } } +/* + * __cpuid_parser_scan_cpu() - Populate current CPU's CPUID table + * @c: CPU capability structure associated with the current CPU + * @clear_cpuid_table: Zero-out the CPUID table residing within @c before populating it + * + * The CPUID parser code expects a zeroed-out CPUID table since the accessor macros at + * <cpuid/api.h> use the leaf's "nr_entries" field as a validity marker; otherwise NULL is + * returned. + * + * At boot, all CPUID tables within the CPU capability structure(s) are zeroed. For + * subsequent CPUID table scans, which are normally done after hardware state changes, the + * table might contain stale data that must be cleared beforehand; e.g., a CPUID leaf that + * is no longer available, but with a "nr_entries" value bigger than zero. + */ +static void __cpuid_parser_scan_cpu(struct cpuinfo_x86 *c, bool clear_cpuid_table) +{ + struct cpuid_table *table = &c->cpuid; + + if (clear_cpuid_table) + memset(table, 0, sizeof(*table)); + + cpuid_fill_table(table, cpuid_common_parse_entries, cpuid_common_parse_entries_size); +} + /** * cpuid_parser_scan_cpu() - Populate current CPU's CPUID table * @c: CPU capability structure associated with the current CPU @@ -165,5 +189,21 @@ cpuid_fill_table(struct cpuid_table *t, const struct cpuid_parse_entry entries[] */ void cpuid_parser_scan_cpu(struct cpuinfo_x86 *c) { - cpuid_fill_table(&c->cpuid, cpuid_common_parse_entries, cpuid_common_parse_entries_size); + __cpuid_parser_scan_cpu(c, false); +} + +/** + * cpuid_parser_rescan_cpu() - Re-populate current CPU's CPUID table + * @c: CPU capability structure associated with the current CPU + * + * Zero-out the CPUID table embedded within @c, then re-populate it using a fresh CPUID scan. + * Since all CPUID instructions are invoked locally, this function must be called on the CPU + * associated with @c. + * + * A CPUID table rescan is usually required after system changes that can affect CPUID state; + * e.g., disabing the Processor Serial Number (PSN) or performing a late microcode update. + */ +void cpuid_parser_rescan_cpu(struct cpuinfo_x86 *c) +{ + __cpuid_parser_scan_cpu(c, true); } -- 2.49.0