powerpc/pseries: Fix scv instruction crash with kexec
authorNicholas Piggin <npiggin@gmail.com>
Tue, 25 Jun 2024 13:40:47 +0000 (23:40 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 28 Jun 2024 12:05:44 +0000 (22:05 +1000)
kexec on pseries disables AIL (reloc_on_exc), required for scv
instruction support, before other CPUs have been shut down. This means
they can execute scv instructions after AIL is disabled, which causes an
interrupt at an unexpected entry location that crashes the kernel.

Change the kexec sequence to disable AIL after other CPUs have been
brought down.

As a refresher, the real-mode scv interrupt vector is 0x17000, and the
fixed-location head code probably couldn't easily deal with implementing
such high addresses so it was just decided not to support that interrupt
at all.

Fixes: 7fa95f9adaee ("powerpc/64s: system call support for scv/rfscv instructions")
Cc: stable@vger.kernel.org # v5.9+
Reported-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Closes: https://lore.kernel.org/3b4b2943-49ad-4619-b195-bc416f1d1409@linux.ibm.com
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Tested-by: Gautam Menghani <gautam@linux.ibm.com>
Tested-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Link: https://msgid.link/20240625134047.298759-1-npiggin@gmail.com
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/kexec/core_64.c
arch/powerpc/platforms/pseries/kexec.c
arch/powerpc/platforms/pseries/pseries.h
arch/powerpc/platforms/pseries/setup.c

index 85050be08a23da88fc704effc0b22579ca00507f..72b12bc10f90b6d974f82434af2abe8eb29847ae 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/paca.h>
 #include <asm/mmu.h>
 #include <asm/sections.h>      /* _end */
+#include <asm/setup.h>
 #include <asm/smp.h>
 #include <asm/hw_breakpoint.h>
 #include <asm/svm.h>
@@ -317,6 +318,16 @@ void default_machine_kexec(struct kimage *image)
        if (!kdump_in_progress())
                kexec_prepare_cpus();
 
+#ifdef CONFIG_PPC_PSERIES
+       /*
+        * This must be done after other CPUs have shut down, otherwise they
+        * could execute the 'scv' instruction, which is not supported with
+        * reloc disabled (see configure_exceptions()).
+        */
+       if (firmware_has_feature(FW_FEATURE_SET_MODE))
+               pseries_disable_reloc_on_exc();
+#endif
+
        printk("kexec: Starting switchover sequence.\n");
 
        /* switch to a staticly allocated stack.  Based on irq stack code.
index 096d09ed89f673378626d6441e9fe94f45a99ba7..431be156ca9bb3138065ad6981607725d54efb7d 100644 (file)
@@ -61,11 +61,3 @@ void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
        } else
                xics_kexec_teardown_cpu(secondary);
 }
-
-void pseries_machine_kexec(struct kimage *image)
-{
-       if (firmware_has_feature(FW_FEATURE_SET_MODE))
-               pseries_disable_reloc_on_exc();
-
-       default_machine_kexec(image);
-}
index bba4ad192b0fe4edfe17dc334237b8930f56ec79..3968a6970fa81d6abbd39f89590baca68766af35 100644 (file)
@@ -38,7 +38,6 @@ static inline void smp_init_pseries(void) { }
 #endif
 
 extern void pseries_kexec_cpu_down(int crash_shutdown, int secondary);
-void pseries_machine_kexec(struct kimage *image);
 
 extern void pSeries_final_fixup(void);
 
index cba40d9d128488780a71e14a6493474c9bbf3fd1..b10a253252387096c954ba6ebb33a72a3b115310 100644 (file)
@@ -1159,7 +1159,6 @@ define_machine(pseries) {
        .machine_check_exception = pSeries_machine_check_exception,
        .machine_check_log_err  = pSeries_machine_check_log_err,
 #ifdef CONFIG_KEXEC_CORE
-       .machine_kexec          = pseries_machine_kexec,
        .kexec_cpu_down         = pseries_kexec_cpu_down,
 #endif
 #ifdef CONFIG_MEMORY_HOTPLUG