From: Bradley Morgan <include@grrlz.net>
To: akpm@linux-foundation.org
Cc: pmladek@suse.com, feng.tang@linux.alibaba.com, tglx@kernel.org,
peterz@infradead.org, rostedt@goodmis.org,
linux-kernel@vger.kernel.org, include@grrlz.net,
Sashiko <sashiko-bot@kernel.org>
Subject: [PATCH v2] panic: allow force_cpu redirect from an NMI
Date: Wed, 8 Jul 2026 16:43:12 +0000 [thread overview]
Message-ID: <20260708164312.19044-1-include@grrlz.net> (raw)
nmi_panic() calls panic_try_start() before panic(), so it claims
panic_cpu first. When the panic then reaches panic_try_force_cpu(),
panic_in_progress() sees panic_cpu set and returns false, so the
redirect to the requested CPU never happens. The crash kernel runs
on the CPU that took the NMI instead.
smp_call_function_single_async() is safe from NMI context, so move
the redirect first. nmi_panic() now calls panic_try_force_cpu()
before panic_try_start(), and only claims panic_cpu when no redirect
is done. The requested CPU then claims panic_cpu itself.
Also use panic_on_other_cpu() in place of the open coded check and
return true to stop directly.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260707183253.9793-1-include@grrlz.net
Signed-off-by: Bradley Morgan <include@grrlz.net>
---
kernel/panic.c | 38 ++++++++++++++++----------------------
1 file changed, 16 insertions(+), 22 deletions(-)
Changes since v1:
- Dropped the atomic_set panic_cpu hand off, it was racy.
- Restructured nmi_panic() to call panic_try_force_cpu() first.
- Used panic_on_other_cpu() instead of an open coded check.
- panic_try_force_cpu() now takes a formatted message string.
diff --git a/kernel/panic.c b/kernel/panic.c
index ebdc46af6aa9..b039bb6f1d19 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -364,8 +364,7 @@ int __weak panic_smp_redirect_cpu(int target_cpu, void *msg)
/**
* panic_try_force_cpu - Redirect panic to a specific CPU for crash kernel
- * @fmt: panic message format string
- * @args: arguments for format string
+ * @msg: already formatted panic message
*
* Some platforms require panic handling to occur on a specific CPU
* for the crash kernel to function correctly. This function redirects
@@ -374,12 +373,10 @@ int __weak panic_smp_redirect_cpu(int target_cpu, void *msg)
* Returns false if panic should proceed on current CPU.
* Returns true if panic was redirected.
*/
-__printf(1, 0)
-static bool panic_try_force_cpu(const char *fmt, va_list args)
+static bool panic_try_force_cpu(const char *msg)
{
int this_cpu = raw_smp_processor_id();
int old_cpu = PANIC_CPU_INVALID;
- const char *msg;
/* Feature not enabled via boot parameter */
if (panic_force_cpu < 0)
@@ -396,9 +393,9 @@ static bool panic_try_force_cpu(const char *fmt, va_list args)
return false;
}
- /* Another panic already in progress */
- if (panic_in_progress())
- return false;
+ /* Stop this CPU when the panic is already proceeding elsewhere. */
+ if (panic_on_other_cpu())
+ return true;
/*
* Only one CPU can do the redirection. Others should go
@@ -412,12 +409,7 @@ static bool panic_try_force_cpu(const char *fmt, va_list args)
* fall back to static message for early boot panics or allocation failure.
*/
if (panic_force_buf) {
- va_list ap;
-
- /* Do not consume args, the caller reuses it if we fail */
- va_copy(ap, args);
- vsnprintf(panic_force_buf, PANIC_MSG_BUFSZ, fmt, ap);
- va_end(ap);
+ strscpy(panic_force_buf, msg, PANIC_MSG_BUFSZ);
msg = panic_force_buf;
} else {
msg = "Redirected panic (buffer unavailable)";
@@ -447,8 +439,7 @@ static bool panic_try_force_cpu(const char *fmt, va_list args)
return true;
}
#else
-__printf(1, 0)
-static inline bool panic_try_force_cpu(const char *fmt, va_list args)
+static inline bool panic_try_force_cpu(const char *msg)
{
return false;
}
@@ -515,7 +506,9 @@ EXPORT_SYMBOL(panic_on_other_cpu);
*/
void nmi_panic(struct pt_regs *regs, const char *msg)
{
- if (panic_try_start())
+ if (panic_try_force_cpu(msg))
+ nmi_panic_self_stop(regs);
+ else if (panic_try_start())
panic("%s", msg);
else if (panic_on_other_cpu())
nmi_panic_self_stop(regs);
@@ -609,8 +602,13 @@ void vpanic(const char *fmt, va_list args)
local_irq_disable();
preempt_disable_notrace();
+ /* Format the message once; reused for the log and any redirect IPI. */
+ len = vscnprintf(buf, sizeof(buf), fmt, args);
+ if (len && buf[len - 1] == '\n')
+ buf[len - 1] = '\0';
+
/* Redirect panic to target CPU if configured via panic_force_cpu=. */
- if (panic_try_force_cpu(fmt, args)) {
+ if (panic_try_force_cpu(buf)) {
/*
* Mark ourselves offline so panic_other_cpus_shutdown() won't wait
* for us on architectures that check num_online_cpus().
@@ -641,10 +639,6 @@ void vpanic(const char *fmt, va_list args)
console_verbose();
bust_spinlocks(1);
- len = vscnprintf(buf, sizeof(buf), fmt, args);
-
- if (len && buf[len - 1] == '\n')
- buf[len - 1] = '\0';
pr_emerg("Kernel panic - not syncing: %s\n", buf);
/*
--
2.53.0
next reply other threads:[~2026-07-08 16:43 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-08 16:43 Bradley Morgan [this message]
2026-07-13 14:04 ` [PATCH v2] panic: allow force_cpu redirect from an NMI Petr Mladek
2026-07-14 0:21 ` Andrew Morton
2026-07-14 8:28 ` Petr Mladek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260708164312.19044-1-include@grrlz.net \
--to=include@grrlz.net \
--cc=akpm@linux-foundation.org \
--cc=feng.tang@linux.alibaba.com \
--cc=linux-kernel@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=pmladek@suse.com \
--cc=rostedt@goodmis.org \
--cc=sashiko-bot@kernel.org \
--cc=tglx@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.