[PATCH v3] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU

Pnina Feder posted 1 patch 1 month ago
There is a newer version of this series
kernel/panic.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)
[PATCH v3] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
Posted by Pnina Feder 1 month ago
Some platforms require panic handling to execute on a specific CPU for
crash dump to work reliably. This can be due to firmware limitations,
interrupt routing constraints, or platform-specific requirements where
only a single CPU is able to safely enter the crash kernel.

Add support for redirecting panic execution to a designated CPU via a
kernel command-line parameter. When the parameter is provided, the CPU
that initially triggers panic forwards the panic context to the target
CPU, which then proceeds with the normal panic and kexec flow.

If the specified CPU is invalid, offline, or a panic is already in
progress on another CPU, the redirection is skipped and panic continues
on the current CPU.

Changes since v2:
 - Make panic redirection warnings generic and platform-agnostic

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202601041820.6M8cIq2e-lkp@intel.com/
Signed-off-by: Pnina Feder <pnina.feder@mobileye.com>
---
 kernel/panic.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)

diff --git a/kernel/panic.c b/kernel/panic.c
index 0d52210a9e2b..6239bcdc2463 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -300,6 +300,92 @@ void __weak crash_smp_send_stop(void)
 
 atomic_t panic_cpu = ATOMIC_INIT(PANIC_CPU_INVALID);
 
+#ifdef CONFIG_SMP
+/* CPU to redirect panic to, -1 means feature is disabled */
+static int panic_force_cpu = -1;
+
+static int __init panic_force_cpu_setup(char *str)
+{
+	int cpu;
+
+	if (!str)
+		return -EINVAL;
+
+	if (kstrtoint(str, 0, &cpu) || cpu < 0) {
+		pr_warn("panic_force_cpu: invalid value '%s'\n", str);
+		return -EINVAL;
+	}
+
+	panic_force_cpu = cpu;
+	pr_info("panic_force_cpu: panic will execute on CPU %d\n", cpu);
+	return 0;
+}
+early_param("panic_force_cpu", panic_force_cpu_setup);
+
+static void do_panic_on_target_cpu(void *info)
+{
+	panic("%s", (char *)info);
+}
+
+/**
+ * panic_force_target_cpu - Redirect panic to a specific CPU for crash kernel
+ * @fmt: panic message format string
+ * @args: arguments for format string
+ *
+ * Some platforms require panic handling to occur on a specific CPU
+ * for the crash kernel to function correctly. This function redirects
+ * panic handling to the CPU specified via the panic_redirect_cpu= boot parameter.
+ *
+ * Returns true if panic should proceed on current CPU.
+ * Returns false (never returns) if panic was redirected.
+ */
+__printf(1, 0)
+static bool panic_force_target_cpu(const char *fmt, va_list args)
+{
+	static char panic_redirect_msg[1024];
+	int cpu = raw_smp_processor_id();
+	int target_cpu = panic_force_cpu;
+
+	/* Feature not enabled via boot parameter */
+	if (target_cpu < 0)
+		return true;
+
+	/* Already on target CPU - proceed normally */
+	if (cpu == target_cpu)
+		return true;
+
+	/* Target CPU is offline, can't redirect */
+	if (!cpu_online(target_cpu)) {
+		pr_warn("panic: target CPU %d is offline, proceeding on CPU %d.\n"
+			"Crash kernel interrupts may be unavailable.\n", target_cpu, cpu);
+		return true;
+	}
+
+	/* Another panic already in progress */
+	if (panic_in_progress()) {
+		pr_warn("panic: Another panic in progress on CPU %d, cannot redirect to CPU %d.\n"
+			"Crash kernel interrupts may be unavailable.\n",
+			atomic_read(&panic_cpu), target_cpu);
+		return true;
+	}
+
+	pr_info("panic: Redirecting from CPU %d to CPU %d for crash kernel\n",
+		cpu, target_cpu);
+
+	vsnprintf(panic_redirect_msg, sizeof(panic_redirect_msg), fmt, args);
+
+	smp_call_function_single(target_cpu, do_panic_on_target_cpu, panic_redirect_msg, false);
+
+	return false;
+}
+#else
+__printf(1, 0)
+static inline bool panic_force_target_cpu(const char *fmt, va_list args)
+{
+	return true;
+}
+#endif /* CONFIG_SMP */
+
 bool panic_try_start(void)
 {
 	int old_cpu, this_cpu;
@@ -451,6 +537,13 @@ void vpanic(const char *fmt, va_list args)
 	local_irq_disable();
 	preempt_disable_notrace();
 
+	/*
+	 * Redirect panic to target CPU if configured via panic_force_cpu=.
+	 * Returns false and never returns if panic was redirected.
+	 */
+	if (!panic_force_target_cpu(fmt, args))
+		panic_smp_self_stop();
+
 	/*
 	 * It's possible to come here directly from a panic-assertion and
 	 * not have preempt disabled. Some functions called from here want
-- 
2.43.0
Re: [PATCH v3] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
Posted by Petr Mladek 1 month ago
Adding more people into Cc. I doubt that smp_call_function_single()
is reliable in panic().

On Mon 2026-01-05 10:18:08, Pnina Feder wrote:
> Some platforms require panic handling to execute on a specific CPU for
> crash dump to work reliably. This can be due to firmware limitations,
> interrupt routing constraints, or platform-specific requirements where
> only a single CPU is able to safely enter the crash kernel.
> 
> Add support for redirecting panic execution to a designated CPU via a
> kernel command-line parameter. When the parameter is provided, the CPU
> that initially triggers panic forwards the panic context to the target
> CPU, which then proceeds with the normal panic and kexec flow.
> 
> If the specified CPU is invalid, offline, or a panic is already in
> progress on another CPU, the redirection is skipped and panic continues
> on the current CPU.
> 
> Changes since v2:
>  - Make panic redirection warnings generic and platform-agnostic
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202601041820.6M8cIq2e-lkp@intel.com/
> Signed-off-by: Pnina Feder <pnina.feder@mobileye.com>
> ---
>  kernel/panic.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 93 insertions(+)
> 
> diff --git a/kernel/panic.c b/kernel/panic.c
> index 0d52210a9e2b..6239bcdc2463 100644
> --- a/kernel/panic.c
> +++ b/kernel/panic.c
> @@ -300,6 +300,92 @@ void __weak crash_smp_send_stop(void)
>  
>  atomic_t panic_cpu = ATOMIC_INIT(PANIC_CPU_INVALID);
>  
> +#ifdef CONFIG_SMP
> +/* CPU to redirect panic to, -1 means feature is disabled */
> +static int panic_force_cpu = -1;
> +
> +static int __init panic_force_cpu_setup(char *str)
> +{
> +	int cpu;
> +
> +	if (!str)
> +		return -EINVAL;
> +
> +	if (kstrtoint(str, 0, &cpu) || cpu < 0) {
> +		pr_warn("panic_force_cpu: invalid value '%s'\n", str);
> +		return -EINVAL;
> +	}
> +
> +	panic_force_cpu = cpu;
> +	pr_info("panic_force_cpu: panic will execute on CPU %d\n", cpu);
> +	return 0;
> +}
> +early_param("panic_force_cpu", panic_force_cpu_setup);
> +
> +static void do_panic_on_target_cpu(void *info)
> +{
> +	panic("%s", (char *)info);
> +}
> +
> +/**
> + * panic_force_target_cpu - Redirect panic to a specific CPU for crash kernel
> + * @fmt: panic message format string
> + * @args: arguments for format string
> + *
> + * Some platforms require panic handling to occur on a specific CPU
> + * for the crash kernel to function correctly. This function redirects
> + * panic handling to the CPU specified via the panic_redirect_cpu= boot parameter.
> + *
> + * Returns true if panic should proceed on current CPU.
> + * Returns false (never returns) if panic was redirected.
> + */
> +__printf(1, 0)
> +static bool panic_force_target_cpu(const char *fmt, va_list args)
> +{
> +	static char panic_redirect_msg[1024];
> +	int cpu = raw_smp_processor_id();
> +	int target_cpu = panic_force_cpu;
> +
> +	/* Feature not enabled via boot parameter */
> +	if (target_cpu < 0)
> +		return true;
> +
> +	/* Already on target CPU - proceed normally */
> +	if (cpu == target_cpu)
> +		return true;
> +
> +	/* Target CPU is offline, can't redirect */
> +	if (!cpu_online(target_cpu)) {
> +		pr_warn("panic: target CPU %d is offline, proceeding on CPU %d.\n"
> +			"Crash kernel interrupts may be unavailable.\n", target_cpu, cpu);
> +		return true;
> +	}
> +
> +	/* Another panic already in progress */
> +	if (panic_in_progress()) {
> +		pr_warn("panic: Another panic in progress on CPU %d, cannot redirect to CPU %d.\n"

IMHO, this message does not add much value and should be omitted.
vpanic() does not print any message when panic_try_start() fails.

> +			"Crash kernel interrupts may be unavailable.\n",

I am confused by this message.

> +			atomic_read(&panic_cpu), target_cpu);
> +		return true;
> +	}
> +
> +	pr_info("panic: Redirecting from CPU %d to CPU %d for crash kernel\n",
> +		cpu, target_cpu);
> +
> +	vsnprintf(panic_redirect_msg, sizeof(panic_redirect_msg), fmt, args);

The "redirect" in "panic_redirect_msg" is confusing. It has nothing
to do with redirection. It is just a buffer for the formatted panic
message. I would call it "buf" or "panic_msg".

> +	smp_call_function_single(target_cpu, do_panic_on_target_cpu, panic_redirect_msg, false);

I doubt that this is safe and reliable in panic() context.
For a start, panic() might be called in NMI and this function takes csd_lock().

panic() code should avoid locks. Or is should use trylock and
handle a failure gracefully.

BTW: The commit message says that this is needed for crash-dump
     to work reliably. So, it does not make sense to do this
     when crash-dump is not configured.

     Maybe, crash-dump should get fixed instead?
     What are the exact problems with the crash-dump, please?

> +
> +	return false;
> +}
> +#else
> +__printf(1, 0)
> +static inline bool panic_force_target_cpu(const char *fmt, va_list args)
> +{
> +	return true;
> +}
> +#endif /* CONFIG_SMP */
> +
>  bool panic_try_start(void)
>  {
>  	int old_cpu, this_cpu;
> @@ -451,6 +537,13 @@ void vpanic(const char *fmt, va_list args)
>  	local_irq_disable();
>  	preempt_disable_notrace();
>  
> +	/*
> +	 * Redirect panic to target CPU if configured via panic_force_cpu=.
> +	 * Returns false and never returns if panic was redirected.
> +	 */
> +	if (!panic_force_target_cpu(fmt, args))
> +		panic_smp_self_stop();
> +
>  	/*
>  	 * It's possible to come here directly from a panic-assertion and
>  	 * not have preempt disabled. Some functions called from here want

Best Regards,
Petr
[PATCH v5] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
Posted by Pnina Feder 1 month ago
Some platforms require panic handling to execute on a specific CPU for
crash dump to work reliably. This can be due to firmware limitations,
interrupt routing constraints, or platform-specific requirements where
only a single CPU is able to safely enter the crash kernel.

Add the panic_force_cpu= kernel command-line parameter to redirect panic
execution to a designated CPU. When the parameter is provided, the CPU
that initially triggers panic forwards the panic context to the target
CPU via IPI, which then proceeds with the normal panic and kexec flow.

The IPI delivery is implemented as a weak function (panic_smp_redirect_cpu)
so architectures with NMI support can override it for more reliable delivery.

If the specified CPU is invalid, offline, or a panic is already in
progress on another CPU, the redirection is skipped and panic continues
on the current CPU.

Changes since v4:
 - Make IPI delivery an overridable weak function (panic_smp_redirect_cpu)
   so architectures can use NMI where available
 - Add declaration on include/linux/smp.h alongside other panic SMP functions
 - Add warning to documentation about reduced reliability
 - Address review comments from Andrew Morton (remove unnecessary cast,
   add missing kernel-doc parameters)

Signed-off-by: Pnina Feder <pnina.feder@mobileye.com>
---
 .../admin-guide/kernel-parameters.txt         |  15 +++
 include/linux/smp.h                           |   1 +
 kernel/panic.c                                | 122 ++++++++++++++++++
 3 files changed, 138 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index a8d0afde7f85..6d6f2880302f 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4753,6 +4753,21 @@ Kernel parameters
 	panic_on_warn=1	panic() instead of WARN().  Useful to cause kdump
 			on a WARN().
 
+	panic_force_cpu=
+			[KNL,SMP] Force panic handling to execute on a specific CPU.
+			Format: <cpu number>
+			Some platforms require panic handling to occur on a
+			specific CPU for the crash kernel to function correctly.
+			This can be due to firmware limitations, interrupt routing
+			constraints, or platform-specific requirements where only
+			a particular CPU can safely enter the crash kernel.
+			When set, panic() will redirect execution to the specified
+			CPU before proceeding with the normal panic and kexec flow.
+			If the target CPU is offline or unavailable, panic proceeds
+			on the current CPU.
+			This option should only be used for systems with the above
+			constraints as it might cause the panic operation to be less reliable.
+
 	panic_print=	Bitmask for printing system info when panic happens.
 			User can chose combination of the following bits:
 			bit 0: print all tasks info
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 91d0ecf3b8d3..1ebd88026119 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -62,6 +62,7 @@ int smp_call_function_single_async(int cpu, call_single_data_t *csd);
 void __noreturn panic_smp_self_stop(void);
 void __noreturn nmi_panic_self_stop(struct pt_regs *regs);
 void crash_smp_send_stop(void);
+int panic_smp_redirect_cpu(int target_cpu, void *msg);
 
 /*
  * Call a function on all processors
diff --git a/kernel/panic.c b/kernel/panic.c
index 0d52210a9e2b..f03eb60ae8ac 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -300,6 +300,121 @@ void __weak crash_smp_send_stop(void)
 
 atomic_t panic_cpu = ATOMIC_INIT(PANIC_CPU_INVALID);
 
+#if defined(CONFIG_SMP) && defined(CONFIG_CRASH_DUMP)
+/* CPU to redirect panic to, or -1 if disabled */
+static int panic_force_cpu = -1;
+
+static int __init panic_force_cpu_setup(char *str)
+{
+	int cpu;
+
+	if (!str)
+		return -EINVAL;
+
+	if (kstrtoint(str, 0, &cpu) || cpu < 0) {
+		pr_warn("panic_force_cpu: invalid value '%s'\n", str);
+		return -EINVAL;
+	}
+
+	panic_force_cpu = cpu;
+	return 0;
+}
+early_param("panic_force_cpu", panic_force_cpu_setup);
+
+static void do_panic_on_target_cpu(void *info)
+{
+	panic("%s", info);
+}
+
+/**
+ * panic_smp_redirect_cpu - Redirect panic to target CPU
+ * @target_cpu: CPU that should handle the panic
+ * @msg: formatted panic message
+ *
+ * Default implementation uses IPI. Architectures with NMI support
+ * can override this for more reliable delivery.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int __weak panic_smp_redirect_cpu(int target_cpu, void *msg)
+{
+	static call_single_data_t panic_csd;
+
+	panic_csd.func = do_panic_on_target_cpu;
+	panic_csd.info = msg;
+
+	return smp_call_function_single_async(target_cpu, &panic_csd);
+}
+
+/**
+ * panic_force_target_cpu - Redirect panic to a specific CPU for crash kernel
+ * @buf: buffer to format the panic message into
+ * @buf_size: size of the buffer
+ * @fmt: panic message format string
+ * @args: arguments for format string
+ *
+ * Some platforms require panic handling to occur on a specific CPU
+ * for the crash kernel to function correctly. This function redirects
+ * panic handling to the CPU specified via the panic_redirect_cpu= boot parameter.
+ *
+ * Returns true if panic should proceed on current CPU.
+ * Returns false (never returns) if panic was redirected.
+ */
+__printf(3, 0)
+static bool panic_force_target_cpu(char *buf, int buf_size, const char *fmt, va_list args)
+{
+	int cpu = raw_smp_processor_id();
+	int target_cpu = panic_force_cpu;
+
+	/* Feature not enabled via boot parameter */
+	if (target_cpu < 0)
+		return true;
+
+	/* Already on target CPU - proceed normally */
+	if (cpu == target_cpu)
+		return true;
+
+	/* Target CPU is offline, can't redirect */
+	if (!cpu_online(target_cpu))
+		return true;
+
+	/* Another panic already in progress */
+	if (panic_in_progress())
+		return true;
+
+	vsnprintf(buf, buf_size, fmt, args);
+
+	console_verbose();
+	bust_spinlocks(1);
+
+	pr_emerg("panic: Redirecting from CPU %d to CPU %d for crash kernel\n",
+		cpu, target_cpu);
+
+	/* Dump original CPU's stack before redirecting */
+	if (test_taint(TAINT_DIE) || oops_in_progress > 1) {
+		panic_this_cpu_backtrace_printed = true;
+	} else if (IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE)) {
+		dump_stack();
+		panic_this_cpu_backtrace_printed = true;
+	}
+
+	printk_legacy_allow_panic_sync();
+	console_flush_on_panic(CONSOLE_FLUSH_PENDING);
+
+	if (panic_smp_redirect_cpu(target_cpu, buf) != 0)
+		return true;
+
+	/* IPI/NMI sent, this CPU should stop */
+	return false;
+}
+#else
+__printf(3, 0)
+static inline bool panic_force_target_cpu(char *buf, int buf_size, const char *fmt, va_list args)
+{
+	return true;
+}
+#endif /* CONFIG_SMP && CONFIG_CRASH_DUMP */
+
 bool panic_try_start(void)
 {
 	int old_cpu, this_cpu;
@@ -451,6 +566,13 @@ void vpanic(const char *fmt, va_list args)
 	local_irq_disable();
 	preempt_disable_notrace();
 
+	/*
+	 * Redirect panic to target CPU if configured via panic_force_cpu=.
+	 * Returns false and never returns if panic was redirected.
+	 */
+	if (!panic_force_target_cpu(buf, sizeof(buf), fmt, args))
+		panic_smp_self_stop();
+
 	/*
 	 * It's possible to come here directly from a panic-assertion and
 	 * not have preempt disabled. Some functions called from here want
-- 
2.43.0
Re: [PATCH v5] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
Posted by kernel test robot 4 weeks, 1 day ago
Hi Pnina,

kernel test robot noticed the following build warnings:

[auto build test WARNING on akpm-mm/mm-everything]
[also build test WARNING on linus/master v6.19-rc4 next-20260109]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Pnina-Feder/panic-add-panic_force_cpu-parameter-to-redirect-panic-to-a-specific-CPU/20260109-043725
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/20260108203612.955769-1-pnina.feder%40mobileye.com
patch subject: [PATCH v5] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
config: x86_64-rhel-9.4 (https://download.01.org/0day-ci/archive/20260109/202601092335.DbBERt3l-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260109/202601092335.DbBERt3l-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202601092335.DbBERt3l-lkp@intel.com/

All warnings (new ones prefixed by >>):

   kernel/panic.c: In function 'do_panic_on_target_cpu':
>> kernel/panic.c:327:17: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'void *' [-Wformat=]
     327 |         panic("%s", info);
         |                ~^   ~~~~
         |                 |   |
         |                 |   void *
         |                 char *
         |                %p


vim +327 kernel/panic.c

   324	
   325	static void do_panic_on_target_cpu(void *info)
   326	{
 > 327		panic("%s", info);
   328	}
   329	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v5] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
Posted by Andrew Morton 4 weeks, 1 day ago
On Fri, 9 Jan 2026 23:19:34 +0100 kernel test robot <lkp@intel.com> wrote:

>    kernel/panic.c: In function 'do_panic_on_target_cpu':
> >> kernel/panic.c:327:17: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'void *' [-Wformat=]
>      327 |         panic("%s", info);
>          |                ~^   ~~~~

Thanks.  That's what you get for listening to akpm ;)

Stupid compiler.
Re: [PATCH v5] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
Posted by Steven Rostedt 1 month ago
On Thu,  8 Jan 2026 22:36:12 +0200
Pnina Feder <pnina.feder@mobileye.com> wrote:

First, new versions of a patch or patch set should *always* be a new thread
and not a reply to the old version. That makes it much harder on
maintainers to see a new series.

> If the specified CPU is invalid, offline, or a panic is already in
> progress on another CPU, the redirection is skipped and panic continues
> on the current CPU.
> 
> Changes since v4:
>  - Make IPI delivery an overridable weak function (panic_smp_redirect_cpu)
>    so architectures can use NMI where available
>  - Add declaration on include/linux/smp.h alongside other panic SMP functions
>  - Add warning to documentation about reduced reliability
>  - Address review comments from Andrew Morton (remove unnecessary cast,
>    add missing kernel-doc parameters)
> 
> Signed-off-by: Pnina Feder <pnina.feder@mobileye.com>
> ---

The "Changes since" line should always be below the '---' otherwise it gets
pulled into the git log and the maintainer needs to manually delete it
(which is annoying).

Also, it is helpful to add a link to the previous version.

> Signed-off-by: Pnina Feder <pnina.feder@mobileye.com>
> ---
 Changes since v4: https://lore.kernel.org/all/20260107215659.3619730-1-pnina.feder@mobileye.com/
  - Make IPI delivery an overridable weak function (panic_smp_redirect_cpu)
    so architectures can use NMI where available
  - Add declaration on include/linux/smp.h alongside other panic SMP functions
  - Add warning to documentation about reduced reliability
  - Address review comments from Andrew Morton (remove unnecessary cast,
    add missing kernel-doc parameters)

This provides the continuity between versions without having to be replies
of older versions.

-- Steve
[PATCH v4] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
Posted by Pnina Feder 1 month ago
Some platforms require panic handling to execute on a specific CPU for
crash dump to work reliably. This can be due to firmware limitations,
interrupt routing constraints, or platform-specific requirements where
only a single CPU is able to safely enter the crash kernel.

Add the panic_force_cpu= kernel command-line parameter to redirect panic
execution to a designated CPU. When the parameter is provided, the CPU
that initially triggers panic forwards the panic context to the target
CPU via IPI, which then proceeds with the normal panic and kexec flow.

If the specified CPU is invalid, offline, or a panic is already in
progress on another CPU, the redirection is skipped and panic continues
on the current CPU.

Changes since v3:
 - Dump original CPU's stack before redirecting to preserve debug info
 - Add Documentation/admin-guide/kernel-parameters.txt entry
 - Use smp_call_function_single_async() to avoid blocking in csd_lock()
 - Add CONFIG_CRASH_DUMP dependency
 - Reuse vpanic()'s static buffer instead of separate allocation
 - Remove verbose warning messages

Signed-off-by: Pnina Feder <pnina.feder@mobileye.com>
---
 .../admin-guide/kernel-parameters.txt         |  13 +++
 kernel/panic.c                                | 104 ++++++++++++++++++
 2 files changed, 117 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index a8d0afde7f85..561ce09a6ae1 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4753,6 +4753,19 @@ Kernel parameters
 	panic_on_warn=1	panic() instead of WARN().  Useful to cause kdump
 			on a WARN().
 
+	panic_force_cpu=
+			[KNL,SMP] Force panic handling to execute on a specific CPU.
+			Format: <cpu number>
+			Some platforms require panic handling to occur on a
+			specific CPU for the crash kernel to function correctly.
+			This can be due to firmware limitations, interrupt routing
+			constraints, or platform-specific requirements where only
+			a particular CPU can safely enter the crash kernel.
+			When set, panic() will redirect execution to the specified
+			CPU before proceeding with the normal panic and kexec flow.
+			If the target CPU is offline or unavailable, panic proceeds
+			on the current CPU.
+
 	panic_print=	Bitmask for printing system info when panic happens.
 			User can chose combination of the following bits:
 			bit 0: print all tasks info
diff --git a/kernel/panic.c b/kernel/panic.c
index 0d52210a9e2b..414ef60d2306 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -300,6 +300,103 @@ void __weak crash_smp_send_stop(void)
 
 atomic_t panic_cpu = ATOMIC_INIT(PANIC_CPU_INVALID);
 
+#if defined(CONFIG_SMP) && defined(CONFIG_CRASH_DUMP)
+/* CPU to redirect panic to, or -1 if disabled */
+static int panic_force_cpu = -1;
+static call_single_data_t panic_csd;
+
+static int __init panic_force_cpu_setup(char *str)
+{
+	int cpu;
+
+	if (!str)
+		return -EINVAL;
+
+	if (kstrtoint(str, 0, &cpu) || cpu < 0) {
+		pr_warn("panic_force_cpu: invalid value '%s'\n", str);
+		return -EINVAL;
+	}
+
+	panic_force_cpu = cpu;
+	return 0;
+}
+early_param("panic_force_cpu", panic_force_cpu_setup);
+
+static void do_panic_on_target_cpu(void *info)
+{
+	panic("%s", (char *)info);
+}
+
+/**
+ * panic_force_target_cpu - Redirect panic to a specific CPU for crash kernel
+ * @fmt: panic message format string
+ * @args: arguments for format string
+ *
+ * Some platforms require panic handling to occur on a specific CPU
+ * for the crash kernel to function correctly. This function redirects
+ * panic handling to the CPU specified via the panic_redirect_cpu= boot parameter.
+ *
+ * Returns true if panic should proceed on current CPU.
+ * Returns false (never returns) if panic was redirected.
+ */
+__printf(3, 0)
+static bool panic_force_target_cpu(char *buf, int buf_size, const char *fmt, va_list args)
+{
+	int cpu = raw_smp_processor_id();
+	int target_cpu = panic_force_cpu;
+
+	/* Feature not enabled via boot parameter */
+	if (target_cpu < 0)
+		return true;
+
+	/* Already on target CPU - proceed normally */
+	if (cpu == target_cpu)
+		return true;
+
+	/* Target CPU is offline, can't redirect */
+	if (!cpu_online(target_cpu))
+		return true;
+
+	/* Another panic already in progress */
+	if (panic_in_progress())
+		return true;
+
+	vsnprintf(buf, buf_size, fmt, args);
+
+	console_verbose();
+	bust_spinlocks(1);
+
+	pr_emerg("panic: Redirecting from CPU %d to CPU %d for crash kernel\n",
+		cpu, target_cpu);
+
+	/* Dump original CPU's stack before redirecting */
+	if (test_taint(TAINT_DIE) || oops_in_progress > 1) {
+		panic_this_cpu_backtrace_printed = true;
+	} else if (IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE)) {
+		dump_stack();
+		panic_this_cpu_backtrace_printed = true;
+	}
+
+	printk_legacy_allow_panic_sync();
+	console_flush_on_panic(CONSOLE_FLUSH_PENDING);
+
+	panic_csd.func = do_panic_on_target_cpu;
+	panic_csd.info = buf;
+
+	/* Use smp_call_function_single_async() to avoid blocking in csd_lock(). */
+	if (smp_call_function_single_async(target_cpu, &panic_csd) != 0)
+		return true;
+
+	return false;
+}
+#else
+__printf(3, 0)
+static inline bool panic_force_target_cpu(char *buf, int buf_size, const char *fmt, va_list args)
+{
+	return true;
+}
+#endif /* CONFIG_SMP && CONFIG CRASH_DUMP */
+
 bool panic_try_start(void)
 {
 	int old_cpu, this_cpu;
@@ -451,6 +548,13 @@ void vpanic(const char *fmt, va_list args)
 	local_irq_disable();
 	preempt_disable_notrace();
 
+	/*
+	 * Redirect panic to target CPU if configured via panic_force_cpu=.
+	 * Returns false and never returns if panic was redirected.
+	 */
+	if (!panic_force_target_cpu(buf, sizeof(buf), fmt, args))
+		panic_smp_self_stop();
+
 	/*
 	 * It's possible to come here directly from a panic-assertion and
 	 * not have preempt disabled. Some functions called from here want
-- 
2.43.0
Re: [PATCH v4] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
Posted by kernel test robot 1 month ago
Hi Pnina,

kernel test robot noticed the following build warnings:

[auto build test WARNING on akpm-mm/mm-everything]
[also build test WARNING on linus/master v6.19-rc4 next-20260108]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Pnina-Feder/panic-add-panic_force_cpu-parameter-to-redirect-panic-to-a-specific-CPU/20260108-055823
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/20260107215659.3619730-1-pnina.feder%40mobileye.com
patch subject: [PATCH v4] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
config: x86_64-kexec (https://download.01.org/0day-ci/archive/20260109/202601090229.rC0GNQqG-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260109/202601090229.rC0GNQqG-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202601090229.rC0GNQqG-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> Warning: kernel/panic.c:344 function parameter 'buf' not described in 'panic_force_target_cpu'
>> Warning: kernel/panic.c:344 function parameter 'buf_size' not described in 'panic_force_target_cpu'
>> Warning: kernel/panic.c:344 function parameter 'buf' not described in 'panic_force_target_cpu'
>> Warning: kernel/panic.c:344 function parameter 'buf_size' not described in 'panic_force_target_cpu'

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v4] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
Posted by Peter Zijlstra 1 month ago
On Wed, Jan 07, 2026 at 11:56:59PM +0200, Pnina Feder wrote:
> Some platforms require panic handling to execute on a specific CPU for
> crash dump to work reliably. This can be due to firmware limitations,
> interrupt routing constraints, or platform-specific requirements where
> only a single CPU is able to safely enter the crash kernel.
> 
> Add the panic_force_cpu= kernel command-line parameter to redirect panic
> execution to a designated CPU. When the parameter is provided, the CPU
> that initially triggers panic forwards the panic context to the target
> CPU via IPI, which then proceeds with the normal panic and kexec flow.
> 
> If the specified CPU is invalid, offline, or a panic is already in
> progress on another CPU, the redirection is skipped and panic continues
> on the current CPU.

This seems exceedingly fragile to me. Who is saying the target CPU is
even responsive? At the very least this should be an arch callback such
that it can use NMIs where available.

Also, if this is a 'requirement' for kexec or the like, this shouldn't
be a command line argument, but something that's set-up by kexec itself
for functional reasons.

> +	panic_force_cpu=
> +			[KNL,SMP] Force panic handling to execute on a specific CPU.
> +			Format: <cpu number>
> +			Some platforms require panic handling to occur on a
> +			specific CPU for the crash kernel to function correctly.
> +			This can be due to firmware limitations, interrupt routing
> +			constraints, or platform-specific requirements where only
> +			a particular CPU can safely enter the crash kernel.
> +			When set, panic() will redirect execution to the specified
> +			CPU before proceeding with the normal panic and kexec flow.
> +			If the target CPU is offline or unavailable, panic proceeds
> +			on the current CPU.

It this stays; it should have a warning that it makes the panic less reliable.
Re: [PATCH v4] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
Posted by Steven Rostedt 1 month ago
On Thu, 8 Jan 2026 08:48:57 +0100
Peter Zijlstra <peterz@infradead.org> wrote:

> > +	panic_force_cpu=
> > +			[KNL,SMP] Force panic handling to execute on a specific CPU.
> > +			Format: <cpu number>
> > +			Some platforms require panic handling to occur on a
> > +			specific CPU for the crash kernel to function correctly.
> > +			This can be due to firmware limitations, interrupt routing
> > +			constraints, or platform-specific requirements where only
> > +			a particular CPU can safely enter the crash kernel.
> > +			When set, panic() will redirect execution to the specified
> > +			CPU before proceeding with the normal panic and kexec flow.
> > +			If the target CPU is offline or unavailable, panic proceeds
> > +			on the current CPU.  
> 
> It this stays; it should have a warning that it makes the panic less reliable.

Agreed. It should probably end with:

              This option should only be used for systems with the above
              constraints as it will cause the panic operation to be less
              reliable.

-- Steve
Re: [PATCH v4] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
Posted by Baoquan He 1 month ago
On 01/07/26 at 11:56pm, Pnina Feder wrote:
> Some platforms require panic handling to execute on a specific CPU for
> crash dump to work reliably. This can be due to firmware limitations,

Thanks for fixing this. Could you kindly reveal which platform this
issue is from?

> interrupt routing constraints, or platform-specific requirements where
> only a single CPU is able to safely enter the crash kernel.
> 
> Add the panic_force_cpu= kernel command-line parameter to redirect panic
> execution to a designated CPU. When the parameter is provided, the CPU
> that initially triggers panic forwards the panic context to the target
> CPU via IPI, which then proceeds with the normal panic and kexec flow.
> 
> If the specified CPU is invalid, offline, or a panic is already in
> progress on another CPU, the redirection is skipped and panic continues
> on the current CPU.

What if both the original CPU and specified CPU are not able to function
well on panic jumping? The crash dumping will fail in this case?

> 
> Changes since v3:
>  - Dump original CPU's stack before redirecting to preserve debug info
>  - Add Documentation/admin-guide/kernel-parameters.txt entry
>  - Use smp_call_function_single_async() to avoid blocking in csd_lock()
>  - Add CONFIG_CRASH_DUMP dependency
>  - Reuse vpanic()'s static buffer instead of separate allocation
>  - Remove verbose warning messages
> 
> Signed-off-by: Pnina Feder <pnina.feder@mobileye.com>
> ---
>  .../admin-guide/kernel-parameters.txt         |  13 +++
>  kernel/panic.c                                | 104 ++++++++++++++++++
>  2 files changed, 117 insertions(+)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index a8d0afde7f85..561ce09a6ae1 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -4753,6 +4753,19 @@ Kernel parameters
>  	panic_on_warn=1	panic() instead of WARN().  Useful to cause kdump
>  			on a WARN().
>  
> +	panic_force_cpu=
> +			[KNL,SMP] Force panic handling to execute on a specific CPU.
> +			Format: <cpu number>
> +			Some platforms require panic handling to occur on a
> +			specific CPU for the crash kernel to function correctly.
> +			This can be due to firmware limitations, interrupt routing
> +			constraints, or platform-specific requirements where only
> +			a particular CPU can safely enter the crash kernel.
> +			When set, panic() will redirect execution to the specified
> +			CPU before proceeding with the normal panic and kexec flow.
> +			If the target CPU is offline or unavailable, panic proceeds
> +			on the current CPU.
> +
>  	panic_print=	Bitmask for printing system info when panic happens.
>  			User can chose combination of the following bits:
>  			bit 0: print all tasks info
> diff --git a/kernel/panic.c b/kernel/panic.c
> index 0d52210a9e2b..414ef60d2306 100644
> --- a/kernel/panic.c
> +++ b/kernel/panic.c
> @@ -300,6 +300,103 @@ void __weak crash_smp_send_stop(void)
>  
>  atomic_t panic_cpu = ATOMIC_INIT(PANIC_CPU_INVALID);
>  
> +#if defined(CONFIG_SMP) && defined(CONFIG_CRASH_DUMP)
> +/* CPU to redirect panic to, or -1 if disabled */
> +static int panic_force_cpu = -1;
> +static call_single_data_t panic_csd;
> +
> +static int __init panic_force_cpu_setup(char *str)
> +{
> +	int cpu;
> +
> +	if (!str)
> +		return -EINVAL;
> +
> +	if (kstrtoint(str, 0, &cpu) || cpu < 0) {
> +		pr_warn("panic_force_cpu: invalid value '%s'\n", str);
> +		return -EINVAL;
> +	}
> +
> +	panic_force_cpu = cpu;
> +	return 0;
> +}
> +early_param("panic_force_cpu", panic_force_cpu_setup);
> +
> +static void do_panic_on_target_cpu(void *info)
> +{
> +	panic("%s", (char *)info);
> +}
> +
> +/**
> + * panic_force_target_cpu - Redirect panic to a specific CPU for crash kernel
> + * @fmt: panic message format string
> + * @args: arguments for format string
> + *
> + * Some platforms require panic handling to occur on a specific CPU
> + * for the crash kernel to function correctly. This function redirects
> + * panic handling to the CPU specified via the panic_redirect_cpu= boot parameter.
> + *
> + * Returns true if panic should proceed on current CPU.
> + * Returns false (never returns) if panic was redirected.
> + */
> +__printf(3, 0)
> +static bool panic_force_target_cpu(char *buf, int buf_size, const char *fmt, va_list args)
> +{
> +	int cpu = raw_smp_processor_id();
> +	int target_cpu = panic_force_cpu;
> +
> +	/* Feature not enabled via boot parameter */
> +	if (target_cpu < 0)
> +		return true;
> +
> +	/* Already on target CPU - proceed normally */
> +	if (cpu == target_cpu)
> +		return true;
> +
> +	/* Target CPU is offline, can't redirect */
> +	if (!cpu_online(target_cpu))
> +		return true;
> +
> +	/* Another panic already in progress */
> +	if (panic_in_progress())
> +		return true;
> +
> +	vsnprintf(buf, buf_size, fmt, args);
> +
> +	console_verbose();
> +	bust_spinlocks(1);
> +
> +	pr_emerg("panic: Redirecting from CPU %d to CPU %d for crash kernel\n",
> +		cpu, target_cpu);
> +
> +	/* Dump original CPU's stack before redirecting */
> +	if (test_taint(TAINT_DIE) || oops_in_progress > 1) {
> +		panic_this_cpu_backtrace_printed = true;
> +	} else if (IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE)) {
> +		dump_stack();
> +		panic_this_cpu_backtrace_printed = true;
> +	}
> +
> +	printk_legacy_allow_panic_sync();
> +	console_flush_on_panic(CONSOLE_FLUSH_PENDING);
> +
> +	panic_csd.func = do_panic_on_target_cpu;
> +	panic_csd.info = buf;
> +
> +	/* Use smp_call_function_single_async() to avoid blocking in csd_lock(). */
> +	if (smp_call_function_single_async(target_cpu, &panic_csd) != 0)
> +		return true;
> +
> +	return false;
> +}
> +#else
> +__printf(3, 0)
> +static inline bool panic_force_target_cpu(char *buf, int buf_size, const char *fmt, va_list args)
> +{
> +	return true;
> +}
> +#endif /* CONFIG_SMP && CONFIG CRASH_DUMP */
> +
>  bool panic_try_start(void)
>  {
>  	int old_cpu, this_cpu;
> @@ -451,6 +548,13 @@ void vpanic(const char *fmt, va_list args)
>  	local_irq_disable();
>  	preempt_disable_notrace();
>  
> +	/*
> +	 * Redirect panic to target CPU if configured via panic_force_cpu=.
> +	 * Returns false and never returns if panic was redirected.
> +	 */
> +	if (!panic_force_target_cpu(buf, sizeof(buf), fmt, args))
> +		panic_smp_self_stop();
> +
>  	/*
>  	 * It's possible to come here directly from a panic-assertion and
>  	 * not have preempt disabled. Some functions called from here want
> -- 
> 2.43.0
>
Re: [PATCH v4] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
Posted by Peter Zijlstra 1 month ago
On Thu, Jan 08, 2026 at 11:11:50AM +0800, Baoquan He wrote:
> On 01/07/26 at 11:56pm, Pnina Feder wrote:
> > Some platforms require panic handling to execute on a specific CPU for
> > crash dump to work reliably. This can be due to firmware limitations,
> 
> Thanks for fixing this. Could you kindly reveal which platform this
> issue is from?
> 
> > interrupt routing constraints, or platform-specific requirements where
> > only a single CPU is able to safely enter the crash kernel.
> > 
> > Add the panic_force_cpu= kernel command-line parameter to redirect panic
> > execution to a designated CPU. When the parameter is provided, the CPU
> > that initially triggers panic forwards the panic context to the target
> > CPU via IPI, which then proceeds with the normal panic and kexec flow.
> > 
> > If the specified CPU is invalid, offline, or a panic is already in
> > progress on another CPU, the redirection is skipped and panic continues
> > on the current CPU.
> 
> What if both the original CPU and specified CPU are not able to function
> well on panic jumping? The crash dumping will fail in this case?

Yes.
Re: [PATCH v4] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU
Posted by Andrew Morton 1 month ago
On Wed,  7 Jan 2026 23:56:59 +0200 Pnina Feder <pnina.feder@mobileye.com> wrote:

> Some platforms require panic handling to execute on a specific CPU for
> crash dump to work reliably. This can be due to firmware limitations,
> interrupt routing constraints, or platform-specific requirements where
> only a single CPU is able to safely enter the crash kernel.
> 
> Add the panic_force_cpu= kernel command-line parameter to redirect panic
> execution to a designated CPU. When the parameter is provided, the CPU
> that initially triggers panic forwards the panic context to the target
> CPU via IPI, which then proceeds with the normal panic and kexec flow.
> 
> If the specified CPU is invalid, offline, or a panic is already in
> progress on another CPU, the redirection is skipped and panic continues
> on the current CPU.
> 
> Changes since v3:
>  - Dump original CPU's stack before redirecting to preserve debug info
>  - Add Documentation/admin-guide/kernel-parameters.txt entry
>  - Use smp_call_function_single_async() to avoid blocking in csd_lock()
>  - Add CONFIG_CRASH_DUMP dependency
>  - Reuse vpanic()'s static buffer instead of separate allocation
>  - Remove verbose warning messages

Looking nice to my eye.

> +#if defined(CONFIG_SMP) && defined(CONFIG_CRASH_DUMP)

Congrats on caring about uniprocessor ;)

> +/* CPU to redirect panic to, or -1 if disabled */
> +static int panic_force_cpu = -1;
> +static call_single_data_t panic_csd;
> +
> +static int __init panic_force_cpu_setup(char *str)
> +{
> +	int cpu;
> +
> +	if (!str)
> +		return -EINVAL;
> +
> +	if (kstrtoint(str, 0, &cpu) || cpu < 0) {
> +		pr_warn("panic_force_cpu: invalid value '%s'\n", str);
> +		return -EINVAL;
> +	}
> +
> +	panic_force_cpu = cpu;
> +	return 0;
> +}
> +early_param("panic_force_cpu", panic_force_cpu_setup);
> +
> +static void do_panic_on_target_cpu(void *info)
> +{
> +	panic("%s", (char *)info);

Probably the (char *) cast isn't needed?

> +}
> +
> +/**
> + * panic_force_target_cpu - Redirect panic to a specific CPU for crash kernel
> + * @fmt: panic message format string
> + * @args: arguments for format string

`make htmldocs' is going to get upset about missing docs for `buf' and
`buf_size'?

> + * Some platforms require panic handling to occur on a specific CPU
> + * for the crash kernel to function correctly. This function redirects
> + * panic handling to the CPU specified via the panic_redirect_cpu= boot parameter.
> + *
> + * Returns true if panic should proceed on current CPU.
> + * Returns false (never returns) if panic was redirected.
> + */
> +__printf(3, 0)
> +static bool panic_force_target_cpu(char *buf, int buf_size, const char *fmt, va_list args)