From: George Guo <dongtai.guo@linux.dev>
To: rppt@kernel.org, pasha.tatashin@soleen.com, pratyush@kernel.org,
chenhuacai@kernel.org, ardb@kernel.org, shuah@kernel.org
Cc: ilias.apalodimas@linaro.org, akpm@linux-foundation.org,
baoquan.he@linux.dev, ruirui.yang@linux.dev,
guodongtai@kylinos.cn, kernel@xen0n.name, graf@amazon.com,
liukexin@kylinos.cn, loongarch@lists.linux.dev,
linux-kernel@vger.kernel.org, kexec@lists.infradead.org,
linux-mm@kvack.org, linux-kselftest@vger.kernel.org,
linux-efi@vger.kernel.org
Subject: [PATCH v6 2/8] kho: Write KHO state to the EFI table at kexec time
Date: Fri, 30 Oct 2026 02:29:49 +0900 [thread overview]
Message-ID: <20261029172956.20791-3-dongtai.guo@linux.dev> (raw)
In-Reply-To: <20261029172956.20791-1-dongtai.guo@linux.dev>
From: George Guo <guodongtai@kylinos.cn>
On arm64 and riscv, KHO addresses and sizes are passed through /chosen
properties in the boot FDT prepared for each kexec image. On x86, they
are passed through a SETUP_KEXEC_KHO record linked from the image's boot
parameters. These records are per-image, unlike the shared EFI table.
The EFI table is shared. A KHO-enabled normal image and a crash image
can both be loaded, but need different contents: the normal image needs
the KHO addresses, while the crash image needs an empty table. Updating
the table at load time cannot satisfy both.
Write the table in kernel_kexec() and __crash_kexec(), once the image
that will run is known. kho_update_efi_table() fills the table from that
image, or zeroes it if the image has no KHO state, including images
loaded with kexec_load().
Clear the table even with CONFIG_KEXEC_HANDOVER disabled, since the
kernel may have inherited a populated table. This prevents a later
kernel from trying to revive obsolete KHO state.
The table stores the size of the bootmem area list (bufsz), not of its
page-aligned segment, as the FDT and x86 code do. If updating or clearing
the table fails, kernel_kexec() returns before liveupdate_reboot(), so
LUO does not save state that the next kernel would not find.
__crash_kexec() ignores the error so the crash boot can still proceed.
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
kernel/crash_core.c | 6 ++++++
kernel/kexec_core.c | 5 +++++
kernel/kexec_internal.h | 8 ++++++++
kernel/liveupdate/kexec_handover.c | 26 ++++++++++++++++++++++++++
4 files changed, 45 insertions(+)
diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index 2b36aa9fade0..0f77adc0928b 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -138,6 +138,12 @@ void __noclone __crash_kexec(struct pt_regs *regs)
if (kexec_crash_image) {
struct pt_regs fixed_regs;
+ /*
+ * A crash image has no KHO state. Zero the EFI
+ * table so the crash kernel has no inherited KHO state.
+ */
+ (void)kho_update_efi_table(kexec_crash_image);
+
crash_setup_regs(&fixed_regs, regs);
crash_save_vmcoreinfo();
machine_crash_shutdown(&fixed_regs);
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index dc770b9a6d05..37597091770a 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -1146,6 +1146,11 @@ int kernel_kexec(void)
goto Unlock;
}
+ /* Write this image's KHO state into the EFI table. */
+ error = kho_update_efi_table(kexec_image);
+ if (error)
+ goto Unlock;
+
if (!kexec_image->preserve_context) {
error = liveupdate_reboot();
if (error)
diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h
index 228bb88c018b..cfdd0b158f72 100644
--- a/kernel/kexec_internal.h
+++ b/kernel/kexec_internal.h
@@ -2,6 +2,7 @@
#ifndef LINUX_KEXEC_INTERNAL_H
#define LINUX_KEXEC_INTERNAL_H
+#include <linux/efi.h>
#include <linux/kexec.h>
struct kexec_segment;
@@ -46,6 +47,7 @@ struct kexec_buf;
int kho_locate_mem_hole(struct kexec_buf *kbuf,
int (*func)(struct resource *, void *));
int kho_fill_kimage(struct kimage *image);
+int kho_update_efi_table(struct kimage *image);
#else
static inline int kho_locate_mem_hole(struct kexec_buf *kbuf,
int (*func)(struct resource *, void *))
@@ -54,5 +56,11 @@ static inline int kho_locate_mem_hole(struct kexec_buf *kbuf,
}
static inline int kho_fill_kimage(struct kimage *image) { return 0; }
+
+static inline int kho_update_efi_table(struct kimage *image)
+{
+ /* The previous kernel may have left KHO state in the EFI table. */
+ return efi_kho_update(0, 0, 0, 0);
+}
#endif /* CONFIG_KEXEC_HANDOVER */
#endif /* LINUX_KEXEC_INTERNAL_H */
diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index 9a53d7750367..74c4633f5afc 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -15,6 +15,7 @@
#include <linux/crash_dump.h>
#include <linux/kmemleak.h>
#include <linux/count_zeros.h>
+#include <linux/efi.h>
#include <linux/kasan.h>
#include <linux/kexec.h>
#include <linux/kexec_handover.h>
@@ -2094,6 +2095,31 @@ int kho_fill_kimage(struct kimage *image)
return 0;
}
+/*
+ * Write the KHO state of @image into the EFI table, or zero the table if
+ * @image has none.
+ *
+ * There is one table, but the normal and the crash image can both be loaded,
+ * so the table is written just before @image runs rather than at load time.
+ * Crash images, images loaded with kexec_load() and images loaded with KHO
+ * disabled have no KHO state. Zeroing the table for them makes the next
+ * kernel boot without inherited KHO state instead of reading stale addresses.
+ */
+int kho_update_efi_table(struct kimage *image)
+{
+ int err;
+
+ if (!image->kho.fdt || !image->kho.bootmem)
+ return efi_kho_update(0, 0, 0, 0);
+
+ err = efi_kho_update(image->kho.fdt, PAGE_SIZE,
+ image->kho.bootmem->mem, image->kho.bootmem->bufsz);
+ if (err)
+ pr_warn("failed to update EFI config table: %pe\n", ERR_PTR(err));
+
+ return err;
+}
+
static int kho_walk_bootmem(struct kexec_buf *kbuf,
int (*func)(struct resource *, void *))
{
--
2.53.0
next prev parent reply other threads:[~2026-10-29 17:30 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-29 17:29 [PATCH v6 0/8] LoongArch: Add KHO support and selftests George Guo
2026-10-29 17:29 ` [PATCH v6 1/8] efi: Pass KHO state to the next kernel in a configuration table George Guo
2026-10-29 19:28 ` Ard Biesheuvel
2026-10-29 19:42 ` Pratyush Yadav
2026-10-29 17:29 ` George Guo [this message]
2026-10-29 17:29 ` [PATCH v6 3/8] kho: Include linux/mm.h in kho_block.c George Guo
2026-10-29 17:29 ` [PATCH v6 4/8] kho: Add kho_disable() George Guo
2026-10-29 17:29 ` [PATCH v6 5/8] LoongArch: Allow memblock arrays to resize George Guo
2026-10-29 17:29 ` [PATCH v6 6/8] LoongArch: Enable kexec handover (KHO) George Guo
2026-10-29 17:29 ` [PATCH v6 7/8] selftests/kho: Add LoongArch vmtest support George Guo
2026-10-29 17:29 ` [PATCH v6 8/8] selftests/liveupdate: " George Guo
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=20261029172956.20791-3-dongtai.guo@linux.dev \
--to=dongtai.guo@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=ardb@kernel.org \
--cc=baoquan.he@linux.dev \
--cc=chenhuacai@kernel.org \
--cc=graf@amazon.com \
--cc=guodongtai@kylinos.cn \
--cc=ilias.apalodimas@linaro.org \
--cc=kernel@xen0n.name \
--cc=kexec@lists.infradead.org \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=liukexin@kylinos.cn \
--cc=loongarch@lists.linux.dev \
--cc=pasha.tatashin@soleen.com \
--cc=pratyush@kernel.org \
--cc=rppt@kernel.org \
--cc=ruirui.yang@linux.dev \
--cc=shuah@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®