The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Bradley Morgan <include@grrlz.net>
To: akpm@linux-foundation.org
Cc: baoquan.he@linux.dev, pmladek@suse.com,
	feng.tang@linux.alibaba.com, gregkh@linuxfoundation.org,
	arnd@arndb.de, corbet@lwn.net, rdunlap@infradead.org,
	gpiccoli@igalia.com, kexec@lists.infradead.org,
	linux-kernel@vger.kernel.org, include@grrlz.net
Subject: [RFC PATCH 1/4] panic: add a pre kdump notifier list
Date: Sat, 11 Jul 2026 00:22:50 +0000	[thread overview]
Message-ID: <20260711002253.1115-2-include@grrlz.net> (raw)
In-Reply-To: <20260711002253.1115-1-include@grrlz.net>

When a crash kernel is loaded, panic() jumps to it before the panic
notifiers run. A hypervisor or firmware therefore never learns that
the guest panicked: the Hyper-V host never receives the crash
registers, a Google gsmi firmware log entry is dropped, a pvpanic
device never signals the host, and an AMD SEV-SNP guest skips the
firmware and IOMMU shutdown. Fleet alerting, availability tracking,
and crash logging all miss the event.

The only escape hatch today is crash_kexec_post_notifiers, but it runs
the entire legacy notifier list before the kdump. That list carries
slow callbacks, IPMI being the obvious one because it talks to a BMC,
so enabling it delays every crash dump on the machine. Hyper-V forces
it on anyway and penalizes every kdump for the sake of one upcall;
this series also removes the forcing that SEV-SNP added for the same
reason, giving SNP hosts the normal early crash kexec back.

Add a small dedicated list that always runs before crash kexec. The
list head stays private and registration goes through a function,
because the callbacks on this list have a strict contract and an API
is how you enforce one. The list lives in its own file, not in panic.c,
so the contract can carry a MAINTAINERS entry and the existing panic
code does not have to move.

Priorities order the list like any atomic notifier chain. The header
documents that they are reserved for callbacks that must run last, for
example because they may not return or because they tear down a
transport that other callbacks still need.

The notify path walks the chain by hand and names each callback on the
console before invoking it. Running anything before the crash kexec is
a reliability trade, if an upcall hangs or faults and costs us the
crash dump, the console identifies the culprit instead of leaving a
machine that silently never rebooted into the kdump kernel. Callback
return values are deliberately ignored, and a nested panic resumes the
walk after the callback that was running instead of refaulting on it.

Signed-off-by: Bradley Morgan <include@grrlz.net>
---
 include/linux/panic_notifier.h | 18 ++++++++++
 kernel/Makefile                |  2 +-
 kernel/panic_notifiers.c       | 65 ++++++++++++++++++++++++++++++++++
 3 files changed, 84 insertions(+), 1 deletion(-)
 create mode 100644 kernel/panic_notifiers.c

diff --git a/include/linux/panic_notifier.h b/include/linux/panic_notifier.h
index 41e32483d7a7..1e99de3a8a6a 100644
--- a/include/linux/panic_notifier.h
+++ b/include/linux/panic_notifier.h
@@ -7,6 +7,24 @@
 
 extern struct atomic_notifier_head panic_notifier_list;
 
+/*
+ * The pre kdump list runs on every panic, before a potential crash
+ * kexec, so a hypervisor or firmware learns of the panic even when a
+ * crash kernel is loaded. A callback:
+ *
+ *  - must not take locks, allocate memory or sleep
+ *  - must not assume other CPUs have been stopped
+ *  - must tolerate being entered again if the panic path panics
+ *
+ * One that cannot belongs on the legacy panic_notifier_list instead.
+ * Reserve low priorities for callbacks that must run last, for
+ * example because they do not return. Return values are ignored: the
+ * whole list always runs.
+ */
+int panic_notifier_register_pre_kdump(struct notifier_block *nb);
+int panic_notifier_unregister_pre_kdump(struct notifier_block *nb);
+void panic_pre_kdump_notify(const char *buf);
+
 extern bool crash_kexec_post_notifiers;
 
 #endif	/* _LINUX_PANIC_NOTIFIERS_H */
diff --git a/kernel/Makefile b/kernel/Makefile
index 1e1a31673577..7add98a5acc2 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -3,7 +3,7 @@
 # Makefile for the linux kernel.
 #
 
-obj-y     = fork.o exec_domain.o exec_state.o panic.o \
+obj-y     = fork.o exec_domain.o exec_state.o panic.o panic_notifiers.o \
 	    cpu.o exit.o softirq.o resource.o \
 	    sysctl.o capability.o ptrace.o user.o \
 	    signal.o sys.o umh.o workqueue.o pid.o task_work.o \
diff --git a/kernel/panic_notifiers.c b/kernel/panic_notifiers.c
new file mode 100644
index 000000000000..31f15f84662e
--- /dev/null
+++ b/kernel/panic_notifiers.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* The pre kdump panic notifier list. See include/linux/panic_notifier.h. */
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#include <linux/panic_notifier.h>
+#include <linux/printk.h>
+#include <linux/rcupdate.h>
+
+static ATOMIC_NOTIFIER_HEAD(panic_pre_kdump_list);
+
+/* The callback must satisfy the contract in include/linux/panic_notifier.h. */
+int panic_notifier_register_pre_kdump(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&panic_pre_kdump_list, nb);
+}
+EXPORT_SYMBOL_GPL(panic_notifier_register_pre_kdump);
+
+/* Synchronizes RCU and may block; must not be called from the panic path. */
+int panic_notifier_unregister_pre_kdump(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&panic_pre_kdump_list, nb);
+}
+EXPORT_SYMBOL_GPL(panic_notifier_unregister_pre_kdump);
+
+/*
+ * Called from panic() only, right before a potential crash kexec. Callbacks
+ * are named on the console first and their return values ignored.
+ */
+void panic_pre_kdump_notify(const char *buf)
+{
+	static struct notifier_block *cursor;
+	struct notifier_block *nb, *resume_after;
+
+	/* No locking: panic_cpu serializes; a nested panic just runs again. */
+	resume_after = cursor;
+
+	rcu_read_lock();
+	for (nb = rcu_dereference(panic_pre_kdump_list.head); nb;
+	     nb = rcu_dereference(nb->next)) {
+		/*
+		 * On a nested panic, skip past the callback that was
+		 * running when it hit: that one is the likely culprit.
+		 */
+		if (resume_after) {
+			if (nb == resume_after)
+				resume_after = NULL;
+			continue;
+		}
+
+#ifdef CONFIG_DEBUG_NOTIFIERS
+		if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) {
+			WARN(1, "Invalid pre kdump notifier!");
+			continue;
+		}
+#endif
+		cursor = nb;
+		pr_emerg("pre kdump notifier: calling %ps\n",
+			 nb->notifier_call);
+		/* The zero action mirrors the legacy panic_notifier_list. */
+		nb->notifier_call(nb, 0, (void *)buf);
+	}
+	rcu_read_unlock();
+	cursor = NULL;
+}
-- 
2.53.0


  reply	other threads:[~2026-07-11  0:23 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-11  0:22 [RFC PATCH 0/4] panic: a pre kdump notifier list for hypervisor upcalls Bradley Morgan
2026-07-11  0:22 ` Bradley Morgan [this message]
2026-07-11  0:22 ` [RFC PATCH 2/4] panic: run the pre kdump list before crash kexec Bradley Morgan
2026-07-11  0:22 ` [RFC PATCH 3/4] misc/pvpanic: notify the host on the pre kdump list Bradley Morgan
2026-07-11  0:22 ` [RFC PATCH 4/4] MAINTAINERS: add an entry for the pre kdump notifier list Bradley Morgan

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=20260711002253.1115-2-include@grrlz.net \
    --to=include@grrlz.net \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=baoquan.he@linux.dev \
    --cc=corbet@lwn.net \
    --cc=feng.tang@linux.alibaba.com \
    --cc=gpiccoli@igalia.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=kexec@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pmladek@suse.com \
    --cc=rdunlap@infradead.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox