summaryrefslogtreecommitdiff
path: root/kernel/panic.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/panic.c')
-rw-r--r--kernel/panic.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/kernel/panic.c b/kernel/panic.c
index e240ca06faab..29c981926f5f 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -513,10 +513,11 @@ bool panic_on_other_cpu(void)
EXPORT_SYMBOL(panic_on_other_cpu);
/*
- * A variant of panic() called from NMI context. We return if we've already
- * panicked on this CPU. If another CPU already panicked, loop in
- * nmi_panic_self_stop() which can provide architecture dependent code such
- * as saving register state for crash dump.
+ * A variant of panic() called from NMI context. The panic is first
+ * redirected to the CPU requested via panic_force_cpu=, when configured.
+ * We return if we've already panicked on this CPU. If another CPU already
+ * panicked, loop in nmi_panic_self_stop() which can provide architecture
+ * dependent code for saving register state for crash dump.
*/
void nmi_panic(struct pt_regs *regs, const char *fmt, ...)
{
@@ -524,6 +525,16 @@ void nmi_panic(struct pt_regs *regs, const char *fmt, ...)
va_start(args, fmt);
+ /* Try to redirect to the requested CPU before claiming panic_cpu. */
+ if (panic_try_force_cpu(fmt, args)) {
+ /*
+ * Mark ourselves offline so panic_other_cpus_shutdown() won't
+ * wait for us on architectures that check num_online_cpus().
+ */
+ set_cpu_online(raw_smp_processor_id(), false);
+ nmi_panic_self_stop(regs);
+ }
+
if (panic_try_start())
vpanic(fmt, args);