From: Changyuan Lyu <changyuanl@google.com>
To: linux-kernel@vger.kernel.org
Cc: akpm@linux-foundation.org, anthony.yznaga@oracle.com,
arnd@arndb.de, ashish.kalra@amd.com, benh@kernel.crashing.org,
bp@alien8.de, catalin.marinas@arm.com, corbet@lwn.net,
dave.hansen@linux.intel.com, devicetree@vger.kernel.org,
dwmw2@infradead.org, ebiederm@xmission.com, graf@amazon.com,
hpa@zytor.com, jgowans@amazon.com, kexec@lists.infradead.org,
krzk@kernel.org, linux-arm-kernel@lists.infradead.org,
linux-doc@vger.kernel.org, linux-mm@kvack.org, luto@kernel.org,
mark.rutland@arm.com, mingo@redhat.com,
pasha.tatashin@soleen.com, pbonzini@redhat.com,
peterz@infradead.org, ptyadav@amazon.de, robh@kernel.org,
rostedt@goodmis.org, rppt@kernel.org, saravanak@google.com,
skinsburskii@linux.microsoft.com, tglx@linutronix.de,
thomas.lendacky@amd.com, will@kernel.org, x86@kernel.org,
Changyuan Lyu <changyuanl@google.com>
Subject: [PATCH v6 07/14] kexec: add KHO support to kexec file loads
Date: Thu, 10 Apr 2025 22:37:38 -0700 [thread overview]
Message-ID: <20250411053745.1817356-8-changyuanl@google.com> (raw)
In-Reply-To: <20250411053745.1817356-1-changyuanl@google.com>
From: Alexander Graf <graf@amazon.com>
Kexec has 2 modes: A user space driven mode and a kernel driven mode.
For the kernel driven mode, kernel code determines the physical
addresses of all target buffers that the payload gets copied into.
With KHO, we can only safely copy payloads into the "scratch area".
Teach the kexec file loader about it, so it only allocates for that
area. In addition, enlighten it with support to ask the KHO subsystem
for its respective payloads to copy into target memory. Also teach the
KHO subsystem how to fill the images for file loads.
Signed-off-by: Alexander Graf <graf@amazon.com>
Co-developed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Co-developed-by: Changyuan Lyu <changyuanl@google.com>
Signed-off-by: Changyuan Lyu <changyuanl@google.com>
---
include/linux/kexec.h | 7 +++++
kernel/kexec_file.c | 13 ++++++++
kernel/kexec_handover.c | 67 +++++++++++++++++++++++++++++++++++++++++
kernel/kexec_internal.h | 16 ++++++++++
4 files changed, 103 insertions(+)
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index c8971861521a5..d3cad108b8076 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -371,6 +371,13 @@ struct kimage {
size_t ima_buffer_size;
#endif
+#ifdef CONFIG_KEXEC_HANDOVER
+ struct {
+ struct kexec_segment *scratch;
+ phys_addr_t fdt;
+ } kho;
+#endif
+
/* Core ELF header buffer */
void *elf_headers;
unsigned long elf_headers_sz;
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index fba686487e3b5..77758c5331229 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -253,6 +253,11 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
/* IMA needs to pass the measurement list to the next kernel. */
ima_add_kexec_buffer(image);
+ /* If KHO is active, add its images to the list */
+ ret = kho_fill_kimage(image);
+ if (ret)
+ goto out;
+
/* Call image load handler */
ldata = kexec_image_load_default(image);
@@ -648,6 +653,14 @@ int kexec_locate_mem_hole(struct kexec_buf *kbuf)
if (kbuf->mem != KEXEC_BUF_MEM_UNKNOWN)
return 0;
+ /*
+ * If KHO is active, only use KHO scratch memory. All other memory
+ * could potentially be handed over.
+ */
+ ret = kho_locate_mem_hole(kbuf, locate_mem_hole_callback);
+ if (ret <= 0)
+ return ret;
+
if (!IS_ENABLED(CONFIG_ARCH_KEEP_MEMBLOCK))
ret = kexec_walk_resources(kbuf, locate_mem_hole_callback);
else
diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
index a594da2a22912..4bbc6f5ef7230 100644
--- a/kernel/kexec_handover.c
+++ b/kernel/kexec_handover.c
@@ -23,6 +23,7 @@
* internal APIs.
*/
#include "../mm/internal.h"
+#include "kexec_internal.h"
#define KHO_FDT_COMPATIBLE "kho-v1"
#define PROP_PRESERVED_MEMORY_MAP "preserved-memory-map"
@@ -1184,3 +1185,69 @@ void __init kho_populate(phys_addr_t fdt_phys, u64 fdt_len,
if (err)
pr_warn("disabling KHO revival: %d\n", err);
}
+
+/* Helper functions for kexec_file_load */
+
+int kho_fill_kimage(struct kimage *image)
+{
+ ssize_t scratch_size;
+ int err = 0;
+ struct kexec_buf scratch;
+
+ if (!kho_enable)
+ return 0;
+
+ image->kho.fdt = page_to_phys(kho_out.ser.fdt);
+
+ scratch_size = sizeof(*kho_scratch) * kho_scratch_cnt;
+ scratch = (struct kexec_buf){
+ .image = image,
+ .buffer = kho_scratch,
+ .bufsz = scratch_size,
+ .mem = KEXEC_BUF_MEM_UNKNOWN,
+ .memsz = scratch_size,
+ .buf_align = SZ_64K, /* Makes it easier to map */
+ .buf_max = ULONG_MAX,
+ .top_down = true,
+ };
+ err = kexec_add_buffer(&scratch);
+ if (err)
+ return err;
+ image->kho.scratch = &image->segment[image->nr_segments - 1];
+
+ return 0;
+}
+
+static int kho_walk_scratch(struct kexec_buf *kbuf,
+ int (*func)(struct resource *, void *))
+{
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < kho_scratch_cnt; i++) {
+ struct resource res = {
+ .start = kho_scratch[i].addr,
+ .end = kho_scratch[i].addr + kho_scratch[i].size - 1,
+ };
+
+ /* Try to fit the kimage into our KHO scratch region */
+ ret = func(&res, kbuf);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+int kho_locate_mem_hole(struct kexec_buf *kbuf,
+ int (*func)(struct resource *, void *))
+{
+ int ret;
+
+ if (!kho_enable || kbuf->image->type == KEXEC_TYPE_CRASH)
+ return 1;
+
+ ret = kho_walk_scratch(kbuf, func);
+
+ return ret == 1 ? 0 : -EADDRNOTAVAIL;
+}
diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h
index d35d9792402d1..30a733a55a67b 100644
--- a/kernel/kexec_internal.h
+++ b/kernel/kexec_internal.h
@@ -39,4 +39,20 @@ extern size_t kexec_purgatory_size;
#else /* CONFIG_KEXEC_FILE */
static inline void kimage_file_post_load_cleanup(struct kimage *image) { }
#endif /* CONFIG_KEXEC_FILE */
+
+struct kexec_buf;
+
+#ifdef CONFIG_KEXEC_HANDOVER
+int kho_locate_mem_hole(struct kexec_buf *kbuf,
+ int (*func)(struct resource *, void *));
+int kho_fill_kimage(struct kimage *image);
+#else
+static inline int kho_locate_mem_hole(struct kexec_buf *kbuf,
+ int (*func)(struct resource *, void *))
+{
+ return 1;
+}
+
+static inline int kho_fill_kimage(struct kimage *image) { return 0; }
+#endif /* CONFIG_KEXEC_HANDOVER */
#endif /* LINUX_KEXEC_INTERNAL_H */
--
2.49.0.604.gff1f9ca942-goog
next prev parent reply other threads:[~2025-04-11 5:38 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-11 5:37 [PATCH v6 00/14] kexec: introduce Kexec HandOver (KHO) Changyuan Lyu
2025-04-11 5:37 ` [PATCH v6 01/14] memblock: add MEMBLOCK_RSRV_KERN flag Changyuan Lyu
2025-04-11 5:37 ` [PATCH v6 02/14] memblock: Add support for scratch memory Changyuan Lyu
2025-04-11 5:37 ` [PATCH v6 03/14] memblock: introduce memmap_init_kho_scratch() Changyuan Lyu
2025-04-11 5:37 ` [PATCH v6 04/14] kexec: add Kexec HandOver (KHO) generation helpers Changyuan Lyu
2025-04-11 5:37 ` [PATCH v6 05/14] kexec: add KHO parsing support Changyuan Lyu
2025-04-11 5:37 ` [PATCH v6 06/14] kexec: enable KHO support for memory preservation Changyuan Lyu
2025-04-11 5:37 ` Changyuan Lyu [this message]
2025-04-11 5:37 ` [PATCH v6 08/14] kexec: add config option for KHO Changyuan Lyu
2025-04-11 5:37 ` [PATCH v6 09/14] arm64: add KHO support Changyuan Lyu
2025-04-11 5:37 ` [PATCH v6 10/14] x86/setup: use memblock_reserve_kern for memory used by kernel Changyuan Lyu
2025-04-28 22:15 ` Dave Hansen
2025-04-11 5:37 ` [PATCH v6 11/14] x86: add KHO support Changyuan Lyu
2025-04-28 22:05 ` Dave Hansen
2025-04-29 8:06 ` Mike Rapoport
2025-04-29 16:06 ` Dave Hansen
2025-04-29 16:32 ` Mike Rapoport
2025-04-29 15:53 ` Mike Rapoport
2025-04-29 16:05 ` Dave Hansen
2025-04-29 16:34 ` Mike Rapoport
2025-04-11 5:37 ` [PATCH v6 12/14] memblock: add KHO support for reserve_mem Changyuan Lyu
2025-04-22 13:31 ` Mike Rapoport
2025-04-24 8:32 ` Changyuan Lyu
2025-04-11 5:37 ` [PATCH v6 13/14] Documentation: add documentation for KHO Changyuan Lyu
2025-04-11 5:37 ` [PATCH v6 14/14] Documentation: KHO: Add memblock bindings Changyuan Lyu
2025-04-28 22:19 ` [PATCH v6 00/14] kexec: introduce Kexec HandOver (KHO) Dave Hansen
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=20250411053745.1817356-8-changyuanl@google.com \
--to=changyuanl@google.com \
--cc=akpm@linux-foundation.org \
--cc=anthony.yznaga@oracle.com \
--cc=arnd@arndb.de \
--cc=ashish.kalra@amd.com \
--cc=benh@kernel.crashing.org \
--cc=bp@alien8.de \
--cc=catalin.marinas@arm.com \
--cc=corbet@lwn.net \
--cc=dave.hansen@linux.intel.com \
--cc=devicetree@vger.kernel.org \
--cc=dwmw2@infradead.org \
--cc=ebiederm@xmission.com \
--cc=graf@amazon.com \
--cc=hpa@zytor.com \
--cc=jgowans@amazon.com \
--cc=kexec@lists.infradead.org \
--cc=krzk@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=luto@kernel.org \
--cc=mark.rutland@arm.com \
--cc=mingo@redhat.com \
--cc=pasha.tatashin@soleen.com \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=ptyadav@amazon.de \
--cc=robh@kernel.org \
--cc=rostedt@goodmis.org \
--cc=rppt@kernel.org \
--cc=saravanak@google.com \
--cc=skinsburskii@linux.microsoft.com \
--cc=tglx@linutronix.de \
--cc=thomas.lendacky@amd.com \
--cc=will@kernel.org \
--cc=x86@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