]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
x86/fred: Enable FRED right after init_mem_mapping()
authorXin Li (Intel) <xin@zytor.com>
Tue, 9 Jul 2024 15:40:48 +0000 (08:40 -0700)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 13 Aug 2024 19:59:21 +0000 (21:59 +0200)
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: 14619d912b65 ("x86/fred: FRED entry/exit and dispatch code")
Reported-by: Hou Wenlong <houwenlong.hwl@antgroup.com>
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Xin Li (Intel) <xin@zytor.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20240709154048.3543361-4-xin@zytor.com
arch/x86/include/asm/processor.h
arch/x86/kernel/cpu/common.c
arch/x86/kernel/setup.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/traps.c

index a75a07f4931fdb5409df7ea883ea429f7da8f446..399f7d1c4c61f0b02ec2a661e55903580d8ae1e0 100644 (file)
@@ -582,7 +582,8 @@ extern void switch_gdt_and_percpu_base(int);
 extern void load_direct_gdt(int);
 extern void load_fixmap_gdt(int);
 extern void cpu_init(void);
-extern void cpu_init_exception_handling(void);
+extern void cpu_init_exception_handling(bool boot_cpu);
+extern void cpu_init_replace_early_idt(void);
 extern void cr4_init(void);
 
 extern void set_task_blockstep(struct task_struct *task, bool on);
index 6de12b3c1b049d8646b26e3d3a119f425c18b957..a4735d9b5a1d876c6023f231db5d4281486afdac 100644 (file)
@@ -2176,7 +2176,7 @@ static inline void tss_setup_io_bitmap(struct tss_struct *tss)
  * Setup everything needed to handle exceptions from the IDT, including the IST
  * exceptions which use paranoid_entry().
  */
-void cpu_init_exception_handling(void)
+void cpu_init_exception_handling(bool boot_cpu)
 {
        struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw);
        int cpu = raw_smp_processor_id();
@@ -2196,13 +2196,24 @@ void cpu_init_exception_handling(void)
        setup_ghcb();
 
        if (cpu_feature_enabled(X86_FEATURE_FRED)) {
-               cpu_init_fred_exceptions();
+               /* The boot CPU has enabled FRED during early boot */
+               if (!boot_cpu)
+                       cpu_init_fred_exceptions();
+
                cpu_init_fred_rsps();
        } else {
                load_current_idt();
        }
 }
 
+void __init cpu_init_replace_early_idt(void)
+{
+       if (cpu_feature_enabled(X86_FEATURE_FRED))
+               cpu_init_fred_exceptions();
+       else
+               idt_setup_early_pf();
+}
+
 /*
  * cpu_init() initializes state that is per-CPU. Some data is already
  * initialized (naturally) in the bootstrap process, such as the GDT.  We
index 6129dc2ba784cbdafb445e43479ca708f252f52a..f1fea506e20f417bdb6d27c98f7f9919c87533b2 100644 (file)
@@ -1039,7 +1039,12 @@ void __init setup_arch(char **cmdline_p)
 
        init_mem_mapping();
 
-       idt_setup_early_pf();
+       /*
+        * init_mem_mapping() relies on the early IDT page fault handling.
+        * Now either enable FRED or install the real page fault handler
+        * for 64-bit in the IDT.
+        */
+       cpu_init_replace_early_idt();
 
        /*
         * Update mmu_cr4_features (and, indirectly, trampoline_cr4_features)
index 0c35207320cb4f6ded65d8ef64dbb24c63c1c84b..dc4fff8fccce2112b70b9a3d6596a28f3e37a406 100644 (file)
@@ -246,7 +246,7 @@ static void notrace start_secondary(void *unused)
                __flush_tlb_all();
        }
 
-       cpu_init_exception_handling();
+       cpu_init_exception_handling(false);
 
        /*
         * Load the microcode before reaching the AP alive synchronization
index 6afb41e6cbbb45da1be2c8af2273251e629f44a0..197d5888b0e25e87da5c5ac91f9ec85636d14e27 100644 (file)
@@ -1411,7 +1411,7 @@ void __init trap_init(void)
        sev_es_init_vc_handling();
 
        /* Initialize TSS before setting up traps so ISTs work */
-       cpu_init_exception_handling();
+       cpu_init_exception_handling(true);
 
        /* Setup traps as cpu_init() might #GP */
        if (!cpu_feature_enabled(X86_FEATURE_FRED))