arm64: Implement panic_smp_self_stop()
authorAaro Koskinen <aaro.koskinen@nokia.com>
Mon, 17 Jun 2019 20:35:19 +0000 (23:35 +0300)
committerCatalin Marinas <catalin.marinas@arm.com>
Tue, 25 Jun 2019 15:42:19 +0000 (16:42 +0100)
Currently arm64 uses the default implementation of panic_smp_self_stop()
where the CPU runs in a cpu_relax() loop unable to receive IPIs anymore.
As a result, when two CPUs panic() simultaneously we get "SMP: failed to
stop secondary CPUs" warnings and extra delays before a reset, because
smp_send_stop() still tries to stop the other paniced CPU.

Provide an implementation of panic_smp_self_stop() that is identical to
the IPI CPU stop handler, so that the online status of stopped CPUs gets
properly updated.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/kernel/smp.c

index 932461d..434d671 100644 (file)
@@ -841,18 +841,25 @@ void arch_irq_work_raise(void)
 }
 #endif
 
-/*
- * ipi_cpu_stop - handle IPI from smp_send_stop()
- */
-static void ipi_cpu_stop(unsigned int cpu)
+static void local_cpu_stop(void)
 {
-       set_cpu_online(cpu, false);
+       set_cpu_online(smp_processor_id(), false);
 
        local_daif_mask();
        sdei_mask_local_cpu();
        cpu_park_loop();
 }
 
+/*
+ * We need to implement panic_smp_self_stop() for parallel panic() calls, so
+ * that cpu_online_mask gets correctly updated and smp_send_stop() can skip
+ * CPUs that have already stopped themselves.
+ */
+void panic_smp_self_stop(void)
+{
+       local_cpu_stop();
+}
+
 #ifdef CONFIG_KEXEC_CORE
 static atomic_t waiting_for_crash_ipi = ATOMIC_INIT(0);
 #endif
@@ -903,7 +910,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
 
        case IPI_CPU_STOP:
                irq_enter();
-               ipi_cpu_stop(cpu);
+               local_cpu_stop();
                irq_exit();
                break;