[PATCH v1 24/26] x86/cpuid: scanner: Add CPUID table rescan support

"Ahmed S. Darwish" <[email protected]>
Newsgroups dev.linux.lists.x86-cpuid,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Add system CPUID table(s) rescan support through cpuid_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.

Follow-up commits will change the call sites in need of CPUID table
rescan one by one.

Signed-off-by: Ahmed S. Darwish <[email protected]>
---
 arch/x86/include/asm/cpuid/table_api.h |  1 +
 arch/x86/kernel/cpu/cpuid_scanner.c    | 52 +++++++++++++++++++++++---
 2 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/cpuid/table_api.h b/arch/x86/include/asm/cpuid/table_api.h
index 5c4788741dfb..af145fbed9f1 100644
--- a/arch/x86/include/asm/cpuid/table_api.h
+++ b/arch/x86/include/asm/cpuid/table_api.h
@@ -115,5 +115,6 @@
 	(struct cpuid_regs *)cpudata_cpuid_index(_cpuinfo, _leaf, _idx)
 
 void cpuid_scan_cpu(struct cpuinfo_x86 *c);
+void cpuid_rescan_cpu(struct cpuinfo_x86 *c);
 
 #endif /* _ASM_X86_CPUID_TABLE_API_H */
diff --git a/arch/x86/kernel/cpu/cpuid_scanner.c b/arch/x86/kernel/cpu/cpuid_scanner.c
index 664946ebe675..74d34c06d8de 100644
--- a/arch/x86/kernel/cpu/cpuid_scanner.c
+++ b/arch/x86/kernel/cpu/cpuid_scanner.c
@@ -149,6 +149,36 @@ static void cpuid_scan(const struct cpuid_scan_info *info)
 	}
 }
 
+/*
+ * @c: CPU capability structure associated with the current CPU
+ * @clear_cpuid_table: Zero out the CPUID table before populating it.
+ *
+ * The CPUID scanner code expects a zeroed table since the accessor macros at
+ * <cpuid/table_api.h> use the leaf's "nr_entries" field as a marker for its
+ * validity (otherwise NULL is returned.)
+ *
+ * At boot time, all CPUID tables within the CPU capability structure(s) are
+ * already 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_scan_cpu(struct cpuinfo_x86 *c, bool clear_cpuid_table)
+{
+	struct cpuid_table *table = &c->cpuid_table;
+
+	const struct cpuid_scan_info info = {
+		.cpuid_table	= table,
+		.entries	= cpuid_common_scan_entries,
+		.nr_entries	= cpuid_common_scan_entries_size,
+	};
+
+	if (clear_cpuid_table)
+		memset(table, 0, sizeof(*table));
+
+	cpuid_scan(&info);
+}
+
 /**
  * cpuid_scan_cpu() - Populate CPUID data for the current CPU
  * @c:		CPU capability structure associated with the current CPU
@@ -159,11 +189,21 @@ static void cpuid_scan(const struct cpuid_scan_info *info)
  */
 void cpuid_scan_cpu(struct cpuinfo_x86 *c)
 {
-	const struct cpuid_scan_info info = {
-		.cpuid_table	= &c->cpuid_table,
-		.entries	= cpuid_common_scan_entries,
-		.nr_entries	= cpuid_common_scan_entries_size,
-	};
+	__cpuid_scan_cpu(c, false);
+}
 
-	cpuid_scan(&info);
+/**
+ * cpuid_rescan_cpu() - Re-populate CPUID data for the current CPU
+ * @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 the CPUID instructions are run 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., Processor Serial Number (PSN) disable.
+ */
+void cpuid_rescan_cpu(struct cpuinfo_x86 *c)
+{
+	__cpuid_scan_cpu(c, true);
 }
-- 
2.49.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.