From nobody Sun Feb 8 17:04:25 2026 Received: from esa3.hc555-34.eu.iphmx.com (esa3.hc555-34.eu.iphmx.com [207.54.77.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4AE5C2222C0 for ; Sun, 11 Jan 2026 12:37:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=207.54.77.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768135031; cv=none; b=T/iUn3Wh8JSxgY6cx5uUwBDD3iBkQaOaSk3k1T3tYv5IrGDDBnlHAVafuDTln20TiYNtELBSzIUfgxD/PEqA+Z0/KMdxn55ilOI8uv7ZhXiSlZgywXCi/fUVq4k9VNjAN5AsVgA6SljKEbAVAqoat1WQVSwTCBD2/Xp13sTFT1w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768135031; c=relaxed/simple; bh=+KtCIe8G/3ldcVPdKyoQpkntR8plyfwgTSgSNvyaBSo=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=cekC4iGOP6GrKOymBQTXoeCpgDwDYnOrK3FjaRvLxaUF0g9jplZKnJ3zq0d52CMV4IL/NKxcFUFdDY+8YVgC7OrpfAKYrZpB/3UzkvrDa8fo/x3TDcGP5Wqpw3k9F1WXF2k3ha5EJInWUbo+PjZehYlc0c/qXTZXRqsK59yIj+8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mobileye.com; spf=pass smtp.mailfrom=mobileye.com; dkim=fail (0-bit key) header.d=mobileye.com header.i=@mobileye.com header.b=VLJm9feH reason="key not found in DNS"; arc=none smtp.client-ip=207.54.77.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mobileye.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mobileye.com Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=mobileye.com header.i=@mobileye.com header.b="VLJm9feH" DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=mobileye.com; i=@mobileye.com; q=dns/txt; s=MoEyIP; t=1768135027; x=1799671027; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=+KtCIe8G/3ldcVPdKyoQpkntR8plyfwgTSgSNvyaBSo=; b=VLJm9feHZ1+Eq1EAKsujkLwPgi7bBInRa7uze+nJPr/LeH88wH9mH5Nt Gzd19t6sAwcZnBW6vooHjNPwAU3gUXdnIjAW547m8LvCG0H4JH2KmZYEV hM798KXCy0Tb1MW6dfRk4HBCKoaJp/Ms22XZNm7ECHsULYGfXWHMdYMA5 0lqcX4TyD7dloMW1y4qg59Se/MCLPL3kRcCAjbb+0HeecZWZE5LhmXNMq Gs04Ko0uVjPOAsDIltZIGJcNwzMyaeBBPRjEDQup37m367Si0bSi9a5me V4LvUKGQYPng11p/AYj77LXLfhvvjbe6Crg6jVeDkSgBL8+YRVDJALzdv g==; X-CSE-ConnectionGUID: 0pdJxwpaQGOH3On2xHlyMw== X-CSE-MsgGUID: xRoGe3AySH2n2U5Y7nDU9w== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from unknown (HELO ces04_data.me-crop.lan) ([146.255.191.134]) by esa3.hc555-34.eu.iphmx.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jan 2026 14:37:00 +0200 X-CSE-ConnectionGUID: D1Lmwsa2Qyubvt/NsFwgHw== X-CSE-MsgGUID: 3R9P26QvSDuDXdvY00VJDA== Received: from unknown (HELO epgd034.me-corp.lan) ([10.154.54.6]) by ces04_data.me-crop.lan with SMTP; 11 Jan 2026 14:38:40 +0200 Received: by epgd034.me-corp.lan (sSMTP sendmail emulation); Sun, 11 Jan 2026 14:36:58 +0200 From: Pnina Feder To: akpm@linux-foundation.org Cc: pmladek@suse.com, bhe@redhat.com, linux-kernel@vger.kernel.org, lkp@intel.com, mgorman@suse.de, mingo@redhat.com, peterz@infradead.org, pnina.feder@mobileye.com, rostedt@goodmis.org, senozhatsky@chromium.org, tglx@linutronix.de, vkondra@mobileye.com Subject: [PATCH v6] panic: add panic_force_cpu= parameter to redirect panic to a specific CPU Date: Sun, 11 Jan 2026 14:36:56 +0200 Message-ID: <20260111123656.1563887-1-pnina.feder@mobileye.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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=3D 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 deliver= y. 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. Signed-off-by: Pnina Feder --- Changes since v5: - Restore (char *) cast in do_panic_on_target_cpu() to fix -Wformat warning - link to v5: https://lore.kernel.org/all/20260108203612.955769-1-pnina.fe= der@mobileye.com/ Changes sinse 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 functio= ns - Add warning to documentation about reduced reliability - Address review comments from Andrew Morton (remove unnecessary cast, add missing kernel-doc parameters) - link to v4: https://lore.kernel.org/all/20260107215659.3619730-1-pnina.f= eder@mobileye.com/ 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 - link to v3: https://lore.kernel.org/all/20260105081808.1771473-1-pnina.f= eder@mobileye.com/ Changes since v2: - Make panic redirection warnings generic and platform-agnostic - link to v2: https://lore.kernel.org/all/20260104204210.2418049-1-pnina.f= eder@mobileye.com/ Changes since v1: - Replace Kconfig option with a kernel command-line parameter - Fix clang format warning reported by kernel test robot - link to v1: https://lore.kernel.org/all/20260101123237.277411-1-pnina.fe= der@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/Documentatio= n/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=3D1 panic() instead of WARN(). Useful to cause kdump on a WARN(). =20 + panic_force_cpu=3D + [KNL,SMP] Force panic handling to execute on a specific CPU. + Format: + 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=3D 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_d= ata_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); =20 /* * Call a function on all processors diff --git a/kernel/panic.c b/kernel/panic.c index 0d52210a9e2b..ef247df06265 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -300,6 +300,121 @@ void __weak crash_smp_send_stop(void) =20 atomic_t panic_cpu =3D ATOMIC_INIT(PANIC_CPU_INVALID); =20 +#if defined(CONFIG_SMP) && defined(CONFIG_CRASH_DUMP) +/* CPU to redirect panic to, or -1 if disabled */ +static int panic_force_cpu =3D -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 =3D 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_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 =3D do_panic_on_target_cpu; + panic_csd.info =3D msg; + + return smp_call_function_single_async(target_cpu, &panic_csd); +} + +/** + * panic_force_target_cpu - Redirect panic to a specific CPU for crash ker= nel + * @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=3D 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 *fm= t, va_list args) +{ + int cpu =3D raw_smp_processor_id(); + int target_cpu =3D panic_force_cpu; + + /* Feature not enabled via boot parameter */ + if (target_cpu < 0) + return true; + + /* Already on target CPU - proceed normally */ + if (cpu =3D=3D 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 =3D true; + } else if (IS_ENABLED(CONFIG_DEBUG_BUGVERBOSE)) { + dump_stack(); + panic_this_cpu_backtrace_printed =3D true; + } + + printk_legacy_allow_panic_sync(); + console_flush_on_panic(CONSOLE_FLUSH_PENDING); + + if (panic_smp_redirect_cpu(target_cpu, buf) !=3D 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 c= har *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(); =20 + /* + * Redirect panic to target CPU if configured via panic_force_cpu=3D. + * 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 --=20 2.43.0