[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251230-kho-v1-1-4d795a24da9e@debian.org>
Date: Tue, 30 Dec 2025 06:13:23 -0800
From: Breno Leitao <leitao@...ian.org>
To: Alexander Graf <graf@...zon.com>, Mike Rapoport <rppt@...nel.org>,
Pasha Tatashin <pasha.tatashin@...een.com>,
Pratyush Yadav <pratyush@...nel.org>
Cc: linux-kernel@...r.kernel.org, kexec@...ts.infradead.org,
linux-mm@...ck.org, usamaarif642@...il.com, rmikey@...a.com, clm@...com,
riel@...riel.com, kernel-team@...a.com, Breno Leitao <leitao@...ian.org>
Subject: [PATCH RFC] kexec: add option to print previous kernel release
after kexec
Introduce a new Kconfig option, CONFIG_KEXEC_SHOW_PREVIOUS_RELEASE,
which enables the storage and display of the previous kernel's release
version across kexec boots when using Kexec Handover (KHO).
Motivation
==========
Kernel bugs that depend on the version of the previously running kernel
are not uncommon, especially in scenarios where a buggy kernel kexecs
into a new one and the issue only manifests in the subsequent kernel.
Recent examples include:
* eb2266312507 ("x86/boot: Fix page table access in 5-level to 4-level paging transition")
* 77d48d39e991 ("efistub/tpm: Use ACPI reclaim memory for event log to avoid corruption")
* 64b45dd46e15 ("x86/efi: skip memattr table on kexec boot")
As kexec-based reboots become more widespread among Linux users, these
issues are becoming increasingly prominent.
When such crashes occur, correlating them to the previous kernel version
is challenging, especially at scale, where the problem may only appear in
specific cases and it is hard to correlate.
With the introduction of Kexec Handover (KHO), we now have a reliable
mechanism to pass information between kernels. This presents an
opportunity to address the problem by carrying the previous kernel's
release version to the next kernel and printing it at boot time.
Implementation Details
======================
The feature is controlled by a new Kconfig option,
CONFIG_KEXEC_SHOW_PREVIOUS_RELEASE.
When enabled, the previous kernel's release version is stored and
printed during boot after a kexec. The option is disabled by default to
avoid unnecessary overhead for users who do not require this
information.
Signed-off-by: Breno Leitao <leitao@...ian.org>
---
kernel/Kconfig.kexec | 13 +++++++++++++
kernel/liveupdate/kexec_handover.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+)
diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec
index 15632358bcf7..9f2a669e13aa 100644
--- a/kernel/Kconfig.kexec
+++ b/kernel/Kconfig.kexec
@@ -94,6 +94,19 @@ config KEXEC_JUMP
Jump between original kernel and kexeced kernel and invoke
code in physical address mode via KEXEC
+config KEXEC_SHOW_PREVIOUS_RELEASE
+ bool "Print previous kernel version on kexec boot"
+ depends on KEXEC_HANDOVER
+ help
+ When enabled, the kernel will store its release version in the
+ KHO FDT before kexec, and the newly booted kernel will read and
+ print this information during early boot.
+
+ This is useful for debugging and auditing to know which kernel
+ version performed the kexec that booted the current kernel.
+
+ If unsure, say N.
+
config CRASH_DUMP
bool "kernel crash dumps"
default ARCH_DEFAULT_CRASH_DUMP
diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index 73da00aeaa99..9e90c8445864 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -21,6 +21,7 @@
#include <linux/page-isolation.h>
#include <linux/unaligned.h>
#include <linux/vmalloc.h>
+#include <linux/utsname.h>
#include <asm/early_ioremap.h>
@@ -36,6 +37,7 @@
#define KHO_FDT_COMPATIBLE "kho-v1"
#define PROP_PRESERVED_MEMORY_MAP "preserved-memory-map"
#define PROP_SUB_FDT "fdt"
+#define PROP_PREVIOUS_RELEASE "previous-release"
#define KHO_PAGE_MAGIC 0x4b484f50U /* ASCII for 'KHOP' */
@@ -1253,6 +1255,9 @@ bool kho_finalized(void)
struct kho_in {
phys_addr_t fdt_phys;
phys_addr_t scratch_phys;
+#ifdef CONFIG_KEXEC_SHOW_PREVIOUS_RELEASE
+ char previous_release[__NEW_UTS_LEN + 1];
+#endif
struct kho_debugfs dbg;
};
@@ -1332,6 +1337,10 @@ static __init int kho_out_fdt_setup(void)
err |= fdt_property_string(root, "compatible", KHO_FDT_COMPATIBLE);
err |= fdt_property(root, PROP_PRESERVED_MEMORY_MAP, &empty_mem_map,
sizeof(empty_mem_map));
+#ifdef CONFIG_KEXEC_SHOW_PREVIOUS_RELEASE
+ err |= fdt_property_string(root, PROP_PREVIOUS_RELEASE,
+ init_uts_ns.name.release);
+#endif
err |= fdt_end_node(root);
err |= fdt_finish(root);
@@ -1455,6 +1464,25 @@ void __init kho_memory_init(void)
}
}
+#ifdef CONFIG_KEXEC_SHOW_PREVIOUS_RELEASE
+static void __init kho_print_previous_kernel(const void *fdt)
+{
+ const char *prev_release;
+ int len;
+
+ prev_release = fdt_getprop(fdt, 0, PROP_PREVIOUS_RELEASE, &len);
+ if (!prev_release || len <= 0)
+ return;
+
+ strscpy(kho_in.previous_release, prev_release,
+ sizeof(kho_in.previous_release));
+ pr_info("This kernel was kexec'ed from kernel release: %s\n",
+ kho_in.previous_release);
+}
+#else
+static void __init kho_print_previous_kernel(const void *fdt) { }
+#endif
+
void __init kho_populate(phys_addr_t fdt_phys, u64 fdt_len,
phys_addr_t scratch_phys, u64 scratch_len)
{
@@ -1526,6 +1554,8 @@ void __init kho_populate(phys_addr_t fdt_phys, u64 fdt_len,
kho_in.fdt_phys = fdt_phys;
kho_in.scratch_phys = scratch_phys;
kho_scratch_cnt = scratch_cnt;
+
+ kho_print_previous_kernel(fdt);
pr_info("found kexec handover data.\n");
out:
---
base-commit: 7620f9ccfabbdaf07620381264d8b8d91412542f
change-id: 20251230-kho-7707e8a2ef1e
Best regards,
--
Breno Leitao <leitao@...ian.org>
Powered by blists - more mailing lists