summaryrefslogtreecommitdiffstats
path: root/arch/x86/realmode
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2021-12-02 16:32:25 +0100
committerBorislav Petkov <bp@suse.de>2021-12-06 09:54:10 +0100
commit71d5049b053876afbde6c3273250b76935494ab2 (patch)
tree262b29644cef0c1009776942ea327eff8dbb64e9 /arch/x86/realmode
parentf154f290855b070cc94dd44ad253c0ef8a9337bb (diff)
downloadlinux-71d5049b053876afbde6c3273250b76935494ab2.tar.bz2
x86/mm: Flush global TLB when switching to trampoline page-table
Move the switching code into a function so that it can be re-used and add a global TLB flush. This makes sure that usage of memory which is not mapped in the trampoline page-table is reliably caught. Also move the clearing of CR4.PCIDE before the CR3 switch because the cr4_clear_bits() function will access data not mapped into the trampoline page-table. Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Borislav Petkov <bp@suse.de> Link: https://lore.kernel.org/r/20211202153226.22946-4-joro@8bytes.org
Diffstat (limited to 'arch/x86/realmode')
-rw-r--r--arch/x86/realmode/init.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index 4a3da7592b99..6d98609387ba 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -17,6 +17,32 @@ u32 *trampoline_cr4_features;
/* Hold the pgd entry used on booting additional CPUs */
pgd_t trampoline_pgd_entry;
+void load_trampoline_pgtable(void)
+{
+#ifdef CONFIG_X86_32
+ load_cr3(initial_page_table);
+#else
+ /*
+ * This function is called before exiting to real-mode and that will
+ * fail with CR4.PCIDE still set.
+ */
+ if (boot_cpu_has(X86_FEATURE_PCID))
+ cr4_clear_bits(X86_CR4_PCIDE);
+
+ write_cr3(real_mode_header->trampoline_pgd);
+#endif
+
+ /*
+ * The CR3 write above will not flush global TLB entries.
+ * Stale, global entries from previous page tables may still be
+ * present. Flush those stale entries.
+ *
+ * This ensures that memory accessed while running with
+ * trampoline_pgd is *actually* mapped into trampoline_pgd.
+ */
+ __flush_tlb_all();
+}
+
void __init reserve_real_mode(void)
{
phys_addr_t mem;