Skip to content

Commit a97756c

Browse files
xinli-intelKAGA-KOKO
authored andcommitted
x86/fred: Enable FRED right after init_mem_mapping()
On 64-bit init_mem_mapping() relies on the minimal page fault handler provided by the early IDT mechanism. The real page fault handler is installed right afterwards into the IDT. This is problematic on CPUs which have X86_FEATURE_FRED set because the real page fault handler retrieves the faulting address from the FRED exception stack frame and not from CR2, but that does obviously not work when FRED is not yet enabled in the CPU. To prevent this enable FRED right after init_mem_mapping() without interrupt stacks. Those are enabled later in trap_init() after the CPU entry area is set up. [ tglx: Encapsulate the FRED details ] Fixes: 14619d9 ("x86/fred: FRED entry/exit and dispatch code") Reported-by: Hou Wenlong <[email protected]> Suggested-by: Thomas Gleixner <[email protected]> Signed-off-by: Xin Li (Intel) <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/all/[email protected]
1 parent 73270c1 commit a97756c

File tree

5 files changed

+23
-6
lines changed

5 files changed

+23
-6
lines changed

arch/x86/include/asm/processor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,8 @@ extern void switch_gdt_and_percpu_base(int);
582582
extern void load_direct_gdt(int);
583583
extern void load_fixmap_gdt(int);
584584
extern void cpu_init(void);
585-
extern void cpu_init_exception_handling(void);
585+
extern void cpu_init_exception_handling(bool boot_cpu);
586+
extern void cpu_init_replace_early_idt(void);
586587
extern void cr4_init(void);
587588

588589
extern void set_task_blockstep(struct task_struct *task, bool on);

arch/x86/kernel/cpu/common.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,7 +2176,7 @@ static inline void tss_setup_io_bitmap(struct tss_struct *tss)
21762176
* Setup everything needed to handle exceptions from the IDT, including the IST
21772177
* exceptions which use paranoid_entry().
21782178
*/
2179-
void cpu_init_exception_handling(void)
2179+
void cpu_init_exception_handling(bool boot_cpu)
21802180
{
21812181
struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw);
21822182
int cpu = raw_smp_processor_id();
@@ -2196,13 +2196,24 @@ void cpu_init_exception_handling(void)
21962196
setup_ghcb();
21972197

21982198
if (cpu_feature_enabled(X86_FEATURE_FRED)) {
2199-
cpu_init_fred_exceptions();
2199+
/* The boot CPU has enabled FRED during early boot */
2200+
if (!boot_cpu)
2201+
cpu_init_fred_exceptions();
2202+
22002203
cpu_init_fred_rsps();
22012204
} else {
22022205
load_current_idt();
22032206
}
22042207
}
22052208

2209+
void __init cpu_init_replace_early_idt(void)
2210+
{
2211+
if (cpu_feature_enabled(X86_FEATURE_FRED))
2212+
cpu_init_fred_exceptions();
2213+
else
2214+
idt_setup_early_pf();
2215+
}
2216+
22062217
/*
22072218
* cpu_init() initializes state that is per-CPU. Some data is already
22082219
* initialized (naturally) in the bootstrap process, such as the GDT. We

arch/x86/kernel/setup.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1039,7 +1039,12 @@ void __init setup_arch(char **cmdline_p)
10391039

10401040
init_mem_mapping();
10411041

1042-
idt_setup_early_pf();
1042+
/*
1043+
* init_mem_mapping() relies on the early IDT page fault handling.
1044+
* Now either enable FRED or install the real page fault handler
1045+
* for 64-bit in the IDT.
1046+
*/
1047+
cpu_init_replace_early_idt();
10431048

10441049
/*
10451050
* Update mmu_cr4_features (and, indirectly, trampoline_cr4_features)

arch/x86/kernel/smpboot.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ static void notrace start_secondary(void *unused)
246246
__flush_tlb_all();
247247
}
248248

249-
cpu_init_exception_handling();
249+
cpu_init_exception_handling(false);
250250

251251
/*
252252
* Load the microcode before reaching the AP alive synchronization

arch/x86/kernel/traps.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1411,7 +1411,7 @@ void __init trap_init(void)
14111411
sev_es_init_vc_handling();
14121412

14131413
/* Initialize TSS before setting up traps so ISTs work */
1414-
cpu_init_exception_handling();
1414+
cpu_init_exception_handling(true);
14151415

14161416
/* Setup traps as cpu_init() might #GP */
14171417
if (!cpu_feature_enabled(X86_FEATURE_FRED))

0 commit comments

Comments
 (0)