Skip to content

Commit 4a692ae

Browse files
committed
Merge tag 'x86_mm_for_v5.17_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 mm updates from Borislav Petkov: - Flush *all* mappings from the TLB after switching to the trampoline pagetable to prevent any stale entries' presence - Flush global mappings from the TLB, in addition to the CR3-write, after switching off of the trampoline_pgd during boot to clear the identity mappings - Prevent instrumentation issues resulting from the above changes * tag 'x86_mm_for_v5.17_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/mm: Prevent early boot triple-faults with instrumentation x86/mm: Include spinlock_t definition in pgtable. x86/mm: Flush global TLB when switching to trampoline page-table x86/mm/64: Flush global TLB on boot and AP bringup x86/realmode: Add comment for Global bit usage in trampoline_pgd x86/mm: Add missing <asm/cpufeatures.h> dependency to <asm/page_64.h>
2 parents bfed6ef + b64dfcd commit 4a692ae

File tree

11 files changed

+76
-18
lines changed

11 files changed

+76
-18
lines changed

arch/x86/include/asm/page_64.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <asm/page_64_types.h>
66

77
#ifndef __ASSEMBLY__
8+
#include <asm/cpufeatures.h>
89
#include <asm/alternative.h>
910

1011
/* duplicated to the one in bootmem.h */

arch/x86/include/asm/pgtable.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#define pgprot_decrypted(prot) __pgprot(__sme_clr(pgprot_val(prot)))
2323

2424
#ifndef __ASSEMBLY__
25+
#include <linux/spinlock.h>
2526
#include <asm/x86_init.h>
2627
#include <asm/pkru.h>
2728
#include <asm/fpu/api.h>

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/include/asm/tlbflush.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,4 +261,9 @@ extern void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch);
261261

262262
#endif /* !MODULE */
263263

264+
static inline void __native_tlb_flush_global(unsigned long cr4)
265+
{
266+
native_write_cr4(cr4 ^ X86_CR4_PGE);
267+
native_write_cr4(cr4);
268+
}
264269
#endif /* _ASM_X86_TLBFLUSH_H */

arch/x86/kernel/cpu/common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ void native_write_cr0(unsigned long val)
384384
}
385385
EXPORT_SYMBOL(native_write_cr0);
386386

387-
void native_write_cr4(unsigned long val)
387+
void __no_profile native_write_cr4(unsigned long val)
388388
{
389389
unsigned long bits_changed = 0;
390390

arch/x86/kernel/head64.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,10 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
487487

488488
clear_bss();
489489

490+
/*
491+
* This needs to happen *before* kasan_early_init() because latter maps stuff
492+
* into that page.
493+
*/
490494
clear_page(init_top_pgt);
491495

492496
/*
@@ -498,6 +502,16 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
498502

499503
kasan_early_init();
500504

505+
/*
506+
* Flush global TLB entries which could be left over from the trampoline page
507+
* table.
508+
*
509+
* This needs to happen *after* kasan_early_init() as KASAN-enabled .configs
510+
* instrument native_write_cr4() so KASAN must be initialized for that
511+
* instrumentation to work.
512+
*/
513+
__native_tlb_flush_global(this_cpu_read(cpu_tlbstate.cr4));
514+
501515
idt_setup_early_handler();
502516

503517
copy_bootdata(__va(real_mode_data));

arch/x86/kernel/head_64.S

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,26 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
166166
call sev_verify_cbit
167167
popq %rsi
168168

169-
/* Switch to new page-table */
169+
/*
170+
* Switch to new page-table
171+
*
172+
* For the boot CPU this switches to early_top_pgt which still has the
173+
* indentity mappings present. The secondary CPUs will switch to the
174+
* init_top_pgt here, away from the trampoline_pgd and unmap the
175+
* indentity mapped ranges.
176+
*/
170177
movq %rax, %cr3
171178

179+
/*
180+
* Do a global TLB flush after the CR3 switch to make sure the TLB
181+
* entries from the identity mapping are flushed.
182+
*/
183+
movq %cr4, %rcx
184+
movq %rcx, %rax
185+
xorq $X86_CR4_PGE, %rcx
186+
movq %rcx, %cr4
187+
movq %rax, %cr4
188+
172189
/* Ensure I am executing from virtual addresses */
173190
movq $1f, %rax
174191
ANNOTATE_RETPOLINE_SAFE

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/mm/init.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,11 @@ static void __init memory_map_bottom_up(unsigned long map_start,
714714
static void __init init_trampoline(void)
715715
{
716716
#ifdef CONFIG_X86_64
717+
/*
718+
* The code below will alias kernel page-tables in the user-range of the
719+
* address space, including the Global bit. So global TLB entries will
720+
* be created when using the trampoline page-table.
721+
*/
717722
if (!kaslr_memory_enabled())
718723
trampoline_pgd_entry = init_top_pgt[pgd_index(__PAGE_OFFSET)];
719724
else

arch/x86/mm/tlb.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,7 +1148,7 @@ void flush_tlb_one_user(unsigned long addr)
11481148
*/
11491149
STATIC_NOPV void native_flush_tlb_global(void)
11501150
{
1151-
unsigned long cr4, flags;
1151+
unsigned long flags;
11521152

11531153
if (static_cpu_has(X86_FEATURE_INVPCID)) {
11541154
/*
@@ -1168,11 +1168,7 @@ STATIC_NOPV void native_flush_tlb_global(void)
11681168
*/
11691169
raw_local_irq_save(flags);
11701170

1171-
cr4 = this_cpu_read(cpu_tlbstate.cr4);
1172-
/* toggle PGE */
1173-
native_write_cr4(cr4 ^ X86_CR4_PGE);
1174-
/* write old PGE again and flush TLBs */
1175-
native_write_cr4(cr4);
1171+
__native_tlb_flush_global(this_cpu_read(cpu_tlbstate.cr4));
11761172

11771173
raw_local_irq_restore(flags);
11781174
}

0 commit comments

Comments
 (0)