Skip to content

Commit 71d5049

Browse files
joergroedelsuryasaimadhu
authored andcommitted
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 <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent f154f29 commit 71d5049

File tree

3 files changed

+29
-10
lines changed

3 files changed

+29
-10
lines changed

arch/x86/include/asm/realmode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ static inline void set_real_mode_mem(phys_addr_t mem)
8989
}
9090

9191
void reserve_real_mode(void);
92+
void load_trampoline_pgtable(void);
9293

9394
#endif /* __ASSEMBLY__ */
9495

arch/x86/kernel/reboot.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -113,17 +113,9 @@ void __noreturn machine_real_restart(unsigned int type)
113113
spin_unlock(&rtc_lock);
114114

115115
/*
116-
* Switch back to the initial page table.
116+
* Switch to the trampoline page table.
117117
*/
118-
#ifdef CONFIG_X86_32
119-
load_cr3(initial_page_table);
120-
#else
121-
write_cr3(real_mode_header->trampoline_pgd);
122-
123-
/* Exiting long mode will fail if CR4.PCIDE is set. */
124-
if (boot_cpu_has(X86_FEATURE_PCID))
125-
cr4_clear_bits(X86_CR4_PCIDE);
126-
#endif
118+
load_trampoline_pgtable();
127119

128120
/* Jump to the identity-mapped low memory code */
129121
#ifdef CONFIG_X86_32

arch/x86/realmode/init.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,32 @@ u32 *trampoline_cr4_features;
1717
/* Hold the pgd entry used on booting additional CPUs */
1818
pgd_t trampoline_pgd_entry;
1919

20+
void load_trampoline_pgtable(void)
21+
{
22+
#ifdef CONFIG_X86_32
23+
load_cr3(initial_page_table);
24+
#else
25+
/*
26+
* This function is called before exiting to real-mode and that will
27+
* fail with CR4.PCIDE still set.
28+
*/
29+
if (boot_cpu_has(X86_FEATURE_PCID))
30+
cr4_clear_bits(X86_CR4_PCIDE);
31+
32+
write_cr3(real_mode_header->trampoline_pgd);
33+
#endif
34+
35+
/*
36+
* The CR3 write above will not flush global TLB entries.
37+
* Stale, global entries from previous page tables may still be
38+
* present. Flush those stale entries.
39+
*
40+
* This ensures that memory accessed while running with
41+
* trampoline_pgd is *actually* mapped into trampoline_pgd.
42+
*/
43+
__flush_tlb_all();
44+
}
45+
2046
void __init reserve_real_mode(void)
2147
{
2248
phys_addr_t mem;

0 commit comments

Comments
 (0)