linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] Add kexec_file support for LoongArch
@ 2025-08-11  9:26 Youling Tang
  2025-08-11  9:26 ` [PATCH 1/6] LoongArch: Add struct loongarch_image_header for kernel image Youling Tang
                   ` (6 more replies)
  0 siblings, 7 replies; 30+ messages in thread
From: Youling Tang @ 2025-08-11  9:26 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	youling.tang, Youling Tang

From: Youling Tang <tangyouling@kylinos.cn>

This patchset implement kexec_file_load() support on LoongArch.

This patch series enables us to load the LoongArch vmlinuz.efi or
vmlinux.efi by specifying its file decriptor, instead of user-filled
buffer via kexec_load() syscall.

To use kexec_file_load() system call, instead of kexec_load(), at kexec
command, '-s' options must be specified. kexec-tools needs to apply the
corresponding patches. These patches can be found in repository [1] and
will be submitted to the kexec-tools community later.

The basic usage of kexec_file is:
1) Load second kernel image:
 # kexec -s -l vmlinuz.efi --initrd=initrd.img --reuse-cmdline

2) Startup second kernel:
 # kexec -e

For kdump:
1) Load capture kernel image:
 # kexec -s -p vmlinuz.efi --initrd=initrd.img --reuse-cmdline

2) Do something to crash, like:
 # echo c > /proc/sysrq-trigger

Link:
[1] https://github.com/tangyouling/kexec-tools/commits/main/

Youling Tang (6):
  LoongArch: Add struct loongarch_image_header for kernel image
  LoongArch: Add kexec_file support
  LoongArch/kexec_file: Add initrd loading
  LoongArch/kexec_file: Add crash dump support
  LoongArch/kexec_file: Add "mem" parameter to limit memory usage of
    kdump kernel
  LoongArch: Enable CONFIG_KEXEC_FILE

 arch/loongarch/Kconfig                     |   8 +
 arch/loongarch/configs/loongson3_defconfig |   1 +
 arch/loongarch/include/asm/image.h         |  58 +++++
 arch/loongarch/include/asm/kexec.h         |  12 ++
 arch/loongarch/kernel/Makefile             |   1 +
 arch/loongarch/kernel/kexec_image.c        | 112 ++++++++++
 arch/loongarch/kernel/machine_kexec.c      |  33 ++-
 arch/loongarch/kernel/machine_kexec_file.c | 234 +++++++++++++++++++++
 8 files changed, 448 insertions(+), 11 deletions(-)
 create mode 100644 arch/loongarch/include/asm/image.h
 create mode 100644 arch/loongarch/kernel/kexec_image.c
 create mode 100644 arch/loongarch/kernel/machine_kexec_file.c

-- 
2.34.1


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 1/6] LoongArch: Add struct loongarch_image_header for kernel image
  2025-08-11  9:26 [PATCH 0/6] Add kexec_file support for LoongArch Youling Tang
@ 2025-08-11  9:26 ` Youling Tang
  2025-08-11  9:26 ` [PATCH 2/6] LoongArch: Add kexec_file support Youling Tang
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Youling Tang @ 2025-08-11  9:26 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	youling.tang, Youling Tang

From: Youling Tang <tangyouling@kylinos.cn>

Define a dedicated image header structure for LoongArch architecture to
standardize kernel loading in bootloaders (primarily for kexec_file).

This header includes critical metadata such as PE signature, entry points,
image size and load address offset, etc.

Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
---
 arch/loongarch/include/asm/image.h | 40 ++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)
 create mode 100644 arch/loongarch/include/asm/image.h

diff --git a/arch/loongarch/include/asm/image.h b/arch/loongarch/include/asm/image.h
new file mode 100644
index 000000000000..1f090736e71d
--- /dev/null
+++ b/arch/loongarch/include/asm/image.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * LoongArch binary image header.
+ *
+ * Author: Youling Tang <tangyouling@kylinos.cn>
+ * Copyright (C) 2025 KylinSoft Corporation.
+ *
+ * Most code is derived from LoongArch port of kexec-tools
+ */
+
+#ifndef __ASM_IMAGE_H
+#define __ASM_IMAGE_H
+#ifndef __ASSEMBLY__
+
+/**
+ * struct loongarch_image_header
+ *
+ * @pe_sig: Optional PE format 'MZ' signature.
+ * @reserved_1: Reserved.
+ * @kernel_entry: Kernel image entry pointer.
+ * @image_size: An estimated size of the memory image size in LSB byte order.
+ * @text_offset: The image load offset in LSB byte order.
+ * @reserved_2: Reserved.
+ * @reserved_3: Reserved.
+ * @pe_header: Optional offset to a PE format header.
+ **/
+
+struct loongarch_image_header {
+	uint8_t pe_sig[2];
+	uint16_t reserved_1[3];
+	uint64_t kernel_entry;
+	uint64_t image_size;
+	uint64_t text_offset;
+	uint64_t reserved_2[3];
+	uint32_t reserved_3;
+	uint32_t pe_header;
+};
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_IMAGE_H */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-11  9:26 [PATCH 0/6] Add kexec_file support for LoongArch Youling Tang
  2025-08-11  9:26 ` [PATCH 1/6] LoongArch: Add struct loongarch_image_header for kernel image Youling Tang
@ 2025-08-11  9:26 ` Youling Tang
  2025-08-11 14:07   ` Huacai Chen
                     ` (2 more replies)
  2025-08-11  9:26 ` [PATCH 3/6] LoongArch/kexec_file: Add initrd loading Youling Tang
                   ` (4 subsequent siblings)
  6 siblings, 3 replies; 30+ messages in thread
From: Youling Tang @ 2025-08-11  9:26 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	youling.tang, Youling Tang

From: Youling Tang <tangyouling@kylinos.cn>

This patch adds support for kexec_file on LoongArch.

The image_load() as two parts:
- the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
- the second part loads other segments (eg: initrd, cmdline)

Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images are supported,
but ELF format is not supported.

Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
---
 arch/loongarch/Kconfig                     |   8 ++
 arch/loongarch/include/asm/image.h         |  18 ++++
 arch/loongarch/include/asm/kexec.h         |  12 +++
 arch/loongarch/kernel/Makefile             |   1 +
 arch/loongarch/kernel/kexec_image.c        | 112 +++++++++++++++++++++
 arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
 arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
 7 files changed, 219 insertions(+), 11 deletions(-)
 create mode 100644 arch/loongarch/kernel/kexec_image.c
 create mode 100644 arch/loongarch/kernel/machine_kexec_file.c

diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index f0abc38c40ac..fd50c83f7827 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -625,6 +625,14 @@ config CPU_HAS_PREFETCH
 config ARCH_SUPPORTS_KEXEC
 	def_bool y
 
+config ARCH_SUPPORTS_KEXEC_FILE
+	def_bool 64BIT
+
+config ARCH_SELECTS_KEXEC_FILE
+	def_bool y
+	depends on KEXEC_FILE
+	select HAVE_IMA_KEXEC if IMA
+
 config ARCH_SUPPORTS_CRASH_DUMP
 	def_bool y
 
diff --git a/arch/loongarch/include/asm/image.h b/arch/loongarch/include/asm/image.h
index 1f090736e71d..829e1ecb1f5d 100644
--- a/arch/loongarch/include/asm/image.h
+++ b/arch/loongarch/include/asm/image.h
@@ -36,5 +36,23 @@ struct loongarch_image_header {
 	uint32_t pe_header;
 };
 
+static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'};
+static const uint8_t loongarch_pe_machtype[6] = {'P', 'E', 0x0, 0x0, 0x64, 0x62};
+
+/**
+ * loongarch_header_check_pe_sig - Helper to check the loongarch image header.
+ *
+ * Returns non-zero if 'MZ' signature is found.
+ */
+
+static inline int loongarch_header_check_pe_sig(const struct loongarch_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return (h->pe_sig[0] == loongarch_image_pe_sig[0]
+		&& h->pe_sig[1] == loongarch_image_pe_sig[1]);
+}
+
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_IMAGE_H */
diff --git a/arch/loongarch/include/asm/kexec.h b/arch/loongarch/include/asm/kexec.h
index cf95cd3eb2de..3ef8517a3670 100644
--- a/arch/loongarch/include/asm/kexec.h
+++ b/arch/loongarch/include/asm/kexec.h
@@ -41,6 +41,18 @@ struct kimage_arch {
 	unsigned long systable_ptr;
 };
 
+#ifdef CONFIG_KEXEC_FILE
+extern const struct kexec_file_ops kexec_image_ops;
+
+int arch_kimage_file_post_load_cleanup(struct kimage *image);
+#define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup
+
+extern int load_other_segments(struct kimage *image,
+		unsigned long kernel_load_addr, unsigned long kernel_size,
+		char *initrd, unsigned long initrd_len,
+		char *cmdline, unsigned long cmdline_len);
+#endif
+
 typedef void (*do_kexec_t)(unsigned long efi_boot,
 			   unsigned long cmdline_ptr,
 			   unsigned long systable_ptr,
diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
index 6f5a4574a911..bd9405ee3888 100644
--- a/arch/loongarch/kernel/Makefile
+++ b/arch/loongarch/kernel/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_MAGIC_SYSRQ)	+= sysrq.o
 obj-$(CONFIG_RELOCATABLE)	+= relocate.o
 
 obj-$(CONFIG_KEXEC_CORE)	+= machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_FILE)	+= machine_kexec_file.o kexec_image.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 
 obj-$(CONFIG_UNWINDER_GUESS)	+= unwind_guess.o
diff --git a/arch/loongarch/kernel/kexec_image.c b/arch/loongarch/kernel/kexec_image.c
new file mode 100644
index 000000000000..fdd1845b4e2e
--- /dev/null
+++ b/arch/loongarch/kernel/kexec_image.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Kexec image loader for LoongArch
+
+ * Author: Youling Tang <tangyouling@kylinos.cn>
+ * Copyright (C) 2025 KylinSoft Corporation.
+ */
+
+#define pr_fmt(fmt)	"kexec_file(Image): " fmt
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/kexec.h>
+#include <linux/pe.h>
+#include <linux/string.h>
+#include <asm/byteorder.h>
+#include <asm/cpufeature.h>
+#include <asm/image.h>
+
+static int image_probe(const char *kernel_buf, unsigned long kernel_len)
+{
+	const struct loongarch_image_header *h =
+		(const struct loongarch_image_header *)(kernel_buf);
+
+	if (!h || (kernel_len < sizeof(*h))) {
+		pr_err("No loongarch image header.\n");
+		return -EINVAL;
+	}
+
+	if (!loongarch_header_check_pe_sig(h)) {
+		pr_err("Bad loongarch PE image header.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void *image_load(struct kimage *image,
+				char *kernel, unsigned long kernel_len,
+				char *initrd, unsigned long initrd_len,
+				char *cmdline, unsigned long cmdline_len)
+{
+	struct loongarch_image_header *h;
+	struct kexec_buf kbuf;
+	unsigned long text_offset, kernel_segment_number;
+	struct kexec_segment *kernel_segment;
+	int ret;
+
+	h = (struct loongarch_image_header *)kernel;
+	if (!h->image_size)
+		return ERR_PTR(-EINVAL);
+
+	/* Load the kernel */
+	kbuf.image = image;
+	kbuf.buf_min = 0;
+	kbuf.buf_max = ULONG_MAX;
+	kbuf.top_down = false;
+
+	kbuf.buffer = kernel;
+	kbuf.bufsz = kernel_len;
+	kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+	kbuf.memsz = le64_to_cpu(h->image_size);
+	text_offset = le64_to_cpu(h->text_offset);
+	kbuf.buf_align = SZ_2M;
+
+	kernel_segment_number = image->nr_segments;
+
+	/*
+	 * The location of the kernel segment may make it impossible to satisfy
+	 * the other segment requirements, so we try repeatedly to find a
+	 * location that will work.
+	 */
+	while ((ret = kexec_add_buffer(&kbuf)) == 0) {
+		/* Try to load additional data */
+		kernel_segment = &image->segment[kernel_segment_number];
+		ret = load_other_segments(image, kernel_segment->mem,
+					  kernel_segment->memsz, initrd,
+					  initrd_len, cmdline, cmdline_len);
+		if (!ret)
+			break;
+
+		/*
+		 * We couldn't find space for the other segments; erase the
+		 * kernel segment and try the next available hole.
+		 */
+		image->nr_segments -= 1;
+		kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
+		kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+	}
+
+	if (ret) {
+		pr_err("Could not find any suitable kernel location!");
+		return ERR_PTR(ret);
+	}
+
+	kernel_segment = &image->segment[kernel_segment_number];
+
+	/* Make sure the second kernel jumps to the correct "kernel_entry". */
+	image->start = kernel_segment->mem + h->kernel_entry - text_offset;
+
+	kexec_dprintk("Loaded kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+		      kernel_segment->mem, kbuf.bufsz,
+		      kernel_segment->memsz);
+
+	return NULL;
+}
+
+const struct kexec_file_ops kexec_image_ops = {
+	.probe = image_probe,
+	.load = image_load,
+};
diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/machine_kexec.c
index f9381800e291..008f43e26120 100644
--- a/arch/loongarch/kernel/machine_kexec.c
+++ b/arch/loongarch/kernel/machine_kexec.c
@@ -70,18 +70,28 @@ int machine_kexec_prepare(struct kimage *kimage)
 	kimage->arch.efi_boot = fw_arg0;
 	kimage->arch.systable_ptr = fw_arg2;
 
-	/* Find the command line */
-	for (i = 0; i < kimage->nr_segments; i++) {
-		if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) {
-			if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
-				kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
-			break;
+	if (kimage->file_mode == 1) {
+		/*
+		 * kimage->cmdline_buf will be released in kexec_file_load, so copy to
+		 * the KEXEC_CMDLINE_ADDR safe area.
+		 */
+		memcpy((void *)KEXEC_CMDLINE_ADDR, (void *)kimage->arch.cmdline_ptr,
+					strlen((char *)kimage->arch.cmdline_ptr) + 1);
+		kimage->arch.cmdline_ptr = (unsigned long)KEXEC_CMDLINE_ADDR;
+	} else {
+		/* Find the command line */
+		for (i = 0; i < kimage->nr_segments; i++) {
+			if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) {
+				if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
+					kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
+				break;
+			}
 		}
-	}
 
-	if (!kimage->arch.cmdline_ptr) {
-		pr_err("Command line not included in the provided image\n");
-		return -EINVAL;
+		if (!kimage->arch.cmdline_ptr) {
+			pr_err("Command line not included in the provided image\n");
+			return -EINVAL;
+		}
 	}
 
 	/* kexec/kdump need a safe page to save reboot_code_buffer */
@@ -288,7 +298,8 @@ void machine_kexec(struct kimage *image)
 	local_irq_disable();
 
 	pr_notice("EFI boot flag 0x%lx\n", efi_boot);
-	pr_notice("Command line at 0x%lx\n", cmdline_ptr);
+	pr_notice("Command line addr at 0x%lx\n", cmdline_ptr);
+	pr_notice("Command line at %s\n", (char *)cmdline_ptr);
 	pr_notice("System table at 0x%lx\n", systable_ptr);
 	pr_notice("We will call new kernel at 0x%lx\n", start_addr);
 	pr_notice("Bye ...\n");
diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
new file mode 100644
index 000000000000..bc91ae0afa4c
--- /dev/null
+++ b/arch/loongarch/kernel/machine_kexec_file.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * kexec_file for LoongArch
+ *
+ * Author: Youling Tang <tangyouling@kylinos.cn>
+ * Copyright (C) 2025 KylinSoft Corporation.
+ *
+ * Most code is derived from LoongArch port of kexec-tools
+ */
+
+#define pr_fmt(fmt) "kexec_file: " fmt
+
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/kexec.h>
+#include <linux/memblock.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <asm/bootinfo.h>
+
+const struct kexec_file_ops * const kexec_file_loaders[] = {
+	&kexec_image_ops,
+	NULL
+};
+
+int arch_kimage_file_post_load_cleanup(struct kimage *image)
+{
+	vfree(image->elf_headers);
+	image->elf_headers = NULL;
+	image->elf_headers_sz = 0;
+
+	return kexec_image_post_load_cleanup_default(image);
+}
+
+int load_other_segments(struct kimage *image,
+			unsigned long kernel_load_addr,
+			unsigned long kernel_size,
+			char *initrd, unsigned long initrd_len,
+			char *cmdline, unsigned long cmdline_len)
+{
+	image->arch.cmdline_ptr = (unsigned long)cmdline;
+
+	return 0;
+}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 3/6] LoongArch/kexec_file: Add initrd loading
  2025-08-11  9:26 [PATCH 0/6] Add kexec_file support for LoongArch Youling Tang
  2025-08-11  9:26 ` [PATCH 1/6] LoongArch: Add struct loongarch_image_header for kernel image Youling Tang
  2025-08-11  9:26 ` [PATCH 2/6] LoongArch: Add kexec_file support Youling Tang
@ 2025-08-11  9:26 ` Youling Tang
  2025-08-11 14:12   ` Huacai Chen
  2025-08-11 17:58   ` Yao Zi
  2025-08-11  9:26 ` [PATCH 4/6] LoongArch/kexec_file: Add crash dump support Youling Tang
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 30+ messages in thread
From: Youling Tang @ 2025-08-11  9:26 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	youling.tang, Youling Tang

From: Youling Tang <tangyouling@kylinos.cn>

Add inird loading support and pass it to the second kernel via the
cmdline 'initrd=start,size'.

Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
---
 arch/loongarch/kernel/machine_kexec_file.c | 71 ++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
index bc91ae0afa4c..e1240644f529 100644
--- a/arch/loongarch/kernel/machine_kexec_file.c
+++ b/arch/loongarch/kernel/machine_kexec_file.c
@@ -34,13 +34,84 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
 	return kexec_image_post_load_cleanup_default(image);
 }
 
+/* Adds the "initrd=start,size" command line parameter to command line. */
+static void cmdline_add_initrd(struct kimage *image, unsigned long *cmdline_tmplen,
+				char *modified_cmdline, unsigned long initrd)
+{
+	int initrd_strlen;
+
+	initrd_strlen = sprintf(modified_cmdline + (*cmdline_tmplen), "initrd=0x%lx,0x%lx ",
+		initrd, image->initrd_buf_len);
+	*cmdline_tmplen += initrd_strlen;
+}
+
+/*
+ * Tries to add the initrd to the image. If it is not possible to find
+ * valid locations, this function will undo changes to the image and return non
+ * zero.
+ */
 int load_other_segments(struct kimage *image,
 			unsigned long kernel_load_addr,
 			unsigned long kernel_size,
 			char *initrd, unsigned long initrd_len,
 			char *cmdline, unsigned long cmdline_len)
 {
+	struct kexec_buf kbuf;
+	unsigned long orig_segments = image->nr_segments;
+	char *modified_cmdline = NULL;
+	unsigned long cmdline_tmplen = 0;
+	unsigned long initrd_load_addr = 0;
+	int ret = 0;
+
+
+	kbuf.image = image;
+	/* not allocate anything below the kernel */
+	kbuf.buf_min = kernel_load_addr + kernel_size;
+
+	modified_cmdline = kzalloc(COMMAND_LINE_SIZE, GFP_KERNEL);
+	if (!modified_cmdline)
+		return -EINVAL;
+
+	/* Ensure it's nul terminated */
+	modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
+
+	/* load initrd */
+	if (initrd) {
+		kbuf.buffer = initrd;
+		kbuf.bufsz = initrd_len;
+		kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+		kbuf.memsz = initrd_len;
+		kbuf.buf_align = 0;
+		/* within 1GB-aligned window of up to 32GB in size */
+		kbuf.buf_max = round_down(kernel_load_addr, SZ_1G)
+						+ (unsigned long)SZ_1G * 32;
+		kbuf.top_down = false;
+
+		ret = kexec_add_buffer(&kbuf);
+		if (ret)
+			goto out_err;
+		initrd_load_addr = kbuf.mem;
+
+		kexec_dprintk("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+			      initrd_load_addr, kbuf.bufsz, kbuf.memsz);
+
+		/* Add the initrd=start,size parameter to the command line */
+		cmdline_add_initrd(image, &cmdline_tmplen, modified_cmdline, initrd_load_addr);
+	}
+
+	if (cmdline_len + cmdline_tmplen > COMMAND_LINE_SIZE) {
+		pr_err("Appending kdump cmdline exceeds cmdline size\n");
+		ret = -EINVAL;
+		goto out_err;
+	}
+	memcpy(modified_cmdline + cmdline_tmplen, cmdline, cmdline_len);
+	cmdline = modified_cmdline;
 	image->arch.cmdline_ptr = (unsigned long)cmdline;
 
 	return 0;
+
+out_err:
+	image->nr_segments = orig_segments;
+	kfree(modified_cmdline);
+	return ret;
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 4/6] LoongArch/kexec_file: Add crash dump support
  2025-08-11  9:26 [PATCH 0/6] Add kexec_file support for LoongArch Youling Tang
                   ` (2 preceding siblings ...)
  2025-08-11  9:26 ` [PATCH 3/6] LoongArch/kexec_file: Add initrd loading Youling Tang
@ 2025-08-11  9:26 ` Youling Tang
  2025-08-11  9:26 ` [PATCH 5/6] LoongArch/kexec_file: Add "mem" parameter to limit memory usage of kdump kernel Youling Tang
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Youling Tang @ 2025-08-11  9:26 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	youling.tang, Youling Tang

From: Youling Tang <tangyouling@kylinos.cn>

Enabling crash dump (kdump) includes:
- prepare contents of ELF header of a core dump file, /proc/vmcore,
  using crash_prepare_elf64_headers().
- add "elfcorehdr=size@start" to command line.

Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
---
 arch/loongarch/kernel/machine_kexec_file.c | 93 ++++++++++++++++++++++
 1 file changed, 93 insertions(+)

diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
index e1240644f529..06def654cc09 100644
--- a/arch/loongarch/kernel/machine_kexec_file.c
+++ b/arch/loongarch/kernel/machine_kexec_file.c
@@ -34,6 +34,63 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
 	return kexec_image_post_load_cleanup_default(image);
 }
 
+#ifdef CONFIG_CRASH_DUMP
+
+static int prepare_elf_headers(void **addr, unsigned long *sz)
+{
+	struct crash_mem *cmem;
+	unsigned int nr_ranges;
+	int ret;
+	u64 i;
+	phys_addr_t start, end;
+
+	nr_ranges = 2; /* for exclusion of crashkernel region */
+	for_each_mem_range(i, &start, &end)
+		nr_ranges++;
+
+	cmem = kmalloc(struct_size(cmem, ranges, nr_ranges), GFP_KERNEL);
+	if (!cmem)
+		return -ENOMEM;
+
+	cmem->max_nr_ranges = nr_ranges;
+	cmem->nr_ranges = 0;
+	for_each_mem_range(i, &start, &end) {
+		cmem->ranges[cmem->nr_ranges].start = start;
+		cmem->ranges[cmem->nr_ranges].end = end - 1;
+		cmem->nr_ranges++;
+	}
+
+	/* Exclude crashkernel region */
+	ret = crash_exclude_mem_range(cmem, crashk_res.start, crashk_res.end);
+	if (ret)
+		goto out;
+
+	if (crashk_low_res.end) {
+		ret = crash_exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end);
+		if (ret)
+			goto out;
+	}
+
+	ret = crash_prepare_elf64_headers(cmem, true, addr, sz);
+
+out:
+	kfree(cmem);
+	return ret;
+}
+
+/* Adds the "elfcorehdr=size@start" command line parameter to command line. */
+static void cmdline_add_elfcorehdr(struct kimage *image, unsigned long *cmdline_tmplen,
+				char *modified_cmdline, unsigned long elfcorehdr_sz)
+{
+	int elfcorehdr_strlen = 0;
+
+	elfcorehdr_strlen = sprintf(modified_cmdline + (*cmdline_tmplen), "elfcorehdr=0x%lx@0x%lx ",
+		elfcorehdr_sz, image->elf_load_addr);
+	*cmdline_tmplen += elfcorehdr_strlen;
+}
+
+#endif
+
 /* Adds the "initrd=start,size" command line parameter to command line. */
 static void cmdline_add_initrd(struct kimage *image, unsigned long *cmdline_tmplen,
 				char *modified_cmdline, unsigned long initrd)
@@ -75,6 +132,42 @@ int load_other_segments(struct kimage *image,
 	/* Ensure it's nul terminated */
 	modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
 
+#ifdef CONFIG_CRASH_DUMP
+	/* load elf core header */
+	void *headers;
+	unsigned long headers_sz;
+	if (image->type == KEXEC_TYPE_CRASH) {
+		ret = prepare_elf_headers(&headers, &headers_sz);
+		if (ret) {
+			pr_err("Preparing elf core header failed\n");
+			goto out_err;
+		}
+
+		kbuf.buffer = headers;
+		kbuf.bufsz = headers_sz;
+		kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
+		kbuf.memsz = headers_sz;
+		kbuf.buf_align = SZ_64K; /* largest supported page size */
+		kbuf.buf_max = ULONG_MAX;
+		kbuf.top_down = true;
+
+		ret = kexec_add_buffer(&kbuf);
+		if (ret) {
+			vfree(headers);
+			goto out_err;
+		}
+		image->elf_headers = headers;
+		image->elf_load_addr = kbuf.mem;
+		image->elf_headers_sz = headers_sz;
+
+		kexec_dprintk("Loaded elf core header at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
+			      image->elf_load_addr, kbuf.bufsz, kbuf.memsz);
+
+		/* Add the elfcorehdr=size@start parameter to the command line */
+		cmdline_add_elfcorehdr(image, &cmdline_tmplen, modified_cmdline, headers_sz);
+	}
+#endif
+
 	/* load initrd */
 	if (initrd) {
 		kbuf.buffer = initrd;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 5/6] LoongArch/kexec_file: Add "mem" parameter to limit memory usage of kdump kernel
  2025-08-11  9:26 [PATCH 0/6] Add kexec_file support for LoongArch Youling Tang
                   ` (3 preceding siblings ...)
  2025-08-11  9:26 ` [PATCH 4/6] LoongArch/kexec_file: Add crash dump support Youling Tang
@ 2025-08-11  9:26 ` Youling Tang
  2025-08-11  9:26 ` [PATCH 6/6] LoongArch: Enable CONFIG_KEXEC_FILE Youling Tang
  2025-08-11 16:20 ` [PATCH 0/6] Add kexec_file support for LoongArch Vincent Li
  6 siblings, 0 replies; 30+ messages in thread
From: Youling Tang @ 2025-08-11  9:26 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	youling.tang, Youling Tang

From: Youling Tang <tangyouling@kylinos.cn>

Add the "mem=size@start" parameter to the cmdline and pass it to the
capture kernel. Limit the runtime memory area for capturing the kernel
to avoid disrupting the production kernel site.

Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
---
 arch/loongarch/kernel/machine_kexec_file.c | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
index 06def654cc09..7da88c80cace 100644
--- a/arch/loongarch/kernel/machine_kexec_file.c
+++ b/arch/loongarch/kernel/machine_kexec_file.c
@@ -89,6 +89,26 @@ static void cmdline_add_elfcorehdr(struct kimage *image, unsigned long *cmdline_
 	*cmdline_tmplen += elfcorehdr_strlen;
 }
 
+/*
+ * Adds the "mem=size@start" command line parameter to command line, indicating the
+ * memory region the new kernel can use to boot into.
+ */
+static void cmdline_add_mem(struct kimage *image, unsigned long *cmdline_tmplen,
+				char *modified_cmdline)
+{
+	int mem_strlen = 0;
+
+	mem_strlen = sprintf(modified_cmdline + (*cmdline_tmplen), "mem=0x%llx@0x%llx ",
+		crashk_res.end - crashk_res.start + 1, crashk_res.start);
+	*cmdline_tmplen += mem_strlen;
+
+	if (crashk_low_res.end) {
+		mem_strlen = sprintf(modified_cmdline + (*cmdline_tmplen), "mem=0x%llx@0x%llx ",
+			crashk_low_res.end - crashk_low_res.start + 1, crashk_low_res.start);
+		*cmdline_tmplen += mem_strlen;
+	}
+}
+
 #endif
 
 /* Adds the "initrd=start,size" command line parameter to command line. */
@@ -136,6 +156,7 @@ int load_other_segments(struct kimage *image,
 	/* load elf core header */
 	void *headers;
 	unsigned long headers_sz;
+
 	if (image->type == KEXEC_TYPE_CRASH) {
 		ret = prepare_elf_headers(&headers, &headers_sz);
 		if (ret) {
@@ -165,6 +186,9 @@ int load_other_segments(struct kimage *image,
 
 		/* Add the elfcorehdr=size@start parameter to the command line */
 		cmdline_add_elfcorehdr(image, &cmdline_tmplen, modified_cmdline, headers_sz);
+
+		/* Add the mem=size@start parameter to the command line */
+		cmdline_add_mem(image, &cmdline_tmplen, modified_cmdline);
 	}
 #endif
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 6/6] LoongArch: Enable CONFIG_KEXEC_FILE
  2025-08-11  9:26 [PATCH 0/6] Add kexec_file support for LoongArch Youling Tang
                   ` (4 preceding siblings ...)
  2025-08-11  9:26 ` [PATCH 5/6] LoongArch/kexec_file: Add "mem" parameter to limit memory usage of kdump kernel Youling Tang
@ 2025-08-11  9:26 ` Youling Tang
  2025-08-11 16:20 ` [PATCH 0/6] Add kexec_file support for LoongArch Vincent Li
  6 siblings, 0 replies; 30+ messages in thread
From: Youling Tang @ 2025-08-11  9:26 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	youling.tang, Youling Tang

From: Youling Tang <tangyouling@kylinos.cn>

This patch enables config KEXEC_FILE by default in the
loongson3_defconfig, so that user-space tools like kexec-tools
can use the same as the default interface for kexec/kdump
on LoongArch.

Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
---
 arch/loongarch/configs/loongson3_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/loongarch/configs/loongson3_defconfig b/arch/loongarch/configs/loongson3_defconfig
index 34eaee0384c9..6cfea2f37cc0 100644
--- a/arch/loongarch/configs/loongson3_defconfig
+++ b/arch/loongarch/configs/loongson3_defconfig
@@ -45,6 +45,7 @@ CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_PERF_EVENTS=y
 CONFIG_KEXEC=y
+CONFIG_KEXEC_FILE=y
 CONFIG_CRASH_DUMP=y
 CONFIG_LOONGARCH=y
 CONFIG_64BIT=y
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-11  9:26 ` [PATCH 2/6] LoongArch: Add kexec_file support Youling Tang
@ 2025-08-11 14:07   ` Huacai Chen
  2025-08-12  1:21     ` Youling Tang
  2025-08-11 17:06   ` Yao Zi
  2025-08-16  5:37   ` kernel test robot
  2 siblings, 1 reply; 30+ messages in thread
From: Huacai Chen @ 2025-08-11 14:07 UTC (permalink / raw)
  To: Youling Tang
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

Hi, Youling,

On Mon, Aug 11, 2025 at 5:28 PM Youling Tang <youling.tang@linux.dev> wrote:
>
> From: Youling Tang <tangyouling@kylinos.cn>
>
> This patch adds support for kexec_file on LoongArch.
>
> The image_load() as two parts:
> - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
> - the second part loads other segments (eg: initrd, cmdline)
>
> Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images are supported,
> but ELF format is not supported.
>
> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> ---
>  arch/loongarch/Kconfig                     |   8 ++
>  arch/loongarch/include/asm/image.h         |  18 ++++
>  arch/loongarch/include/asm/kexec.h         |  12 +++
>  arch/loongarch/kernel/Makefile             |   1 +
>  arch/loongarch/kernel/kexec_image.c        | 112 +++++++++++++++++++++
>  arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
>  arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
>  7 files changed, 219 insertions(+), 11 deletions(-)
>  create mode 100644 arch/loongarch/kernel/kexec_image.c
>  create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
>
> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
> index f0abc38c40ac..fd50c83f7827 100644
> --- a/arch/loongarch/Kconfig
> +++ b/arch/loongarch/Kconfig
> @@ -625,6 +625,14 @@ config CPU_HAS_PREFETCH
>  config ARCH_SUPPORTS_KEXEC
>         def_bool y
>
> +config ARCH_SUPPORTS_KEXEC_FILE
> +       def_bool 64BIT
> +
> +config ARCH_SELECTS_KEXEC_FILE
> +       def_bool y
> +       depends on KEXEC_FILE
> +       select HAVE_IMA_KEXEC if IMA
> +
>  config ARCH_SUPPORTS_CRASH_DUMP
>         def_bool y
>
> diff --git a/arch/loongarch/include/asm/image.h b/arch/loongarch/include/asm/image.h
> index 1f090736e71d..829e1ecb1f5d 100644
> --- a/arch/loongarch/include/asm/image.h
> +++ b/arch/loongarch/include/asm/image.h
> @@ -36,5 +36,23 @@ struct loongarch_image_header {
>         uint32_t pe_header;
>  };
>
> +static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'};
> +static const uint8_t loongarch_pe_machtype[6] = {'P', 'E', 0x0, 0x0, 0x64, 0x62};
> +
> +/**
> + * loongarch_header_check_pe_sig - Helper to check the loongarch image header.
> + *
> + * Returns non-zero if 'MZ' signature is found.
> + */
> +
> +static inline int loongarch_header_check_pe_sig(const struct loongarch_image_header *h)
> +{
> +       if (!h)
> +               return 0;
> +
> +       return (h->pe_sig[0] == loongarch_image_pe_sig[0]
> +               && h->pe_sig[1] == loongarch_image_pe_sig[1]);
> +}
> +
>  #endif /* __ASSEMBLY__ */
>  #endif /* __ASM_IMAGE_H */
> diff --git a/arch/loongarch/include/asm/kexec.h b/arch/loongarch/include/asm/kexec.h
> index cf95cd3eb2de..3ef8517a3670 100644
> --- a/arch/loongarch/include/asm/kexec.h
> +++ b/arch/loongarch/include/asm/kexec.h
> @@ -41,6 +41,18 @@ struct kimage_arch {
>         unsigned long systable_ptr;
>  };
>
> +#ifdef CONFIG_KEXEC_FILE
> +extern const struct kexec_file_ops kexec_image_ops;
> +
> +int arch_kimage_file_post_load_cleanup(struct kimage *image);
> +#define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup
> +
> +extern int load_other_segments(struct kimage *image,
> +               unsigned long kernel_load_addr, unsigned long kernel_size,
> +               char *initrd, unsigned long initrd_len,
> +               char *cmdline, unsigned long cmdline_len);
I think the RISC-V naming "load_extra_segments" is better.

> +#endif
> +
>  typedef void (*do_kexec_t)(unsigned long efi_boot,
>                            unsigned long cmdline_ptr,
>                            unsigned long systable_ptr,
> diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
> index 6f5a4574a911..bd9405ee3888 100644
> --- a/arch/loongarch/kernel/Makefile
> +++ b/arch/loongarch/kernel/Makefile
> @@ -62,6 +62,7 @@ obj-$(CONFIG_MAGIC_SYSRQ)     += sysrq.o
>  obj-$(CONFIG_RELOCATABLE)      += relocate.o
>
>  obj-$(CONFIG_KEXEC_CORE)       += machine_kexec.o relocate_kernel.o
> +obj-$(CONFIG_KEXEC_FILE)       += machine_kexec_file.o kexec_image.o
We only support the efi format, so we don't need to split a
kexec_image.c like RISC-V, just put everything into
machine_kexec_file.c is OK.

Huacai

>  obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
>
>  obj-$(CONFIG_UNWINDER_GUESS)   += unwind_guess.o
> diff --git a/arch/loongarch/kernel/kexec_image.c b/arch/loongarch/kernel/kexec_image.c
> new file mode 100644
> index 000000000000..fdd1845b4e2e
> --- /dev/null
> +++ b/arch/loongarch/kernel/kexec_image.c
> @@ -0,0 +1,112 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Kexec image loader for LoongArch
> +
> + * Author: Youling Tang <tangyouling@kylinos.cn>
> + * Copyright (C) 2025 KylinSoft Corporation.
> + */
> +
> +#define pr_fmt(fmt)    "kexec_file(Image): " fmt
> +
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +#include <linux/kernel.h>
> +#include <linux/kexec.h>
> +#include <linux/pe.h>
> +#include <linux/string.h>
> +#include <asm/byteorder.h>
> +#include <asm/cpufeature.h>
> +#include <asm/image.h>
> +
> +static int image_probe(const char *kernel_buf, unsigned long kernel_len)
> +{
> +       const struct loongarch_image_header *h =
> +               (const struct loongarch_image_header *)(kernel_buf);
> +
> +       if (!h || (kernel_len < sizeof(*h))) {
> +               pr_err("No loongarch image header.\n");
> +               return -EINVAL;
> +       }
> +
> +       if (!loongarch_header_check_pe_sig(h)) {
> +               pr_err("Bad loongarch PE image header.\n");
> +               return -EINVAL;
> +       }
> +
> +       return 0;
> +}
> +
> +static void *image_load(struct kimage *image,
> +                               char *kernel, unsigned long kernel_len,
> +                               char *initrd, unsigned long initrd_len,
> +                               char *cmdline, unsigned long cmdline_len)
> +{
> +       struct loongarch_image_header *h;
> +       struct kexec_buf kbuf;
> +       unsigned long text_offset, kernel_segment_number;
> +       struct kexec_segment *kernel_segment;
> +       int ret;
> +
> +       h = (struct loongarch_image_header *)kernel;
> +       if (!h->image_size)
> +               return ERR_PTR(-EINVAL);
> +
> +       /* Load the kernel */
> +       kbuf.image = image;
> +       kbuf.buf_min = 0;
> +       kbuf.buf_max = ULONG_MAX;
> +       kbuf.top_down = false;
> +
> +       kbuf.buffer = kernel;
> +       kbuf.bufsz = kernel_len;
> +       kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> +       kbuf.memsz = le64_to_cpu(h->image_size);
> +       text_offset = le64_to_cpu(h->text_offset);
> +       kbuf.buf_align = SZ_2M;
> +
> +       kernel_segment_number = image->nr_segments;
> +
> +       /*
> +        * The location of the kernel segment may make it impossible to satisfy
> +        * the other segment requirements, so we try repeatedly to find a
> +        * location that will work.
> +        */
> +       while ((ret = kexec_add_buffer(&kbuf)) == 0) {
> +               /* Try to load additional data */
> +               kernel_segment = &image->segment[kernel_segment_number];
> +               ret = load_other_segments(image, kernel_segment->mem,
> +                                         kernel_segment->memsz, initrd,
> +                                         initrd_len, cmdline, cmdline_len);
> +               if (!ret)
> +                       break;
> +
> +               /*
> +                * We couldn't find space for the other segments; erase the
> +                * kernel segment and try the next available hole.
> +                */
> +               image->nr_segments -= 1;
> +               kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
> +               kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> +       }
> +
> +       if (ret) {
> +               pr_err("Could not find any suitable kernel location!");
> +               return ERR_PTR(ret);
> +       }
> +
> +       kernel_segment = &image->segment[kernel_segment_number];
> +
> +       /* Make sure the second kernel jumps to the correct "kernel_entry". */
> +       image->start = kernel_segment->mem + h->kernel_entry - text_offset;
> +
> +       kexec_dprintk("Loaded kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
> +                     kernel_segment->mem, kbuf.bufsz,
> +                     kernel_segment->memsz);
> +
> +       return NULL;
> +}
> +
> +const struct kexec_file_ops kexec_image_ops = {
> +       .probe = image_probe,
> +       .load = image_load,
> +};
> diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/machine_kexec.c
> index f9381800e291..008f43e26120 100644
> --- a/arch/loongarch/kernel/machine_kexec.c
> +++ b/arch/loongarch/kernel/machine_kexec.c
> @@ -70,18 +70,28 @@ int machine_kexec_prepare(struct kimage *kimage)
>         kimage->arch.efi_boot = fw_arg0;
>         kimage->arch.systable_ptr = fw_arg2;
>
> -       /* Find the command line */
> -       for (i = 0; i < kimage->nr_segments; i++) {
> -               if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) {
> -                       if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
> -                               kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
> -                       break;
> +       if (kimage->file_mode == 1) {
> +               /*
> +                * kimage->cmdline_buf will be released in kexec_file_load, so copy to
> +                * the KEXEC_CMDLINE_ADDR safe area.
> +                */
> +               memcpy((void *)KEXEC_CMDLINE_ADDR, (void *)kimage->arch.cmdline_ptr,
> +                                       strlen((char *)kimage->arch.cmdline_ptr) + 1);
> +               kimage->arch.cmdline_ptr = (unsigned long)KEXEC_CMDLINE_ADDR;
> +       } else {
> +               /* Find the command line */
> +               for (i = 0; i < kimage->nr_segments; i++) {
> +                       if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) {
> +                               if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
> +                                       kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
> +                               break;
> +                       }
>                 }
> -       }
>
> -       if (!kimage->arch.cmdline_ptr) {
> -               pr_err("Command line not included in the provided image\n");
> -               return -EINVAL;
> +               if (!kimage->arch.cmdline_ptr) {
> +                       pr_err("Command line not included in the provided image\n");
> +                       return -EINVAL;
> +               }
>         }
>
>         /* kexec/kdump need a safe page to save reboot_code_buffer */
> @@ -288,7 +298,8 @@ void machine_kexec(struct kimage *image)
>         local_irq_disable();
>
>         pr_notice("EFI boot flag 0x%lx\n", efi_boot);
> -       pr_notice("Command line at 0x%lx\n", cmdline_ptr);
> +       pr_notice("Command line addr at 0x%lx\n", cmdline_ptr);
> +       pr_notice("Command line at %s\n", (char *)cmdline_ptr);
>         pr_notice("System table at 0x%lx\n", systable_ptr);
>         pr_notice("We will call new kernel at 0x%lx\n", start_addr);
>         pr_notice("Bye ...\n");
> diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
> new file mode 100644
> index 000000000000..bc91ae0afa4c
> --- /dev/null
> +++ b/arch/loongarch/kernel/machine_kexec_file.c
> @@ -0,0 +1,46 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * kexec_file for LoongArch
> + *
> + * Author: Youling Tang <tangyouling@kylinos.cn>
> + * Copyright (C) 2025 KylinSoft Corporation.
> + *
> + * Most code is derived from LoongArch port of kexec-tools
> + */
> +
> +#define pr_fmt(fmt) "kexec_file: " fmt
> +
> +#include <linux/ioport.h>
> +#include <linux/kernel.h>
> +#include <linux/kexec.h>
> +#include <linux/memblock.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +#include <linux/vmalloc.h>
> +#include <asm/bootinfo.h>
> +
> +const struct kexec_file_ops * const kexec_file_loaders[] = {
> +       &kexec_image_ops,
> +       NULL
> +};
> +
> +int arch_kimage_file_post_load_cleanup(struct kimage *image)
> +{
> +       vfree(image->elf_headers);
> +       image->elf_headers = NULL;
> +       image->elf_headers_sz = 0;
> +
> +       return kexec_image_post_load_cleanup_default(image);
> +}
> +
> +int load_other_segments(struct kimage *image,
> +                       unsigned long kernel_load_addr,
> +                       unsigned long kernel_size,
> +                       char *initrd, unsigned long initrd_len,
> +                       char *cmdline, unsigned long cmdline_len)
> +{
> +       image->arch.cmdline_ptr = (unsigned long)cmdline;
> +
> +       return 0;
> +}
> --
> 2.34.1
>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 3/6] LoongArch/kexec_file: Add initrd loading
  2025-08-11  9:26 ` [PATCH 3/6] LoongArch/kexec_file: Add initrd loading Youling Tang
@ 2025-08-11 14:12   ` Huacai Chen
  2025-08-12  2:38     ` Youling Tang
  2025-08-11 17:58   ` Yao Zi
  1 sibling, 1 reply; 30+ messages in thread
From: Huacai Chen @ 2025-08-11 14:12 UTC (permalink / raw)
  To: Youling Tang
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

Hi, Youling,

On Mon, Aug 11, 2025 at 5:28 PM Youling Tang <youling.tang@linux.dev> wrote:
>
> From: Youling Tang <tangyouling@kylinos.cn>
>
> Add inird loading support and pass it to the second kernel via the
> cmdline 'initrd=start,size'.
I think Patch-3 and Patch-5 should be merged into Patch-2.

Huacai

>
> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> ---
>  arch/loongarch/kernel/machine_kexec_file.c | 71 ++++++++++++++++++++++
>  1 file changed, 71 insertions(+)
>
> diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
> index bc91ae0afa4c..e1240644f529 100644
> --- a/arch/loongarch/kernel/machine_kexec_file.c
> +++ b/arch/loongarch/kernel/machine_kexec_file.c
> @@ -34,13 +34,84 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
>         return kexec_image_post_load_cleanup_default(image);
>  }
>
> +/* Adds the "initrd=start,size" command line parameter to command line. */
> +static void cmdline_add_initrd(struct kimage *image, unsigned long *cmdline_tmplen,
> +                               char *modified_cmdline, unsigned long initrd)
> +{
> +       int initrd_strlen;
> +
> +       initrd_strlen = sprintf(modified_cmdline + (*cmdline_tmplen), "initrd=0x%lx,0x%lx ",
> +               initrd, image->initrd_buf_len);
> +       *cmdline_tmplen += initrd_strlen;
> +}
> +
> +/*
> + * Tries to add the initrd to the image. If it is not possible to find
> + * valid locations, this function will undo changes to the image and return non
> + * zero.
> + */
>  int load_other_segments(struct kimage *image,
>                         unsigned long kernel_load_addr,
>                         unsigned long kernel_size,
>                         char *initrd, unsigned long initrd_len,
>                         char *cmdline, unsigned long cmdline_len)
>  {
> +       struct kexec_buf kbuf;
> +       unsigned long orig_segments = image->nr_segments;
> +       char *modified_cmdline = NULL;
> +       unsigned long cmdline_tmplen = 0;
> +       unsigned long initrd_load_addr = 0;
> +       int ret = 0;
> +
> +
> +       kbuf.image = image;
> +       /* not allocate anything below the kernel */
> +       kbuf.buf_min = kernel_load_addr + kernel_size;
> +
> +       modified_cmdline = kzalloc(COMMAND_LINE_SIZE, GFP_KERNEL);
> +       if (!modified_cmdline)
> +               return -EINVAL;
> +
> +       /* Ensure it's nul terminated */
> +       modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
> +
> +       /* load initrd */
> +       if (initrd) {
> +               kbuf.buffer = initrd;
> +               kbuf.bufsz = initrd_len;
> +               kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> +               kbuf.memsz = initrd_len;
> +               kbuf.buf_align = 0;
> +               /* within 1GB-aligned window of up to 32GB in size */
> +               kbuf.buf_max = round_down(kernel_load_addr, SZ_1G)
> +                                               + (unsigned long)SZ_1G * 32;
> +               kbuf.top_down = false;
> +
> +               ret = kexec_add_buffer(&kbuf);
> +               if (ret)
> +                       goto out_err;
> +               initrd_load_addr = kbuf.mem;
> +
> +               kexec_dprintk("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
> +                             initrd_load_addr, kbuf.bufsz, kbuf.memsz);
> +
> +               /* Add the initrd=start,size parameter to the command line */
> +               cmdline_add_initrd(image, &cmdline_tmplen, modified_cmdline, initrd_load_addr);
> +       }
> +
> +       if (cmdline_len + cmdline_tmplen > COMMAND_LINE_SIZE) {
> +               pr_err("Appending kdump cmdline exceeds cmdline size\n");
> +               ret = -EINVAL;
> +               goto out_err;
> +       }
> +       memcpy(modified_cmdline + cmdline_tmplen, cmdline, cmdline_len);
> +       cmdline = modified_cmdline;
>         image->arch.cmdline_ptr = (unsigned long)cmdline;
>
>         return 0;
> +
> +out_err:
> +       image->nr_segments = orig_segments;
> +       kfree(modified_cmdline);
> +       return ret;
>  }
> --
> 2.34.1
>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 0/6] Add kexec_file support for LoongArch
  2025-08-11  9:26 [PATCH 0/6] Add kexec_file support for LoongArch Youling Tang
                   ` (5 preceding siblings ...)
  2025-08-11  9:26 ` [PATCH 6/6] LoongArch: Enable CONFIG_KEXEC_FILE Youling Tang
@ 2025-08-11 16:20 ` Vincent Li
  2025-08-12  6:21   ` Youling Tang
  6 siblings, 1 reply; 30+ messages in thread
From: Vincent Li @ 2025-08-11 16:20 UTC (permalink / raw)
  To: Youling Tang
  Cc: Huacai Chen, WANG Xuerui, Baoquan He, kexec, loongarch,
	linux-kernel, Youling Tang

Hi Youling,

On Mon, Aug 11, 2025 at 2:28 AM Youling Tang <youling.tang@linux.dev> wrote:
>
> From: Youling Tang <tangyouling@kylinos.cn>
>
> This patchset implement kexec_file_load() support on LoongArch.
>
> This patch series enables us to load the LoongArch vmlinuz.efi or
> vmlinux.efi by specifying its file decriptor, instead of user-filled
> buffer via kexec_load() syscall.
>
> To use kexec_file_load() system call, instead of kexec_load(), at kexec
> command, '-s' options must be specified. kexec-tools needs to apply the
> corresponding patches. These patches can be found in repository [1] and
> will be submitted to the kexec-tools community later.
>
> The basic usage of kexec_file is:
> 1) Load second kernel image:
>  # kexec -s -l vmlinuz.efi --initrd=initrd.img --reuse-cmdline
>
> 2) Startup second kernel:
>  # kexec -e
>
> For kdump:
> 1) Load capture kernel image:
>  # kexec -s -p vmlinuz.efi --initrd=initrd.img --reuse-cmdline
>
> 2) Do something to crash, like:
>  # echo c > /proc/sysrq-trigger
>

I am new to this feature but I am interested to test this feature, How
do I get the second kernel or capture image vmlinux.efi and
initrd.img, do I need to build them separately and how?

> Link:
> [1] https://github.com/tangyouling/kexec-tools/commits/main/
>
> Youling Tang (6):
>   LoongArch: Add struct loongarch_image_header for kernel image
>   LoongArch: Add kexec_file support
>   LoongArch/kexec_file: Add initrd loading
>   LoongArch/kexec_file: Add crash dump support
>   LoongArch/kexec_file: Add "mem" parameter to limit memory usage of
>     kdump kernel
>   LoongArch: Enable CONFIG_KEXEC_FILE
>
>  arch/loongarch/Kconfig                     |   8 +
>  arch/loongarch/configs/loongson3_defconfig |   1 +
>  arch/loongarch/include/asm/image.h         |  58 +++++
>  arch/loongarch/include/asm/kexec.h         |  12 ++
>  arch/loongarch/kernel/Makefile             |   1 +
>  arch/loongarch/kernel/kexec_image.c        | 112 ++++++++++
>  arch/loongarch/kernel/machine_kexec.c      |  33 ++-
>  arch/loongarch/kernel/machine_kexec_file.c | 234 +++++++++++++++++++++
>  8 files changed, 448 insertions(+), 11 deletions(-)
>  create mode 100644 arch/loongarch/include/asm/image.h
>  create mode 100644 arch/loongarch/kernel/kexec_image.c
>  create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
>
> --
> 2.34.1
>
>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-11  9:26 ` [PATCH 2/6] LoongArch: Add kexec_file support Youling Tang
  2025-08-11 14:07   ` Huacai Chen
@ 2025-08-11 17:06   ` Yao Zi
  2025-08-12  2:39     ` Huacai Chen
  2025-08-12  6:15     ` Youling Tang
  2025-08-16  5:37   ` kernel test robot
  2 siblings, 2 replies; 30+ messages in thread
From: Yao Zi @ 2025-08-11 17:06 UTC (permalink / raw)
  To: Youling Tang, Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

On Mon, Aug 11, 2025 at 05:26:55PM +0800, Youling Tang wrote:
> From: Youling Tang <tangyouling@kylinos.cn>
> 
> This patch adds support for kexec_file on LoongArch.
> 
> The image_load() as two parts:
> - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
> - the second part loads other segments (eg: initrd, cmdline)
> 
> Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images are supported,
> but ELF format is not supported.
> 
> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> ---
>  arch/loongarch/Kconfig                     |   8 ++
>  arch/loongarch/include/asm/image.h         |  18 ++++
>  arch/loongarch/include/asm/kexec.h         |  12 +++
>  arch/loongarch/kernel/Makefile             |   1 +
>  arch/loongarch/kernel/kexec_image.c        | 112 +++++++++++++++++++++
>  arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
>  arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
>  7 files changed, 219 insertions(+), 11 deletions(-)
>  create mode 100644 arch/loongarch/kernel/kexec_image.c
>  create mode 100644 arch/loongarch/kernel/machine_kexec_file.c

...

> diff --git a/arch/loongarch/include/asm/image.h b/arch/loongarch/include/asm/image.h
> index 1f090736e71d..829e1ecb1f5d 100644
> --- a/arch/loongarch/include/asm/image.h
> +++ b/arch/loongarch/include/asm/image.h
> @@ -36,5 +36,23 @@ struct loongarch_image_header {
>  	uint32_t pe_header;
>  };
>  
> +static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'};
> +static const uint8_t loongarch_pe_machtype[6] = {'P', 'E', 0x0, 0x0, 0x64, 0x62};

loongarch_pe_machtype isn't used at all.

> +
> +/**
> + * loongarch_header_check_pe_sig - Helper to check the loongarch image header.
> + *
> + * Returns non-zero if 'MZ' signature is found.
> + */
> +
> +static inline int loongarch_header_check_pe_sig(const struct loongarch_image_header *h)
> +{
> +	if (!h)
> +		return 0;
> +
> +	return (h->pe_sig[0] == loongarch_image_pe_sig[0]
> +		&& h->pe_sig[1] == loongarch_image_pe_sig[1]);

This could be simplified with a memcmp(). Also, this check isn't strict
enough: PE files for any architectures, and even legacy MS-DOS COM
executables all start with "MZ".

> +}
> +
>  #endif /* __ASSEMBLY__ */
>  #endif /* __ASM_IMAGE_H */

...

> diff --git a/arch/loongarch/kernel/kexec_image.c b/arch/loongarch/kernel/kexec_image.c
> new file mode 100644
> index 000000000000..fdd1845b4e2e
> --- /dev/null
> +++ b/arch/loongarch/kernel/kexec_image.c
> @@ -0,0 +1,112 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Kexec image loader for LoongArch
> +
> + * Author: Youling Tang <tangyouling@kylinos.cn>
> + * Copyright (C) 2025 KylinSoft Corporation.
> + */
> +
> +#define pr_fmt(fmt)	"kexec_file(Image): " fmt
> +
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +#include <linux/kernel.h>
> +#include <linux/kexec.h>
> +#include <linux/pe.h>
> +#include <linux/string.h>
> +#include <asm/byteorder.h>
> +#include <asm/cpufeature.h>
> +#include <asm/image.h>
> +
> +static int image_probe(const char *kernel_buf, unsigned long kernel_len)
> +{
> +	const struct loongarch_image_header *h =
> +		(const struct loongarch_image_header *)(kernel_buf);

Parentheses around "kernel_buf" are unnecessary.

> +	if (!h || (kernel_len < sizeof(*h))) {

Comparisons have higher priority than logic operations, so this pair of
parentheses is redundant, too.

> +		pr_err("No loongarch image header.\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!loongarch_header_check_pe_sig(h)) {
> +		pr_err("Bad loongarch PE image header.\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static void *image_load(struct kimage *image,
> +				char *kernel, unsigned long kernel_len,
> +				char *initrd, unsigned long initrd_len,
> +				char *cmdline, unsigned long cmdline_len)
> +{
> +	struct loongarch_image_header *h;
> +	struct kexec_buf kbuf;
> +	unsigned long text_offset, kernel_segment_number;
> +	struct kexec_segment *kernel_segment;
> +	int ret;
> +
> +	h = (struct loongarch_image_header *)kernel;
> +	if (!h->image_size)
> +		return ERR_PTR(-EINVAL);
> +
> +	/* Load the kernel */
> +	kbuf.image = image;
> +	kbuf.buf_min = 0;
> +	kbuf.buf_max = ULONG_MAX;
> +	kbuf.top_down = false;
> +
> +	kbuf.buffer = kernel;
> +	kbuf.bufsz = kernel_len;
> +	kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> +	kbuf.memsz = le64_to_cpu(h->image_size);
> +	text_offset = le64_to_cpu(h->text_offset);
> +	kbuf.buf_align = SZ_2M;

I think this aligment is unnecessary for relocatable LoongArch kernels:
it should be enough to align to the page size. See also my comments
below.

> +	kernel_segment_number = image->nr_segments;
> +
> +	/*
> +	 * The location of the kernel segment may make it impossible to satisfy
> +	 * the other segment requirements, so we try repeatedly to find a
> +	 * location that will work.
> +	 */
> +	while ((ret = kexec_add_buffer(&kbuf)) == 0) {
> +		/* Try to load additional data */
> +		kernel_segment = &image->segment[kernel_segment_number];
> +		ret = load_other_segments(image, kernel_segment->mem,
> +					  kernel_segment->memsz, initrd,
> +					  initrd_len, cmdline, cmdline_len);
> +		if (!ret)
> +			break;
> +
> +		/*
> +		 * We couldn't find space for the other segments; erase the
> +		 * kernel segment and try the next available hole.
> +		 */
> +		image->nr_segments -= 1;
> +		kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
> +		kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> +	}
> +
> +	if (ret) {
> +		pr_err("Could not find any suitable kernel location!");
> +		return ERR_PTR(ret);
> +	}
> +
> +	kernel_segment = &image->segment[kernel_segment_number];
> +
> +	/* Make sure the second kernel jumps to the correct "kernel_entry". */
> +	image->start = kernel_segment->mem + h->kernel_entry - text_offset;

A non-relocatable loongarch kernel cannot be loaded to arbitrary
address. Thus this loading function seems to only work for relocatable
kernels, maybe it's better to leave a comment indicating the limitation.

For now, we don't seem to have a way to find out whether the kernel is
relocatable (for example, a flag in kernel image header), so it's
impossible to point out whether the loaded kernel boots fine with
arbitrary loading address...

> +	kexec_dprintk("Loaded kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
> +		      kernel_segment->mem, kbuf.bufsz,
> +		      kernel_segment->memsz);
> +
> +	return NULL;
> +}
> +
> +const struct kexec_file_ops kexec_image_ops = {
> +	.probe = image_probe,
> +	.load = image_load,
> +};
> diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/machine_kexec.c
> index f9381800e291..008f43e26120 100644
> --- a/arch/loongarch/kernel/machine_kexec.c
> +++ b/arch/loongarch/kernel/machine_kexec.c
> @@ -70,18 +70,28 @@ int machine_kexec_prepare(struct kimage *kimage)

...

> -	if (!kimage->arch.cmdline_ptr) {
> -		pr_err("Command line not included in the provided image\n");
> -		return -EINVAL;
> +		if (!kimage->arch.cmdline_ptr) {
> +			pr_err("Command line not included in the provided image\n");
> +			return -EINVAL;
> +		}
>  	}
>  
>  	/* kexec/kdump need a safe page to save reboot_code_buffer */
> @@ -288,7 +298,8 @@ void machine_kexec(struct kimage *image)
>  	local_irq_disable();
>  
>  	pr_notice("EFI boot flag 0x%lx\n", efi_boot);
> -	pr_notice("Command line at 0x%lx\n", cmdline_ptr);
> +	pr_notice("Command line addr at 0x%lx\n", cmdline_ptr);
> +	pr_notice("Command line at %s\n", (char *)cmdline_ptr);

The printed message doesn't match meaning of the pointer: you're
printing the content of cmdline_ptr, instead of its address, thus
"Command line at" sounds confusing to me.

Furthermore, this chunk isn't related to "support for kexec_file", I
think it's better to separate it into another patch (or even another
series).

>  	pr_notice("System table at 0x%lx\n", systable_ptr);
>  	pr_notice("We will call new kernel at 0x%lx\n", start_addr);
>  	pr_notice("Bye ...\n");

Best regards,
Yao Zi

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 3/6] LoongArch/kexec_file: Add initrd loading
  2025-08-11  9:26 ` [PATCH 3/6] LoongArch/kexec_file: Add initrd loading Youling Tang
  2025-08-11 14:12   ` Huacai Chen
@ 2025-08-11 17:58   ` Yao Zi
  2025-08-12  4:05     ` Youling Tang
  1 sibling, 1 reply; 30+ messages in thread
From: Yao Zi @ 2025-08-11 17:58 UTC (permalink / raw)
  To: Youling Tang, Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

On Mon, Aug 11, 2025 at 05:26:56PM +0800, Youling Tang wrote:
> From: Youling Tang <tangyouling@kylinos.cn>
> 
> Add inird loading support and pass it to the second kernel via the
> cmdline 'initrd=start,size'.

I think This won't work if the exec'ed kernel enables
CONFIG_CMDLINE_FORCE. Is it possible to mimic libstub's behavior of
installing a configuration table LINUX_EFI_INITRD_MEDIA_GUID?

>
> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> ---
>  arch/loongarch/kernel/machine_kexec_file.c | 71 ++++++++++++++++++++++
>  1 file changed, 71 insertions(+)
> 
> diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
> index bc91ae0afa4c..e1240644f529 100644
> --- a/arch/loongarch/kernel/machine_kexec_file.c
> +++ b/arch/loongarch/kernel/machine_kexec_file.c
> @@ -34,13 +34,84 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
>  	return kexec_image_post_load_cleanup_default(image);
>  }
>  
> +/* Adds the "initrd=start,size" command line parameter to command line. */
> +static void cmdline_add_initrd(struct kimage *image, unsigned long *cmdline_tmplen,
> +				char *modified_cmdline, unsigned long initrd)
> +{
> +	int initrd_strlen;
> +
> +	initrd_strlen = sprintf(modified_cmdline + (*cmdline_tmplen), "initrd=0x%lx,0x%lx ",

modified_cmdline is allocated as COMMAND_LINE_SIZE bytes, thus I think
it's possible to overflow the buffer.

> +		initrd, image->initrd_buf_len);
> +	*cmdline_tmplen += initrd_strlen;
> +}
> +
> +/*
> + * Tries to add the initrd to the image. If it is not possible to find
> + * valid locations, this function will undo changes to the image and return non
> + * zero.
> + */
>  int load_other_segments(struct kimage *image,
>  			unsigned long kernel_load_addr,
>  			unsigned long kernel_size,
>  			char *initrd, unsigned long initrd_len,
>  			char *cmdline, unsigned long cmdline_len)
>  {
> +	struct kexec_buf kbuf;
> +	unsigned long orig_segments = image->nr_segments;
> +	char *modified_cmdline = NULL;
> +	unsigned long cmdline_tmplen = 0;
> +	unsigned long initrd_load_addr = 0;
> +	int ret = 0;
> +
> +
> +	kbuf.image = image;
> +	/* not allocate anything below the kernel */
> +	kbuf.buf_min = kernel_load_addr + kernel_size;
> +
> +	modified_cmdline = kzalloc(COMMAND_LINE_SIZE, GFP_KERNEL);
> +	if (!modified_cmdline)
> +		return -EINVAL;
> +
> +	/* Ensure it's nul terminated */
> +	modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
> +
> +	/* load initrd */
> +	if (initrd) {
> +		kbuf.buffer = initrd;
> +		kbuf.bufsz = initrd_len;
> +		kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> +		kbuf.memsz = initrd_len;
> +		kbuf.buf_align = 0;
> +		/* within 1GB-aligned window of up to 32GB in size */
> +		kbuf.buf_max = round_down(kernel_load_addr, SZ_1G)
> +						+ (unsigned long)SZ_1G * 32;
> +		kbuf.top_down = false;
> +
> +		ret = kexec_add_buffer(&kbuf);
> +		if (ret)
> +			goto out_err;
> +		initrd_load_addr = kbuf.mem;
> +
> +		kexec_dprintk("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
> +			      initrd_load_addr, kbuf.bufsz, kbuf.memsz);
> +
> +		/* Add the initrd=start,size parameter to the command line */
> +		cmdline_add_initrd(image, &cmdline_tmplen, modified_cmdline, initrd_load_addr);
> +	}
> +
> +	if (cmdline_len + cmdline_tmplen > COMMAND_LINE_SIZE) {

It's too later to check for overflowing here, where the data after
modified_cmdline may already be overwritten.

> +		pr_err("Appending kdump cmdline exceeds cmdline size\n");

I think load_other_segments could be invoked without kdump involved. If
that's correct, this message is inaccurate.

> +		ret = -EINVAL;
> +		goto out_err;
> +	}

Regards,
Yao Zi

> +	memcpy(modified_cmdline + cmdline_tmplen, cmdline, cmdline_len);
> +	cmdline = modified_cmdline;
>  	image->arch.cmdline_ptr = (unsigned long)cmdline;
>  
>  	return 0;
> +
> +out_err:
> +	image->nr_segments = orig_segments;
> +	kfree(modified_cmdline);
> +	return ret;
>  }
> -- 
> 2.34.1
> 
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-11 14:07   ` Huacai Chen
@ 2025-08-12  1:21     ` Youling Tang
  2025-08-12  1:53       ` Yanteng Si
  2025-08-12  2:53       ` Huacai Chen
  0 siblings, 2 replies; 30+ messages in thread
From: Youling Tang @ 2025-08-12  1:21 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

Hi, Huacai
On 2025/8/11 22:07, Huacai Chen wrote:
> Hi, Youling,
>
> On Mon, Aug 11, 2025 at 5:28 PM Youling Tang <youling.tang@linux.dev> wrote:
>> From: Youling Tang <tangyouling@kylinos.cn>
>>
>> This patch adds support for kexec_file on LoongArch.
>>
>> The image_load() as two parts:
>> - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
>> - the second part loads other segments (eg: initrd, cmdline)
>>
>> Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images are supported,
>> but ELF format is not supported.
>>
>> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
>> ---
>>   arch/loongarch/Kconfig                     |   8 ++
>>   arch/loongarch/include/asm/image.h         |  18 ++++
>>   arch/loongarch/include/asm/kexec.h         |  12 +++
>>   arch/loongarch/kernel/Makefile             |   1 +
>>   arch/loongarch/kernel/kexec_image.c        | 112 +++++++++++++++++++++
>>   arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
>>   arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
>>   7 files changed, 219 insertions(+), 11 deletions(-)
>>   create mode 100644 arch/loongarch/kernel/kexec_image.c
>>   create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
>>
>> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
>> index f0abc38c40ac..fd50c83f7827 100644
>> --- a/arch/loongarch/Kconfig
>> +++ b/arch/loongarch/Kconfig
>> @@ -625,6 +625,14 @@ config CPU_HAS_PREFETCH
>>   config ARCH_SUPPORTS_KEXEC
>>          def_bool y
>>
>> +config ARCH_SUPPORTS_KEXEC_FILE
>> +       def_bool 64BIT
>> +
>> +config ARCH_SELECTS_KEXEC_FILE
>> +       def_bool y
>> +       depends on KEXEC_FILE
>> +       select HAVE_IMA_KEXEC if IMA
>> +
>>   config ARCH_SUPPORTS_CRASH_DUMP
>>          def_bool y
>>
>> diff --git a/arch/loongarch/include/asm/image.h b/arch/loongarch/include/asm/image.h
>> index 1f090736e71d..829e1ecb1f5d 100644
>> --- a/arch/loongarch/include/asm/image.h
>> +++ b/arch/loongarch/include/asm/image.h
>> @@ -36,5 +36,23 @@ struct loongarch_image_header {
>>          uint32_t pe_header;
>>   };
>>
>> +static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'};
>> +static const uint8_t loongarch_pe_machtype[6] = {'P', 'E', 0x0, 0x0, 0x64, 0x62};
>> +
>> +/**
>> + * loongarch_header_check_pe_sig - Helper to check the loongarch image header.
>> + *
>> + * Returns non-zero if 'MZ' signature is found.
>> + */
>> +
>> +static inline int loongarch_header_check_pe_sig(const struct loongarch_image_header *h)
>> +{
>> +       if (!h)
>> +               return 0;
>> +
>> +       return (h->pe_sig[0] == loongarch_image_pe_sig[0]
>> +               && h->pe_sig[1] == loongarch_image_pe_sig[1]);
>> +}
>> +
>>   #endif /* __ASSEMBLY__ */
>>   #endif /* __ASM_IMAGE_H */
>> diff --git a/arch/loongarch/include/asm/kexec.h b/arch/loongarch/include/asm/kexec.h
>> index cf95cd3eb2de..3ef8517a3670 100644
>> --- a/arch/loongarch/include/asm/kexec.h
>> +++ b/arch/loongarch/include/asm/kexec.h
>> @@ -41,6 +41,18 @@ struct kimage_arch {
>>          unsigned long systable_ptr;
>>   };
>>
>> +#ifdef CONFIG_KEXEC_FILE
>> +extern const struct kexec_file_ops kexec_image_ops;
>> +
>> +int arch_kimage_file_post_load_cleanup(struct kimage *image);
>> +#define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup
>> +
>> +extern int load_other_segments(struct kimage *image,
>> +               unsigned long kernel_load_addr, unsigned long kernel_size,
>> +               char *initrd, unsigned long initrd_len,
>> +               char *cmdline, unsigned long cmdline_len);
> I think the RISC-V naming "load_extra_segments" is better.
This name is also fine, but I prefer it to be consistent with
that in kexec-tools.
>
>> +#endif
>> +
>>   typedef void (*do_kexec_t)(unsigned long efi_boot,
>>                             unsigned long cmdline_ptr,
>>                             unsigned long systable_ptr,
>> diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
>> index 6f5a4574a911..bd9405ee3888 100644
>> --- a/arch/loongarch/kernel/Makefile
>> +++ b/arch/loongarch/kernel/Makefile
>> @@ -62,6 +62,7 @@ obj-$(CONFIG_MAGIC_SYSRQ)     += sysrq.o
>>   obj-$(CONFIG_RELOCATABLE)      += relocate.o
>>
>>   obj-$(CONFIG_KEXEC_CORE)       += machine_kexec.o relocate_kernel.o
>> +obj-$(CONFIG_KEXEC_FILE)       += machine_kexec_file.o kexec_image.o
> We only support the efi format, so we don't need to split a
> kexec_image.c like RISC-V, just put everything into
> machine_kexec_file.c is OK.
I hope it is separated and consistent with other architectures.
For instance, arm64 only supports one type.

Youling.
>
> Huacai
>
>>   obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
>>
>>   obj-$(CONFIG_UNWINDER_GUESS)   += unwind_guess.o
>> diff --git a/arch/loongarch/kernel/kexec_image.c b/arch/loongarch/kernel/kexec_image.c
>> new file mode 100644
>> index 000000000000..fdd1845b4e2e
>> --- /dev/null
>> +++ b/arch/loongarch/kernel/kexec_image.c
>> @@ -0,0 +1,112 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Kexec image loader for LoongArch
>> +
>> + * Author: Youling Tang <tangyouling@kylinos.cn>
>> + * Copyright (C) 2025 KylinSoft Corporation.
>> + */
>> +
>> +#define pr_fmt(fmt)    "kexec_file(Image): " fmt
>> +
>> +#include <linux/err.h>
>> +#include <linux/errno.h>
>> +#include <linux/kernel.h>
>> +#include <linux/kexec.h>
>> +#include <linux/pe.h>
>> +#include <linux/string.h>
>> +#include <asm/byteorder.h>
>> +#include <asm/cpufeature.h>
>> +#include <asm/image.h>
>> +
>> +static int image_probe(const char *kernel_buf, unsigned long kernel_len)
>> +{
>> +       const struct loongarch_image_header *h =
>> +               (const struct loongarch_image_header *)(kernel_buf);
>> +
>> +       if (!h || (kernel_len < sizeof(*h))) {
>> +               pr_err("No loongarch image header.\n");
>> +               return -EINVAL;
>> +       }
>> +
>> +       if (!loongarch_header_check_pe_sig(h)) {
>> +               pr_err("Bad loongarch PE image header.\n");
>> +               return -EINVAL;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static void *image_load(struct kimage *image,
>> +                               char *kernel, unsigned long kernel_len,
>> +                               char *initrd, unsigned long initrd_len,
>> +                               char *cmdline, unsigned long cmdline_len)
>> +{
>> +       struct loongarch_image_header *h;
>> +       struct kexec_buf kbuf;
>> +       unsigned long text_offset, kernel_segment_number;
>> +       struct kexec_segment *kernel_segment;
>> +       int ret;
>> +
>> +       h = (struct loongarch_image_header *)kernel;
>> +       if (!h->image_size)
>> +               return ERR_PTR(-EINVAL);
>> +
>> +       /* Load the kernel */
>> +       kbuf.image = image;
>> +       kbuf.buf_min = 0;
>> +       kbuf.buf_max = ULONG_MAX;
>> +       kbuf.top_down = false;
>> +
>> +       kbuf.buffer = kernel;
>> +       kbuf.bufsz = kernel_len;
>> +       kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
>> +       kbuf.memsz = le64_to_cpu(h->image_size);
>> +       text_offset = le64_to_cpu(h->text_offset);
>> +       kbuf.buf_align = SZ_2M;
>> +
>> +       kernel_segment_number = image->nr_segments;
>> +
>> +       /*
>> +        * The location of the kernel segment may make it impossible to satisfy
>> +        * the other segment requirements, so we try repeatedly to find a
>> +        * location that will work.
>> +        */
>> +       while ((ret = kexec_add_buffer(&kbuf)) == 0) {
>> +               /* Try to load additional data */
>> +               kernel_segment = &image->segment[kernel_segment_number];
>> +               ret = load_other_segments(image, kernel_segment->mem,
>> +                                         kernel_segment->memsz, initrd,
>> +                                         initrd_len, cmdline, cmdline_len);
>> +               if (!ret)
>> +                       break;
>> +
>> +               /*
>> +                * We couldn't find space for the other segments; erase the
>> +                * kernel segment and try the next available hole.
>> +                */
>> +               image->nr_segments -= 1;
>> +               kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
>> +               kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
>> +       }
>> +
>> +       if (ret) {
>> +               pr_err("Could not find any suitable kernel location!");
>> +               return ERR_PTR(ret);
>> +       }
>> +
>> +       kernel_segment = &image->segment[kernel_segment_number];
>> +
>> +       /* Make sure the second kernel jumps to the correct "kernel_entry". */
>> +       image->start = kernel_segment->mem + h->kernel_entry - text_offset;
>> +
>> +       kexec_dprintk("Loaded kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
>> +                     kernel_segment->mem, kbuf.bufsz,
>> +                     kernel_segment->memsz);
>> +
>> +       return NULL;
>> +}
>> +
>> +const struct kexec_file_ops kexec_image_ops = {
>> +       .probe = image_probe,
>> +       .load = image_load,
>> +};
>> diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/machine_kexec.c
>> index f9381800e291..008f43e26120 100644
>> --- a/arch/loongarch/kernel/machine_kexec.c
>> +++ b/arch/loongarch/kernel/machine_kexec.c
>> @@ -70,18 +70,28 @@ int machine_kexec_prepare(struct kimage *kimage)
>>          kimage->arch.efi_boot = fw_arg0;
>>          kimage->arch.systable_ptr = fw_arg2;
>>
>> -       /* Find the command line */
>> -       for (i = 0; i < kimage->nr_segments; i++) {
>> -               if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) {
>> -                       if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
>> -                               kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
>> -                       break;
>> +       if (kimage->file_mode == 1) {
>> +               /*
>> +                * kimage->cmdline_buf will be released in kexec_file_load, so copy to
>> +                * the KEXEC_CMDLINE_ADDR safe area.
>> +                */
>> +               memcpy((void *)KEXEC_CMDLINE_ADDR, (void *)kimage->arch.cmdline_ptr,
>> +                                       strlen((char *)kimage->arch.cmdline_ptr) + 1);
>> +               kimage->arch.cmdline_ptr = (unsigned long)KEXEC_CMDLINE_ADDR;
>> +       } else {
>> +               /* Find the command line */
>> +               for (i = 0; i < kimage->nr_segments; i++) {
>> +                       if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) {
>> +                               if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
>> +                                       kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
>> +                               break;
>> +                       }
>>                  }
>> -       }
>>
>> -       if (!kimage->arch.cmdline_ptr) {
>> -               pr_err("Command line not included in the provided image\n");
>> -               return -EINVAL;
>> +               if (!kimage->arch.cmdline_ptr) {
>> +                       pr_err("Command line not included in the provided image\n");
>> +                       return -EINVAL;
>> +               }
>>          }
>>
>>          /* kexec/kdump need a safe page to save reboot_code_buffer */
>> @@ -288,7 +298,8 @@ void machine_kexec(struct kimage *image)
>>          local_irq_disable();
>>
>>          pr_notice("EFI boot flag 0x%lx\n", efi_boot);
>> -       pr_notice("Command line at 0x%lx\n", cmdline_ptr);
>> +       pr_notice("Command line addr at 0x%lx\n", cmdline_ptr);
>> +       pr_notice("Command line at %s\n", (char *)cmdline_ptr);
>>          pr_notice("System table at 0x%lx\n", systable_ptr);
>>          pr_notice("We will call new kernel at 0x%lx\n", start_addr);
>>          pr_notice("Bye ...\n");
>> diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
>> new file mode 100644
>> index 000000000000..bc91ae0afa4c
>> --- /dev/null
>> +++ b/arch/loongarch/kernel/machine_kexec_file.c
>> @@ -0,0 +1,46 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * kexec_file for LoongArch
>> + *
>> + * Author: Youling Tang <tangyouling@kylinos.cn>
>> + * Copyright (C) 2025 KylinSoft Corporation.
>> + *
>> + * Most code is derived from LoongArch port of kexec-tools
>> + */
>> +
>> +#define pr_fmt(fmt) "kexec_file: " fmt
>> +
>> +#include <linux/ioport.h>
>> +#include <linux/kernel.h>
>> +#include <linux/kexec.h>
>> +#include <linux/memblock.h>
>> +#include <linux/slab.h>
>> +#include <linux/string.h>
>> +#include <linux/types.h>
>> +#include <linux/vmalloc.h>
>> +#include <asm/bootinfo.h>
>> +
>> +const struct kexec_file_ops * const kexec_file_loaders[] = {
>> +       &kexec_image_ops,
>> +       NULL
>> +};
>> +
>> +int arch_kimage_file_post_load_cleanup(struct kimage *image)
>> +{
>> +       vfree(image->elf_headers);
>> +       image->elf_headers = NULL;
>> +       image->elf_headers_sz = 0;
>> +
>> +       return kexec_image_post_load_cleanup_default(image);
>> +}
>> +
>> +int load_other_segments(struct kimage *image,
>> +                       unsigned long kernel_load_addr,
>> +                       unsigned long kernel_size,
>> +                       char *initrd, unsigned long initrd_len,
>> +                       char *cmdline, unsigned long cmdline_len)
>> +{
>> +       image->arch.cmdline_ptr = (unsigned long)cmdline;
>> +
>> +       return 0;
>> +}
>> --
>> 2.34.1
>>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-12  1:21     ` Youling Tang
@ 2025-08-12  1:53       ` Yanteng Si
  2025-08-12  9:32         ` Youling Tang
  2025-08-12  2:53       ` Huacai Chen
  1 sibling, 1 reply; 30+ messages in thread
From: Yanteng Si @ 2025-08-12  1:53 UTC (permalink / raw)
  To: Youling Tang, Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

在 8/12/25 9:21 AM, Youling Tang 写道:
> Hi, Huacai
> On 2025/8/11 22:07, Huacai Chen wrote:
>> Hi, Youling,
>>
>> On Mon, Aug 11, 2025 at 5:28 PM Youling Tang <youling.tang@linux.dev> wrote:
>>> From: Youling Tang <tangyouling@kylinos.cn>
>>>
>>> This patch adds support for kexec_file on LoongArch.
>>>
>>> The image_load() as two parts:
>>> - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
>>> - the second part loads other segments (eg: initrd, cmdline)
>>>
>>> Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images are supported,
>>> but ELF format is not supported.
>>>
>>> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
>>> ---
>>>   arch/loongarch/Kconfig                     |   8 ++
>>>   arch/loongarch/include/asm/image.h         |  18 ++++
>>>   arch/loongarch/include/asm/kexec.h         |  12 +++
>>>   arch/loongarch/kernel/Makefile             |   1 +
>>>   arch/loongarch/kernel/kexec_image.c        | 112 +++++++++++++++++++++
>>>   arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
>>>   arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
>>>   7 files changed, 219 insertions(+), 11 deletions(-)
>>>   create mode 100644 arch/loongarch/kernel/kexec_image.c
>>>   create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
>>>
>>> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
>>> index f0abc38c40ac..fd50c83f7827 100644
>>> --- a/arch/loongarch/Kconfig
>>> +++ b/arch/loongarch/Kconfig
>>> @@ -625,6 +625,14 @@ config CPU_HAS_PREFETCH
>>>   config ARCH_SUPPORTS_KEXEC
>>>          def_bool y
>>>
>>> +config ARCH_SUPPORTS_KEXEC_FILE
>>> +       def_bool 64BIT
>>> +
>>> +config ARCH_SELECTS_KEXEC_FILE
>>> +       def_bool y
>>> +       depends on KEXEC_FILE
>>> +       select HAVE_IMA_KEXEC if IMA
>>> +
>>>   config ARCH_SUPPORTS_CRASH_DUMP
>>>          def_bool y
>>>
>>> diff --git a/arch/loongarch/include/asm/image.h b/arch/loongarch/include/asm/image.h
>>> index 1f090736e71d..829e1ecb1f5d 100644
>>> --- a/arch/loongarch/include/asm/image.h
>>> +++ b/arch/loongarch/include/asm/image.h
>>> @@ -36,5 +36,23 @@ struct loongarch_image_header {
>>>          uint32_t pe_header;
>>>   };
>>>
>>> +static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'};
>>> +static const uint8_t loongarch_pe_machtype[6] = {'P', 'E', 0x0, 0x0, 0x64, 0x62};
>>> +
>>> +/**
>>> + * loongarch_header_check_pe_sig - Helper to check the loongarch image header.
>>> + *
>>> + * Returns non-zero if 'MZ' signature is found.
>>> + */
>>> +
>>> +static inline int loongarch_header_check_pe_sig(const struct loongarch_image_header *h)
>>> +{
>>> +       if (!h)
>>> +               return 0;
>>> +
>>> +       return (h->pe_sig[0] == loongarch_image_pe_sig[0]
>>> +               && h->pe_sig[1] == loongarch_image_pe_sig[1]);
>>> +}
>>> +
>>>   #endif /* __ASSEMBLY__ */
>>>   #endif /* __ASM_IMAGE_H */
>>> diff --git a/arch/loongarch/include/asm/kexec.h b/arch/loongarch/include/asm/kexec.h
>>> index cf95cd3eb2de..3ef8517a3670 100644
>>> --- a/arch/loongarch/include/asm/kexec.h
>>> +++ b/arch/loongarch/include/asm/kexec.h
>>> @@ -41,6 +41,18 @@ struct kimage_arch {
>>>          unsigned long systable_ptr;
>>>   };
>>>
>>> +#ifdef CONFIG_KEXEC_FILE
>>> +extern const struct kexec_file_ops kexec_image_ops;
>>> +
>>> +int arch_kimage_file_post_load_cleanup(struct kimage *image);
>>> +#define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup
>>> +
>>> +extern int load_other_segments(struct kimage *image,
>>> +               unsigned long kernel_load_addr, unsigned long kernel_size,
>>> +               char *initrd, unsigned long initrd_len,
>>> +               char *cmdline, unsigned long cmdline_len);
>> I think the RISC-V naming "load_extra_segments" is better.
> This name is also fine, but I prefer it to be consistent with
> that in kexec-tools.
I have looked at the code of kexec-tools, and it seems that you referenced a great deal of ARM code when implementing the LoongArch part.


>>
>>> +#endif
>>> +
>>>   typedef void (*do_kexec_t)(unsigned long efi_boot,
>>>                             unsigned long cmdline_ptr,
>>>                             unsigned long systable_ptr,
>>> diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
>>> index 6f5a4574a911..bd9405ee3888 100644
>>> --- a/arch/loongarch/kernel/Makefile
>>> +++ b/arch/loongarch/kernel/Makefile
>>> @@ -62,6 +62,7 @@ obj-$(CONFIG_MAGIC_SYSRQ)     += sysrq.o
>>>   obj-$(CONFIG_RELOCATABLE)      += relocate.o
>>>
>>>   obj-$(CONFIG_KEXEC_CORE)       += machine_kexec.o relocate_kernel.o
>>> +obj-$(CONFIG_KEXEC_FILE)       += machine_kexec_file.o kexec_image.o
>> We only support the efi format, so we don't need to split a
>> kexec_image.c like RISC-V, just put everything into
>> machine_kexec_file.c is OK.
> I hope it is separated and consistent with other architectures.
> For instance, arm64 only supports one type.
The ARM64 architecture has a long history, and we shouldn't be constrained by it.


Thanks,
Yanteng
>
> Youling.
>>
>> Huacai

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 3/6] LoongArch/kexec_file: Add initrd loading
  2025-08-11 14:12   ` Huacai Chen
@ 2025-08-12  2:38     ` Youling Tang
  2025-08-12  3:03       ` Huacai Chen
  0 siblings, 1 reply; 30+ messages in thread
From: Youling Tang @ 2025-08-12  2:38 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

Hi, Huacai
On 2025/8/11 22:12, Huacai Chen wrote:
> Hi, Youling,
>
> On Mon, Aug 11, 2025 at 5:28 PM Youling Tang <youling.tang@linux.dev> wrote:
>> From: Youling Tang <tangyouling@kylinos.cn>
>>
>> Add inird loading support and pass it to the second kernel via the
>> cmdline 'initrd=start,size'.
> I think Patch-3 and Patch-5 should be merged into Patch-2.
Not all cases require loading initrd, so Patch-2 is a runnable basic patch.
Separating it into different patches makes it easier to understand and
review the code.

Patch-5 coming out separately can better illustrate the role of "mem"
parameters in capturing the kernel.

Youling.
>
> Huacai
>
>> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
>> ---
>>   arch/loongarch/kernel/machine_kexec_file.c | 71 ++++++++++++++++++++++
>>   1 file changed, 71 insertions(+)
>>
>> diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
>> index bc91ae0afa4c..e1240644f529 100644
>> --- a/arch/loongarch/kernel/machine_kexec_file.c
>> +++ b/arch/loongarch/kernel/machine_kexec_file.c
>> @@ -34,13 +34,84 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
>>          return kexec_image_post_load_cleanup_default(image);
>>   }
>>
>> +/* Adds the "initrd=start,size" command line parameter to command line. */
>> +static void cmdline_add_initrd(struct kimage *image, unsigned long *cmdline_tmplen,
>> +                               char *modified_cmdline, unsigned long initrd)
>> +{
>> +       int initrd_strlen;
>> +
>> +       initrd_strlen = sprintf(modified_cmdline + (*cmdline_tmplen), "initrd=0x%lx,0x%lx ",
>> +               initrd, image->initrd_buf_len);
>> +       *cmdline_tmplen += initrd_strlen;
>> +}
>> +
>> +/*
>> + * Tries to add the initrd to the image. If it is not possible to find
>> + * valid locations, this function will undo changes to the image and return non
>> + * zero.
>> + */
>>   int load_other_segments(struct kimage *image,
>>                          unsigned long kernel_load_addr,
>>                          unsigned long kernel_size,
>>                          char *initrd, unsigned long initrd_len,
>>                          char *cmdline, unsigned long cmdline_len)
>>   {
>> +       struct kexec_buf kbuf;
>> +       unsigned long orig_segments = image->nr_segments;
>> +       char *modified_cmdline = NULL;
>> +       unsigned long cmdline_tmplen = 0;
>> +       unsigned long initrd_load_addr = 0;
>> +       int ret = 0;
>> +
>> +
>> +       kbuf.image = image;
>> +       /* not allocate anything below the kernel */
>> +       kbuf.buf_min = kernel_load_addr + kernel_size;
>> +
>> +       modified_cmdline = kzalloc(COMMAND_LINE_SIZE, GFP_KERNEL);
>> +       if (!modified_cmdline)
>> +               return -EINVAL;
>> +
>> +       /* Ensure it's nul terminated */
>> +       modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
>> +
>> +       /* load initrd */
>> +       if (initrd) {
>> +               kbuf.buffer = initrd;
>> +               kbuf.bufsz = initrd_len;
>> +               kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
>> +               kbuf.memsz = initrd_len;
>> +               kbuf.buf_align = 0;
>> +               /* within 1GB-aligned window of up to 32GB in size */
>> +               kbuf.buf_max = round_down(kernel_load_addr, SZ_1G)
>> +                                               + (unsigned long)SZ_1G * 32;
>> +               kbuf.top_down = false;
>> +
>> +               ret = kexec_add_buffer(&kbuf);
>> +               if (ret)
>> +                       goto out_err;
>> +               initrd_load_addr = kbuf.mem;
>> +
>> +               kexec_dprintk("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
>> +                             initrd_load_addr, kbuf.bufsz, kbuf.memsz);
>> +
>> +               /* Add the initrd=start,size parameter to the command line */
>> +               cmdline_add_initrd(image, &cmdline_tmplen, modified_cmdline, initrd_load_addr);
>> +       }
>> +
>> +       if (cmdline_len + cmdline_tmplen > COMMAND_LINE_SIZE) {
>> +               pr_err("Appending kdump cmdline exceeds cmdline size\n");
>> +               ret = -EINVAL;
>> +               goto out_err;
>> +       }
>> +       memcpy(modified_cmdline + cmdline_tmplen, cmdline, cmdline_len);
>> +       cmdline = modified_cmdline;
>>          image->arch.cmdline_ptr = (unsigned long)cmdline;
>>
>>          return 0;
>> +
>> +out_err:
>> +       image->nr_segments = orig_segments;
>> +       kfree(modified_cmdline);
>> +       return ret;
>>   }
>> --
>> 2.34.1
>>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-11 17:06   ` Yao Zi
@ 2025-08-12  2:39     ` Huacai Chen
  2025-08-12  7:56       ` Yao Zi
  2025-08-12  6:15     ` Youling Tang
  1 sibling, 1 reply; 30+ messages in thread
From: Huacai Chen @ 2025-08-12  2:39 UTC (permalink / raw)
  To: Yao Zi
  Cc: Youling Tang, WANG Xuerui, Baoquan He, kexec, loongarch,
	linux-kernel, Youling Tang

On Tue, Aug 12, 2025 at 1:09 AM Yao Zi <ziyao@disroot.org> wrote:
>
> On Mon, Aug 11, 2025 at 05:26:55PM +0800, Youling Tang wrote:
> > From: Youling Tang <tangyouling@kylinos.cn>
> >
> > This patch adds support for kexec_file on LoongArch.
> >
> > The image_load() as two parts:
> > - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
> > - the second part loads other segments (eg: initrd, cmdline)
> >
> > Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images are supported,
> > but ELF format is not supported.
> >
> > Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> > ---
> >  arch/loongarch/Kconfig                     |   8 ++
> >  arch/loongarch/include/asm/image.h         |  18 ++++
> >  arch/loongarch/include/asm/kexec.h         |  12 +++
> >  arch/loongarch/kernel/Makefile             |   1 +
> >  arch/loongarch/kernel/kexec_image.c        | 112 +++++++++++++++++++++
> >  arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
> >  arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
> >  7 files changed, 219 insertions(+), 11 deletions(-)
> >  create mode 100644 arch/loongarch/kernel/kexec_image.c
> >  create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
>
> ...
>
> > diff --git a/arch/loongarch/include/asm/image.h b/arch/loongarch/include/asm/image.h
> > index 1f090736e71d..829e1ecb1f5d 100644
> > --- a/arch/loongarch/include/asm/image.h
> > +++ b/arch/loongarch/include/asm/image.h
> > @@ -36,5 +36,23 @@ struct loongarch_image_header {
> >       uint32_t pe_header;
> >  };
> >
> > +static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'};
> > +static const uint8_t loongarch_pe_machtype[6] = {'P', 'E', 0x0, 0x0, 0x64, 0x62};
>
> loongarch_pe_machtype isn't used at all.
>
> > +
> > +/**
> > + * loongarch_header_check_pe_sig - Helper to check the loongarch image header.
> > + *
> > + * Returns non-zero if 'MZ' signature is found.
> > + */
> > +
> > +static inline int loongarch_header_check_pe_sig(const struct loongarch_image_header *h)
> > +{
> > +     if (!h)
> > +             return 0;
> > +
> > +     return (h->pe_sig[0] == loongarch_image_pe_sig[0]
> > +             && h->pe_sig[1] == loongarch_image_pe_sig[1]);
>
> This could be simplified with a memcmp(). Also, this check isn't strict
> enough: PE files for any architectures, and even legacy MS-DOS COM
> executables all start with "MZ".
>
> > +}
> > +
> >  #endif /* __ASSEMBLY__ */
> >  #endif /* __ASM_IMAGE_H */
>
> ...
>
> > diff --git a/arch/loongarch/kernel/kexec_image.c b/arch/loongarch/kernel/kexec_image.c
> > new file mode 100644
> > index 000000000000..fdd1845b4e2e
> > --- /dev/null
> > +++ b/arch/loongarch/kernel/kexec_image.c
> > @@ -0,0 +1,112 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Kexec image loader for LoongArch
> > +
> > + * Author: Youling Tang <tangyouling@kylinos.cn>
> > + * Copyright (C) 2025 KylinSoft Corporation.
> > + */
> > +
> > +#define pr_fmt(fmt)  "kexec_file(Image): " fmt
> > +
> > +#include <linux/err.h>
> > +#include <linux/errno.h>
> > +#include <linux/kernel.h>
> > +#include <linux/kexec.h>
> > +#include <linux/pe.h>
> > +#include <linux/string.h>
> > +#include <asm/byteorder.h>
> > +#include <asm/cpufeature.h>
> > +#include <asm/image.h>
> > +
> > +static int image_probe(const char *kernel_buf, unsigned long kernel_len)
> > +{
> > +     const struct loongarch_image_header *h =
> > +             (const struct loongarch_image_header *)(kernel_buf);
>
> Parentheses around "kernel_buf" are unnecessary.
>
> > +     if (!h || (kernel_len < sizeof(*h))) {
>
> Comparisons have higher priority than logic operations, so this pair of
> parentheses is redundant, too.
But the kernel coding style suggest to use parentheses in this case.

>
> > +             pr_err("No loongarch image header.\n");
> > +             return -EINVAL;
> > +     }
> > +
> > +     if (!loongarch_header_check_pe_sig(h)) {
> > +             pr_err("Bad loongarch PE image header.\n");
> > +             return -EINVAL;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static void *image_load(struct kimage *image,
> > +                             char *kernel, unsigned long kernel_len,
> > +                             char *initrd, unsigned long initrd_len,
> > +                             char *cmdline, unsigned long cmdline_len)
> > +{
> > +     struct loongarch_image_header *h;
> > +     struct kexec_buf kbuf;
> > +     unsigned long text_offset, kernel_segment_number;
> > +     struct kexec_segment *kernel_segment;
> > +     int ret;
> > +
> > +     h = (struct loongarch_image_header *)kernel;
> > +     if (!h->image_size)
> > +             return ERR_PTR(-EINVAL);
> > +
> > +     /* Load the kernel */
> > +     kbuf.image = image;
> > +     kbuf.buf_min = 0;
> > +     kbuf.buf_max = ULONG_MAX;
> > +     kbuf.top_down = false;
> > +
> > +     kbuf.buffer = kernel;
> > +     kbuf.bufsz = kernel_len;
> > +     kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> > +     kbuf.memsz = le64_to_cpu(h->image_size);
> > +     text_offset = le64_to_cpu(h->text_offset);
> > +     kbuf.buf_align = SZ_2M;
>
> I think this aligment is unnecessary for relocatable LoongArch kernels:
> it should be enough to align to the page size. See also my comments
> below.
>
> > +     kernel_segment_number = image->nr_segments;
> > +
> > +     /*
> > +      * The location of the kernel segment may make it impossible to satisfy
> > +      * the other segment requirements, so we try repeatedly to find a
> > +      * location that will work.
> > +      */
> > +     while ((ret = kexec_add_buffer(&kbuf)) == 0) {
> > +             /* Try to load additional data */
> > +             kernel_segment = &image->segment[kernel_segment_number];
> > +             ret = load_other_segments(image, kernel_segment->mem,
> > +                                       kernel_segment->memsz, initrd,
> > +                                       initrd_len, cmdline, cmdline_len);
> > +             if (!ret)
> > +                     break;
> > +
> > +             /*
> > +              * We couldn't find space for the other segments; erase the
> > +              * kernel segment and try the next available hole.
> > +              */
> > +             image->nr_segments -= 1;
> > +             kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
> > +             kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> > +     }
> > +
> > +     if (ret) {
> > +             pr_err("Could not find any suitable kernel location!");
> > +             return ERR_PTR(ret);
> > +     }
> > +
> > +     kernel_segment = &image->segment[kernel_segment_number];
> > +
> > +     /* Make sure the second kernel jumps to the correct "kernel_entry". */
> > +     image->start = kernel_segment->mem + h->kernel_entry - text_offset;
>
> A non-relocatable loongarch kernel cannot be loaded to arbitrary
> address. Thus this loading function seems to only work for relocatable
> kernels, maybe it's better to leave a comment indicating the limitation.
>
> For now, we don't seem to have a way to find out whether the kernel is
> relocatable (for example, a flag in kernel image header), so it's
> impossible to point out whether the loaded kernel boots fine with
> arbitrary loading address...
>
> > +     kexec_dprintk("Loaded kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
> > +                   kernel_segment->mem, kbuf.bufsz,
> > +                   kernel_segment->memsz);
> > +
> > +     return NULL;
> > +}
> > +
> > +const struct kexec_file_ops kexec_image_ops = {
> > +     .probe = image_probe,
> > +     .load = image_load,
> > +};
> > diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/machine_kexec.c
> > index f9381800e291..008f43e26120 100644
> > --- a/arch/loongarch/kernel/machine_kexec.c
> > +++ b/arch/loongarch/kernel/machine_kexec.c
> > @@ -70,18 +70,28 @@ int machine_kexec_prepare(struct kimage *kimage)
>
> ...
>
> > -     if (!kimage->arch.cmdline_ptr) {
> > -             pr_err("Command line not included in the provided image\n");
> > -             return -EINVAL;
> > +             if (!kimage->arch.cmdline_ptr) {
> > +                     pr_err("Command line not included in the provided image\n");
> > +                     return -EINVAL;
> > +             }
> >       }
> >
> >       /* kexec/kdump need a safe page to save reboot_code_buffer */
> > @@ -288,7 +298,8 @@ void machine_kexec(struct kimage *image)
> >       local_irq_disable();
> >
> >       pr_notice("EFI boot flag 0x%lx\n", efi_boot);
> > -     pr_notice("Command line at 0x%lx\n", cmdline_ptr);
> > +     pr_notice("Command line addr at 0x%lx\n", cmdline_ptr);
> > +     pr_notice("Command line at %s\n", (char *)cmdline_ptr);
>
> The printed message doesn't match meaning of the pointer: you're
> printing the content of cmdline_ptr, instead of its address, thus
> "Command line at" sounds confusing to me.
>
> Furthermore, this chunk isn't related to "support for kexec_file", I
> think it's better to separate it into another patch (or even another
> series).
Separating is not necessary from my point of view, indeed I suggest to
squash patches in this series.

Huacai

>
> >       pr_notice("System table at 0x%lx\n", systable_ptr);
> >       pr_notice("We will call new kernel at 0x%lx\n", start_addr);
> >       pr_notice("Bye ...\n");
>
> Best regards,
> Yao Zi

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-12  1:21     ` Youling Tang
  2025-08-12  1:53       ` Yanteng Si
@ 2025-08-12  2:53       ` Huacai Chen
  1 sibling, 0 replies; 30+ messages in thread
From: Huacai Chen @ 2025-08-12  2:53 UTC (permalink / raw)
  To: Youling Tang
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

On Tue, Aug 12, 2025 at 9:22 AM Youling Tang <youling.tang@linux.dev> wrote:
>
> Hi, Huacai
> On 2025/8/11 22:07, Huacai Chen wrote:
> > Hi, Youling,
> >
> > On Mon, Aug 11, 2025 at 5:28 PM Youling Tang <youling.tang@linux.dev> wrote:
> >> From: Youling Tang <tangyouling@kylinos.cn>
> >>
> >> This patch adds support for kexec_file on LoongArch.
> >>
> >> The image_load() as two parts:
> >> - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
> >> - the second part loads other segments (eg: initrd, cmdline)
> >>
> >> Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images are supported,
> >> but ELF format is not supported.
> >>
> >> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> >> ---
> >>   arch/loongarch/Kconfig                     |   8 ++
> >>   arch/loongarch/include/asm/image.h         |  18 ++++
> >>   arch/loongarch/include/asm/kexec.h         |  12 +++
> >>   arch/loongarch/kernel/Makefile             |   1 +
> >>   arch/loongarch/kernel/kexec_image.c        | 112 +++++++++++++++++++++
> >>   arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
> >>   arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
> >>   7 files changed, 219 insertions(+), 11 deletions(-)
> >>   create mode 100644 arch/loongarch/kernel/kexec_image.c
> >>   create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
> >>
> >> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
> >> index f0abc38c40ac..fd50c83f7827 100644
> >> --- a/arch/loongarch/Kconfig
> >> +++ b/arch/loongarch/Kconfig
> >> @@ -625,6 +625,14 @@ config CPU_HAS_PREFETCH
> >>   config ARCH_SUPPORTS_KEXEC
> >>          def_bool y
> >>
> >> +config ARCH_SUPPORTS_KEXEC_FILE
> >> +       def_bool 64BIT
> >> +
> >> +config ARCH_SELECTS_KEXEC_FILE
> >> +       def_bool y
> >> +       depends on KEXEC_FILE
> >> +       select HAVE_IMA_KEXEC if IMA
> >> +
> >>   config ARCH_SUPPORTS_CRASH_DUMP
> >>          def_bool y
> >>
> >> diff --git a/arch/loongarch/include/asm/image.h b/arch/loongarch/include/asm/image.h
> >> index 1f090736e71d..829e1ecb1f5d 100644
> >> --- a/arch/loongarch/include/asm/image.h
> >> +++ b/arch/loongarch/include/asm/image.h
> >> @@ -36,5 +36,23 @@ struct loongarch_image_header {
> >>          uint32_t pe_header;
> >>   };
> >>
> >> +static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'};
> >> +static const uint8_t loongarch_pe_machtype[6] = {'P', 'E', 0x0, 0x0, 0x64, 0x62};
> >> +
> >> +/**
> >> + * loongarch_header_check_pe_sig - Helper to check the loongarch image header.
> >> + *
> >> + * Returns non-zero if 'MZ' signature is found.
> >> + */
> >> +
> >> +static inline int loongarch_header_check_pe_sig(const struct loongarch_image_header *h)
> >> +{
> >> +       if (!h)
> >> +               return 0;
> >> +
> >> +       return (h->pe_sig[0] == loongarch_image_pe_sig[0]
> >> +               && h->pe_sig[1] == loongarch_image_pe_sig[1]);
> >> +}
> >> +
> >>   #endif /* __ASSEMBLY__ */
> >>   #endif /* __ASM_IMAGE_H */
> >> diff --git a/arch/loongarch/include/asm/kexec.h b/arch/loongarch/include/asm/kexec.h
> >> index cf95cd3eb2de..3ef8517a3670 100644
> >> --- a/arch/loongarch/include/asm/kexec.h
> >> +++ b/arch/loongarch/include/asm/kexec.h
> >> @@ -41,6 +41,18 @@ struct kimage_arch {
> >>          unsigned long systable_ptr;
> >>   };
> >>
> >> +#ifdef CONFIG_KEXEC_FILE
> >> +extern const struct kexec_file_ops kexec_image_ops;
> >> +
> >> +int arch_kimage_file_post_load_cleanup(struct kimage *image);
> >> +#define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup
> >> +
> >> +extern int load_other_segments(struct kimage *image,
> >> +               unsigned long kernel_load_addr, unsigned long kernel_size,
> >> +               char *initrd, unsigned long initrd_len,
> >> +               char *cmdline, unsigned long cmdline_len);
> > I think the RISC-V naming "load_extra_segments" is better.
> This name is also fine, but I prefer it to be consistent with
> that in kexec-tools.
OK, then you can keep your original name.

> >
> >> +#endif
> >> +
> >>   typedef void (*do_kexec_t)(unsigned long efi_boot,
> >>                             unsigned long cmdline_ptr,
> >>                             unsigned long systable_ptr,
> >> diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
> >> index 6f5a4574a911..bd9405ee3888 100644
> >> --- a/arch/loongarch/kernel/Makefile
> >> +++ b/arch/loongarch/kernel/Makefile
> >> @@ -62,6 +62,7 @@ obj-$(CONFIG_MAGIC_SYSRQ)     += sysrq.o
> >>   obj-$(CONFIG_RELOCATABLE)      += relocate.o
> >>
> >>   obj-$(CONFIG_KEXEC_CORE)       += machine_kexec.o relocate_kernel.o
> >> +obj-$(CONFIG_KEXEC_FILE)       += machine_kexec_file.o kexec_image.o
> > We only support the efi format, so we don't need to split a
> > kexec_image.c like RISC-V, just put everything into
> > machine_kexec_file.c is OK.
> I hope it is separated and consistent with other architectures.
> For instance, arm64 only supports one type.
It seems only ARM64 and RISC-V are consistent, x86/powerpc/parisc are not.

Huacai

>
> Youling.
> >
> > Huacai
> >
> >>   obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
> >>
> >>   obj-$(CONFIG_UNWINDER_GUESS)   += unwind_guess.o
> >> diff --git a/arch/loongarch/kernel/kexec_image.c b/arch/loongarch/kernel/kexec_image.c
> >> new file mode 100644
> >> index 000000000000..fdd1845b4e2e
> >> --- /dev/null
> >> +++ b/arch/loongarch/kernel/kexec_image.c
> >> @@ -0,0 +1,112 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * Kexec image loader for LoongArch
> >> +
> >> + * Author: Youling Tang <tangyouling@kylinos.cn>
> >> + * Copyright (C) 2025 KylinSoft Corporation.
> >> + */
> >> +
> >> +#define pr_fmt(fmt)    "kexec_file(Image): " fmt
> >> +
> >> +#include <linux/err.h>
> >> +#include <linux/errno.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/kexec.h>
> >> +#include <linux/pe.h>
> >> +#include <linux/string.h>
> >> +#include <asm/byteorder.h>
> >> +#include <asm/cpufeature.h>
> >> +#include <asm/image.h>
> >> +
> >> +static int image_probe(const char *kernel_buf, unsigned long kernel_len)
> >> +{
> >> +       const struct loongarch_image_header *h =
> >> +               (const struct loongarch_image_header *)(kernel_buf);
> >> +
> >> +       if (!h || (kernel_len < sizeof(*h))) {
> >> +               pr_err("No loongarch image header.\n");
> >> +               return -EINVAL;
> >> +       }
> >> +
> >> +       if (!loongarch_header_check_pe_sig(h)) {
> >> +               pr_err("Bad loongarch PE image header.\n");
> >> +               return -EINVAL;
> >> +       }
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static void *image_load(struct kimage *image,
> >> +                               char *kernel, unsigned long kernel_len,
> >> +                               char *initrd, unsigned long initrd_len,
> >> +                               char *cmdline, unsigned long cmdline_len)
> >> +{
> >> +       struct loongarch_image_header *h;
> >> +       struct kexec_buf kbuf;
> >> +       unsigned long text_offset, kernel_segment_number;
> >> +       struct kexec_segment *kernel_segment;
> >> +       int ret;
> >> +
> >> +       h = (struct loongarch_image_header *)kernel;
> >> +       if (!h->image_size)
> >> +               return ERR_PTR(-EINVAL);
> >> +
> >> +       /* Load the kernel */
> >> +       kbuf.image = image;
> >> +       kbuf.buf_min = 0;
> >> +       kbuf.buf_max = ULONG_MAX;
> >> +       kbuf.top_down = false;
> >> +
> >> +       kbuf.buffer = kernel;
> >> +       kbuf.bufsz = kernel_len;
> >> +       kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> >> +       kbuf.memsz = le64_to_cpu(h->image_size);
> >> +       text_offset = le64_to_cpu(h->text_offset);
> >> +       kbuf.buf_align = SZ_2M;
> >> +
> >> +       kernel_segment_number = image->nr_segments;
> >> +
> >> +       /*
> >> +        * The location of the kernel segment may make it impossible to satisfy
> >> +        * the other segment requirements, so we try repeatedly to find a
> >> +        * location that will work.
> >> +        */
> >> +       while ((ret = kexec_add_buffer(&kbuf)) == 0) {
> >> +               /* Try to load additional data */
> >> +               kernel_segment = &image->segment[kernel_segment_number];
> >> +               ret = load_other_segments(image, kernel_segment->mem,
> >> +                                         kernel_segment->memsz, initrd,
> >> +                                         initrd_len, cmdline, cmdline_len);
> >> +               if (!ret)
> >> +                       break;
> >> +
> >> +               /*
> >> +                * We couldn't find space for the other segments; erase the
> >> +                * kernel segment and try the next available hole.
> >> +                */
> >> +               image->nr_segments -= 1;
> >> +               kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
> >> +               kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> >> +       }
> >> +
> >> +       if (ret) {
> >> +               pr_err("Could not find any suitable kernel location!");
> >> +               return ERR_PTR(ret);
> >> +       }
> >> +
> >> +       kernel_segment = &image->segment[kernel_segment_number];
> >> +
> >> +       /* Make sure the second kernel jumps to the correct "kernel_entry". */
> >> +       image->start = kernel_segment->mem + h->kernel_entry - text_offset;
> >> +
> >> +       kexec_dprintk("Loaded kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
> >> +                     kernel_segment->mem, kbuf.bufsz,
> >> +                     kernel_segment->memsz);
> >> +
> >> +       return NULL;
> >> +}
> >> +
> >> +const struct kexec_file_ops kexec_image_ops = {
> >> +       .probe = image_probe,
> >> +       .load = image_load,
> >> +};
> >> diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/machine_kexec.c
> >> index f9381800e291..008f43e26120 100644
> >> --- a/arch/loongarch/kernel/machine_kexec.c
> >> +++ b/arch/loongarch/kernel/machine_kexec.c
> >> @@ -70,18 +70,28 @@ int machine_kexec_prepare(struct kimage *kimage)
> >>          kimage->arch.efi_boot = fw_arg0;
> >>          kimage->arch.systable_ptr = fw_arg2;
> >>
> >> -       /* Find the command line */
> >> -       for (i = 0; i < kimage->nr_segments; i++) {
> >> -               if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) {
> >> -                       if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
> >> -                               kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
> >> -                       break;
> >> +       if (kimage->file_mode == 1) {
> >> +               /*
> >> +                * kimage->cmdline_buf will be released in kexec_file_load, so copy to
> >> +                * the KEXEC_CMDLINE_ADDR safe area.
> >> +                */
> >> +               memcpy((void *)KEXEC_CMDLINE_ADDR, (void *)kimage->arch.cmdline_ptr,
> >> +                                       strlen((char *)kimage->arch.cmdline_ptr) + 1);
> >> +               kimage->arch.cmdline_ptr = (unsigned long)KEXEC_CMDLINE_ADDR;
> >> +       } else {
> >> +               /* Find the command line */
> >> +               for (i = 0; i < kimage->nr_segments; i++) {
> >> +                       if (!strncmp(bootloader, (char __user *)kimage->segment[i].buf, strlen(bootloader))) {
> >> +                               if (!copy_from_user(cmdline_ptr, kimage->segment[i].buf, COMMAND_LINE_SIZE))
> >> +                                       kimage->arch.cmdline_ptr = (unsigned long)cmdline_ptr;
> >> +                               break;
> >> +                       }
> >>                  }
> >> -       }
> >>
> >> -       if (!kimage->arch.cmdline_ptr) {
> >> -               pr_err("Command line not included in the provided image\n");
> >> -               return -EINVAL;
> >> +               if (!kimage->arch.cmdline_ptr) {
> >> +                       pr_err("Command line not included in the provided image\n");
> >> +                       return -EINVAL;
> >> +               }
> >>          }
> >>
> >>          /* kexec/kdump need a safe page to save reboot_code_buffer */
> >> @@ -288,7 +298,8 @@ void machine_kexec(struct kimage *image)
> >>          local_irq_disable();
> >>
> >>          pr_notice("EFI boot flag 0x%lx\n", efi_boot);
> >> -       pr_notice("Command line at 0x%lx\n", cmdline_ptr);
> >> +       pr_notice("Command line addr at 0x%lx\n", cmdline_ptr);
> >> +       pr_notice("Command line at %s\n", (char *)cmdline_ptr);
> >>          pr_notice("System table at 0x%lx\n", systable_ptr);
> >>          pr_notice("We will call new kernel at 0x%lx\n", start_addr);
> >>          pr_notice("Bye ...\n");
> >> diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
> >> new file mode 100644
> >> index 000000000000..bc91ae0afa4c
> >> --- /dev/null
> >> +++ b/arch/loongarch/kernel/machine_kexec_file.c
> >> @@ -0,0 +1,46 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * kexec_file for LoongArch
> >> + *
> >> + * Author: Youling Tang <tangyouling@kylinos.cn>
> >> + * Copyright (C) 2025 KylinSoft Corporation.
> >> + *
> >> + * Most code is derived from LoongArch port of kexec-tools
> >> + */
> >> +
> >> +#define pr_fmt(fmt) "kexec_file: " fmt
> >> +
> >> +#include <linux/ioport.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/kexec.h>
> >> +#include <linux/memblock.h>
> >> +#include <linux/slab.h>
> >> +#include <linux/string.h>
> >> +#include <linux/types.h>
> >> +#include <linux/vmalloc.h>
> >> +#include <asm/bootinfo.h>
> >> +
> >> +const struct kexec_file_ops * const kexec_file_loaders[] = {
> >> +       &kexec_image_ops,
> >> +       NULL
> >> +};
> >> +
> >> +int arch_kimage_file_post_load_cleanup(struct kimage *image)
> >> +{
> >> +       vfree(image->elf_headers);
> >> +       image->elf_headers = NULL;
> >> +       image->elf_headers_sz = 0;
> >> +
> >> +       return kexec_image_post_load_cleanup_default(image);
> >> +}
> >> +
> >> +int load_other_segments(struct kimage *image,
> >> +                       unsigned long kernel_load_addr,
> >> +                       unsigned long kernel_size,
> >> +                       char *initrd, unsigned long initrd_len,
> >> +                       char *cmdline, unsigned long cmdline_len)
> >> +{
> >> +       image->arch.cmdline_ptr = (unsigned long)cmdline;
> >> +
> >> +       return 0;
> >> +}
> >> --
> >> 2.34.1
> >>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 3/6] LoongArch/kexec_file: Add initrd loading
  2025-08-12  2:38     ` Youling Tang
@ 2025-08-12  3:03       ` Huacai Chen
  0 siblings, 0 replies; 30+ messages in thread
From: Huacai Chen @ 2025-08-12  3:03 UTC (permalink / raw)
  To: Youling Tang
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

On Tue, Aug 12, 2025 at 10:38 AM Youling Tang <youling.tang@linux.dev> wrote:
>
> Hi, Huacai
> On 2025/8/11 22:12, Huacai Chen wrote:
> > Hi, Youling,
> >
> > On Mon, Aug 11, 2025 at 5:28 PM Youling Tang <youling.tang@linux.dev> wrote:
> >> From: Youling Tang <tangyouling@kylinos.cn>
> >>
> >> Add inird loading support and pass it to the second kernel via the
> >> cmdline 'initrd=start,size'.
> > I think Patch-3 and Patch-5 should be merged into Patch-2.
> Not all cases require loading initrd, so Patch-2 is a runnable basic patch.
> Separating it into different patches makes it easier to understand and
> review the code.
Unnecessary, without separating the code is clear enough.

>
> Patch-5 coming out separately can better illustrate the role of "mem"
> parameters in capturing the kernel.
Emm, Patch-5 should be squashed to Patch-4, not Patch-2.

Huacai

>
> Youling.
> >
> > Huacai
> >
> >> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> >> ---
> >>   arch/loongarch/kernel/machine_kexec_file.c | 71 ++++++++++++++++++++++
> >>   1 file changed, 71 insertions(+)
> >>
> >> diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
> >> index bc91ae0afa4c..e1240644f529 100644
> >> --- a/arch/loongarch/kernel/machine_kexec_file.c
> >> +++ b/arch/loongarch/kernel/machine_kexec_file.c
> >> @@ -34,13 +34,84 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
> >>          return kexec_image_post_load_cleanup_default(image);
> >>   }
> >>
> >> +/* Adds the "initrd=start,size" command line parameter to command line. */
> >> +static void cmdline_add_initrd(struct kimage *image, unsigned long *cmdline_tmplen,
> >> +                               char *modified_cmdline, unsigned long initrd)
> >> +{
> >> +       int initrd_strlen;
> >> +
> >> +       initrd_strlen = sprintf(modified_cmdline + (*cmdline_tmplen), "initrd=0x%lx,0x%lx ",
> >> +               initrd, image->initrd_buf_len);
> >> +       *cmdline_tmplen += initrd_strlen;
> >> +}
> >> +
> >> +/*
> >> + * Tries to add the initrd to the image. If it is not possible to find
> >> + * valid locations, this function will undo changes to the image and return non
> >> + * zero.
> >> + */
> >>   int load_other_segments(struct kimage *image,
> >>                          unsigned long kernel_load_addr,
> >>                          unsigned long kernel_size,
> >>                          char *initrd, unsigned long initrd_len,
> >>                          char *cmdline, unsigned long cmdline_len)
> >>   {
> >> +       struct kexec_buf kbuf;
> >> +       unsigned long orig_segments = image->nr_segments;
> >> +       char *modified_cmdline = NULL;
> >> +       unsigned long cmdline_tmplen = 0;
> >> +       unsigned long initrd_load_addr = 0;
> >> +       int ret = 0;
> >> +
> >> +
> >> +       kbuf.image = image;
> >> +       /* not allocate anything below the kernel */
> >> +       kbuf.buf_min = kernel_load_addr + kernel_size;
> >> +
> >> +       modified_cmdline = kzalloc(COMMAND_LINE_SIZE, GFP_KERNEL);
> >> +       if (!modified_cmdline)
> >> +               return -EINVAL;
> >> +
> >> +       /* Ensure it's nul terminated */
> >> +       modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
> >> +
> >> +       /* load initrd */
> >> +       if (initrd) {
> >> +               kbuf.buffer = initrd;
> >> +               kbuf.bufsz = initrd_len;
> >> +               kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> >> +               kbuf.memsz = initrd_len;
> >> +               kbuf.buf_align = 0;
> >> +               /* within 1GB-aligned window of up to 32GB in size */
> >> +               kbuf.buf_max = round_down(kernel_load_addr, SZ_1G)
> >> +                                               + (unsigned long)SZ_1G * 32;
> >> +               kbuf.top_down = false;
> >> +
> >> +               ret = kexec_add_buffer(&kbuf);
> >> +               if (ret)
> >> +                       goto out_err;
> >> +               initrd_load_addr = kbuf.mem;
> >> +
> >> +               kexec_dprintk("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
> >> +                             initrd_load_addr, kbuf.bufsz, kbuf.memsz);
> >> +
> >> +               /* Add the initrd=start,size parameter to the command line */
> >> +               cmdline_add_initrd(image, &cmdline_tmplen, modified_cmdline, initrd_load_addr);
> >> +       }
> >> +
> >> +       if (cmdline_len + cmdline_tmplen > COMMAND_LINE_SIZE) {
> >> +               pr_err("Appending kdump cmdline exceeds cmdline size\n");
> >> +               ret = -EINVAL;
> >> +               goto out_err;
> >> +       }
> >> +       memcpy(modified_cmdline + cmdline_tmplen, cmdline, cmdline_len);
> >> +       cmdline = modified_cmdline;
> >>          image->arch.cmdline_ptr = (unsigned long)cmdline;
> >>
> >>          return 0;
> >> +
> >> +out_err:
> >> +       image->nr_segments = orig_segments;
> >> +       kfree(modified_cmdline);
> >> +       return ret;
> >>   }
> >> --
> >> 2.34.1
> >>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 3/6] LoongArch/kexec_file: Add initrd loading
  2025-08-11 17:58   ` Yao Zi
@ 2025-08-12  4:05     ` Youling Tang
  2025-08-12  6:25       ` Yao Zi
  0 siblings, 1 reply; 30+ messages in thread
From: Youling Tang @ 2025-08-12  4:05 UTC (permalink / raw)
  To: Yao Zi, Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

Hi, Yao
On 2025/8/12 01:58, Yao Zi wrote:
> On Mon, Aug 11, 2025 at 05:26:56PM +0800, Youling Tang wrote:
>> From: Youling Tang <tangyouling@kylinos.cn>
>>
>> Add inird loading support and pass it to the second kernel via the
>> cmdline 'initrd=start,size'.
> I think This won't work if the exec'ed kernel enables
> CONFIG_CMDLINE_FORCE. Is it possible to mimic libstub's behavior of
> installing a configuration table LINUX_EFI_INITRD_MEDIA_GUID?
The command line passed by kexec to the second kernel has no effect if
CONFIG_CMDLINE_FORCE is enabled, which is not quite suitable for the
kexec scenario.

Currently, the initrd, elfcorehdr, and mem parameters will all be passed
through the command line to maintain consistency with the implementation
behavior of kexec-tools. It is possible that the content of systab will
be modified in the future and some parts will be integrated into systab
(the current cmdline mode will be better compatible with the elf kernel).
>
>> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
>> ---
>>   arch/loongarch/kernel/machine_kexec_file.c | 71 ++++++++++++++++++++++
>>   1 file changed, 71 insertions(+)
>>
>> diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
>> index bc91ae0afa4c..e1240644f529 100644
>> --- a/arch/loongarch/kernel/machine_kexec_file.c
>> +++ b/arch/loongarch/kernel/machine_kexec_file.c
>> @@ -34,13 +34,84 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
>>   	return kexec_image_post_load_cleanup_default(image);
>>   }
>>   
>> +/* Adds the "initrd=start,size" command line parameter to command line. */
>> +static void cmdline_add_initrd(struct kimage *image, unsigned long *cmdline_tmplen,
>> +				char *modified_cmdline, unsigned long initrd)
>> +{
>> +	int initrd_strlen;
>> +
>> +	initrd_strlen = sprintf(modified_cmdline + (*cmdline_tmplen), "initrd=0x%lx,0x%lx ",
> modified_cmdline is allocated as COMMAND_LINE_SIZE bytes, thus I think
> it's possible to overflow the buffer.
At this point, modified_cmdline can clearly know that it only stores
the additional commands we add (initrd,mem,elfcorehdr), and will not
exceed COMMAND_LINE_SIZE.
>
>> +		initrd, image->initrd_buf_len);
>> +	*cmdline_tmplen += initrd_strlen;
>> +}
>> +
>> +/*
>> + * Tries to add the initrd to the image. If it is not possible to find
>> + * valid locations, this function will undo changes to the image and return non
>> + * zero.
>> + */
>>   int load_other_segments(struct kimage *image,
>>   			unsigned long kernel_load_addr,
>>   			unsigned long kernel_size,
>>   			char *initrd, unsigned long initrd_len,
>>   			char *cmdline, unsigned long cmdline_len)
>>   {
>> +	struct kexec_buf kbuf;
>> +	unsigned long orig_segments = image->nr_segments;
>> +	char *modified_cmdline = NULL;
>> +	unsigned long cmdline_tmplen = 0;
>> +	unsigned long initrd_load_addr = 0;
>> +	int ret = 0;
>> +
>> +
>> +	kbuf.image = image;
>> +	/* not allocate anything below the kernel */
>> +	kbuf.buf_min = kernel_load_addr + kernel_size;
>> +
>> +	modified_cmdline = kzalloc(COMMAND_LINE_SIZE, GFP_KERNEL);
>> +	if (!modified_cmdline)
>> +		return -EINVAL;
>> +
>> +	/* Ensure it's nul terminated */
>> +	modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
>> +
>> +	/* load initrd */
>> +	if (initrd) {
>> +		kbuf.buffer = initrd;
>> +		kbuf.bufsz = initrd_len;
>> +		kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
>> +		kbuf.memsz = initrd_len;
>> +		kbuf.buf_align = 0;
>> +		/* within 1GB-aligned window of up to 32GB in size */
>> +		kbuf.buf_max = round_down(kernel_load_addr, SZ_1G)
>> +						+ (unsigned long)SZ_1G * 32;
>> +		kbuf.top_down = false;
>> +
>> +		ret = kexec_add_buffer(&kbuf);
>> +		if (ret)
>> +			goto out_err;
>> +		initrd_load_addr = kbuf.mem;
>> +
>> +		kexec_dprintk("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
>> +			      initrd_load_addr, kbuf.bufsz, kbuf.memsz);
>> +
>> +		/* Add the initrd=start,size parameter to the command line */
>> +		cmdline_add_initrd(image, &cmdline_tmplen, modified_cmdline, initrd_load_addr);
>> +	}
>> +
>> +	if (cmdline_len + cmdline_tmplen > COMMAND_LINE_SIZE) {
> It's too later to check for overflowing here, where the data after
> modified_cmdline may already be overwritten.
At this point, we append the original command line to modified_cmdline,
so it is appropriate to determine whether the command line length exceeds
the limit.
>
>> +		pr_err("Appending kdump cmdline exceeds cmdline size\n");
> I think load_other_segments could be invoked without kdump involved. If
> that's correct, this message is inaccurate.
Yes, it should be corrected.


Thanks,
Youling.
>
>> +		ret = -EINVAL;
>> +		goto out_err;
>> +	}
> Regards,
> Yao Zi
>
>> +	memcpy(modified_cmdline + cmdline_tmplen, cmdline, cmdline_len);
>> +	cmdline = modified_cmdline;
>>   	image->arch.cmdline_ptr = (unsigned long)cmdline;
>>   
>>   	return 0;
>> +
>> +out_err:
>> +	image->nr_segments = orig_segments;
>> +	kfree(modified_cmdline);
>> +	return ret;
>>   }
>> -- 
>> 2.34.1
>>
>>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-11 17:06   ` Yao Zi
  2025-08-12  2:39     ` Huacai Chen
@ 2025-08-12  6:15     ` Youling Tang
  2025-08-12  7:06       ` Youling Tang
  1 sibling, 1 reply; 30+ messages in thread
From: Youling Tang @ 2025-08-12  6:15 UTC (permalink / raw)
  To: Yao Zi, Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

Hi, Yao
On 2025/8/12 01:06, Yao Zi wrote:
> On Mon, Aug 11, 2025 at 05:26:55PM +0800, Youling Tang wrote:
>> From: Youling Tang <tangyouling@kylinos.cn>
>>
>> This patch adds support for kexec_file on LoongArch.
>>
>> The image_load() as two parts:
>> - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
>> - the second part loads other segments (eg: initrd, cmdline)
>>
>> Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images are supported,
>> but ELF format is not supported.
>>
>> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
>> ---
>>   arch/loongarch/Kconfig                     |   8 ++
>>   arch/loongarch/include/asm/image.h         |  18 ++++
>>   arch/loongarch/include/asm/kexec.h         |  12 +++
>>   arch/loongarch/kernel/Makefile             |   1 +
>>   arch/loongarch/kernel/kexec_image.c        | 112 +++++++++++++++++++++
>>   arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
>>   arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
>>   7 files changed, 219 insertions(+), 11 deletions(-)
>>   create mode 100644 arch/loongarch/kernel/kexec_image.c
>>   create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
> ...
>
>> diff --git a/arch/loongarch/include/asm/image.h b/arch/loongarch/include/asm/image.h
>> index 1f090736e71d..829e1ecb1f5d 100644
>> --- a/arch/loongarch/include/asm/image.h
>> +++ b/arch/loongarch/include/asm/image.h
>> @@ -36,5 +36,23 @@ struct loongarch_image_header {
>>   	uint32_t pe_header;
>>   };
>>   
>> +static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'};
>> +static const uint8_t loongarch_pe_machtype[6] = {'P', 'E', 0x0, 0x0, 0x64, 0x62};
> loongarch_pe_machtype isn't used at all.
It will be removed.
>
>> +
>> +/**
>> + * loongarch_header_check_pe_sig - Helper to check the loongarch image header.
>> + *
>> + * Returns non-zero if 'MZ' signature is found.
>> + */
>> +
>> +static inline int loongarch_header_check_pe_sig(const struct loongarch_image_header *h)
>> +{
>> +	if (!h)
>> +		return 0;
>> +
>> +	return (h->pe_sig[0] == loongarch_image_pe_sig[0]
>> +		&& h->pe_sig[1] == loongarch_image_pe_sig[1]);
> This could be simplified with a memcmp(). Also, this check isn't strict
> enough: PE files for any architectures, and even legacy MS-DOS COM
> executables all start with "MZ".
>
>> +}
>> +
>>   #endif /* __ASSEMBLY__ */
>>   #endif /* __ASM_IMAGE_H */
> ...
>
>> diff --git a/arch/loongarch/kernel/kexec_image.c b/arch/loongarch/kernel/kexec_image.c
>> new file mode 100644
>> index 000000000000..fdd1845b4e2e
>> --- /dev/null
>> +++ b/arch/loongarch/kernel/kexec_image.c
>> @@ -0,0 +1,112 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Kexec image loader for LoongArch
>> +
>> + * Author: Youling Tang <tangyouling@kylinos.cn>
>> + * Copyright (C) 2025 KylinSoft Corporation.
>> + */
>> +
>> +#define pr_fmt(fmt)	"kexec_file(Image): " fmt
>> +
>> +#include <linux/err.h>
>> +#include <linux/errno.h>
>> +#include <linux/kernel.h>
>> +#include <linux/kexec.h>
>> +#include <linux/pe.h>
>> +#include <linux/string.h>
>> +#include <asm/byteorder.h>
>> +#include <asm/cpufeature.h>
>> +#include <asm/image.h>
>> +
>> +static int image_probe(const char *kernel_buf, unsigned long kernel_len)
>> +{
>> +	const struct loongarch_image_header *h =
>> +		(const struct loongarch_image_header *)(kernel_buf);
> Parentheses around "kernel_buf" are unnecessary.
It will be removed.
>
>> +	if (!h || (kernel_len < sizeof(*h))) {
> Comparisons have higher priority than logic operations, so this pair of
> parentheses is redundant, too.
Yes, but the parentheses will be retained for greater readability.
>
>> +		pr_err("No loongarch image header.\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	if (!loongarch_header_check_pe_sig(h)) {
>> +		pr_err("Bad loongarch PE image header.\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static void *image_load(struct kimage *image,
>> +				char *kernel, unsigned long kernel_len,
>> +				char *initrd, unsigned long initrd_len,
>> +				char *cmdline, unsigned long cmdline_len)
>> +{
>> +	struct loongarch_image_header *h;
>> +	struct kexec_buf kbuf;
>> +	unsigned long text_offset, kernel_segment_number;
>> +	struct kexec_segment *kernel_segment;
>> +	int ret;
>> +
>> +	h = (struct loongarch_image_header *)kernel;
>> +	if (!h->image_size)
>> +		return ERR_PTR(-EINVAL);
>> +
>> +	/* Load the kernel */
>> +	kbuf.image = image;
>> +	kbuf.buf_min = 0;
>> +	kbuf.buf_max = ULONG_MAX;
>> +	kbuf.top_down = false;
>> +
>> +	kbuf.buffer = kernel;
>> +	kbuf.bufsz = kernel_len;
>> +	kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
>> +	kbuf.memsz = le64_to_cpu(h->image_size);
>> +	text_offset = le64_to_cpu(h->text_offset);
>> +	kbuf.buf_align = SZ_2M;
> I think this aligment is unnecessary for relocatable LoongArch kernels:
> it should be enough to align to the page size. See also my comments
> below.
>
>> +	kernel_segment_number = image->nr_segments;
>> +
>> +	/*
>> +	 * The location of the kernel segment may make it impossible to satisfy
>> +	 * the other segment requirements, so we try repeatedly to find a
>> +	 * location that will work.
>> +	 */
>> +	while ((ret = kexec_add_buffer(&kbuf)) == 0) {
>> +		/* Try to load additional data */
>> +		kernel_segment = &image->segment[kernel_segment_number];
>> +		ret = load_other_segments(image, kernel_segment->mem,
>> +					  kernel_segment->memsz, initrd,
>> +					  initrd_len, cmdline, cmdline_len);
>> +		if (!ret)
>> +			break;
>> +
>> +		/*
>> +		 * We couldn't find space for the other segments; erase the
>> +		 * kernel segment and try the next available hole.
>> +		 */
>> +		image->nr_segments -= 1;
>> +		kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
>> +		kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
>> +	}
>> +
>> +	if (ret) {
>> +		pr_err("Could not find any suitable kernel location!");
>> +		return ERR_PTR(ret);
>> +	}
>> +
>> +	kernel_segment = &image->segment[kernel_segment_number];
>> +
>> +	/* Make sure the second kernel jumps to the correct "kernel_entry". */
>> +	image->start = kernel_segment->mem + h->kernel_entry - text_offset;
> A non-relocatable loongarch kernel cannot be loaded to arbitrary
> address. Thus this loading function seems to only work for relocatable
> kernels, maybe it's better to leave a comment indicating the limitation.
>
> For now, we don't seem to have a way to find out whether the kernel is
> relocatable (for example, a flag in kernel image header), so it's
> impossible to point out whether the loaded kernel boots fine with
> arbitrary loading address...
LoongArch enables the relocation of the kernel when the kdump
feature is enabled.

config ARCH_SELECTS_CRASH_DUMP
         def_bool y
         depends on CRASH_DUMP
         select RELOCATABLE

After enabling the relocation, LoongArch is the PIE kernel. For
more details, please refer to commit d8da19fbdedd ("LoongArch:
Add support for kernel relocation")
>> +	kexec_dprintk("Loaded kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
>> +		      kernel_segment->mem, kbuf.bufsz,
>> +		      kernel_segment->memsz);
>> +
>> +	return NULL;
>> +}
>> +
>> +const struct kexec_file_ops kexec_image_ops = {
>> +	.probe = image_probe,
>> +	.load = image_load,
>> +};
>> diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/machine_kexec.c
>> index f9381800e291..008f43e26120 100644
>> --- a/arch/loongarch/kernel/machine_kexec.c
>> +++ b/arch/loongarch/kernel/machine_kexec.c
>> @@ -70,18 +70,28 @@ int machine_kexec_prepare(struct kimage *kimage)
> ...
>
>> -	if (!kimage->arch.cmdline_ptr) {
>> -		pr_err("Command line not included in the provided image\n");
>> -		return -EINVAL;
>> +		if (!kimage->arch.cmdline_ptr) {
>> +			pr_err("Command line not included in the provided image\n");
>> +			return -EINVAL;
>> +		}
>>   	}
>>   
>>   	/* kexec/kdump need a safe page to save reboot_code_buffer */
>> @@ -288,7 +298,8 @@ void machine_kexec(struct kimage *image)
>>   	local_irq_disable();
>>   
>>   	pr_notice("EFI boot flag 0x%lx\n", efi_boot);
>> -	pr_notice("Command line at 0x%lx\n", cmdline_ptr);
>> +	pr_notice("Command line addr at 0x%lx\n", cmdline_ptr);
>> +	pr_notice("Command line at %s\n", (char *)cmdline_ptr);
> The printed message doesn't match meaning of the pointer: you're
> printing the content of cmdline_ptr, instead of its address, thus
> "Command line at" sounds confusing to me.
I will correct it.

Thanks,
Youling.
>
> Furthermore, this chunk isn't related to "support for kexec_file", I
> think it's better to separate it into another patch (or even another
> series).
>
>>   	pr_notice("System table at 0x%lx\n", systable_ptr);
>>   	pr_notice("We will call new kernel at 0x%lx\n", start_addr);
>>   	pr_notice("Bye ...\n");
> Best regards,
> Yao Zi

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 0/6] Add kexec_file support for LoongArch
  2025-08-11 16:20 ` [PATCH 0/6] Add kexec_file support for LoongArch Vincent Li
@ 2025-08-12  6:21   ` Youling Tang
  0 siblings, 0 replies; 30+ messages in thread
From: Youling Tang @ 2025-08-12  6:21 UTC (permalink / raw)
  To: Vincent Li
  Cc: Huacai Chen, WANG Xuerui, Baoquan He, kexec, loongarch,
	linux-kernel, Youling Tang

Hi, Vincent
On 2025/8/12 00:20, Vincent Li wrote:
> Hi Youling,
>
> On Mon, Aug 11, 2025 at 2:28 AM Youling Tang <youling.tang@linux.dev> wrote:
>> From: Youling Tang <tangyouling@kylinos.cn>
>>
>> This patchset implement kexec_file_load() support on LoongArch.
>>
>> This patch series enables us to load the LoongArch vmlinuz.efi or
>> vmlinux.efi by specifying its file decriptor, instead of user-filled
>> buffer via kexec_load() syscall.
>>
>> To use kexec_file_load() system call, instead of kexec_load(), at kexec
>> command, '-s' options must be specified. kexec-tools needs to apply the
>> corresponding patches. These patches can be found in repository [1] and
>> will be submitted to the kexec-tools community later.
>>
>> The basic usage of kexec_file is:
>> 1) Load second kernel image:
>>   # kexec -s -l vmlinuz.efi --initrd=initrd.img --reuse-cmdline
>>
>> 2) Startup second kernel:
>>   # kexec -e
>>
>> For kdump:
>> 1) Load capture kernel image:
>>   # kexec -s -p vmlinuz.efi --initrd=initrd.img --reuse-cmdline
>>
>> 2) Do something to crash, like:
>>   # echo c > /proc/sysrq-trigger
>>
> I am new to this feature but I am interested to test this feature, How
> do I get the second kernel or capture image vmlinux.efi and
> initrd.img, do I need to build them separately and how?
There is no need to build separately. The kernel images and
initrd of the first kernel and the second kernel can be the same
(because LoongArch is a PIE kernel when RELOCATABLE is enabled).

Thanks,
Youling.
>
>> Link:
>> [1] https://github.com/tangyouling/kexec-tools/commits/main/
>>
>> Youling Tang (6):
>>    LoongArch: Add struct loongarch_image_header for kernel image
>>    LoongArch: Add kexec_file support
>>    LoongArch/kexec_file: Add initrd loading
>>    LoongArch/kexec_file: Add crash dump support
>>    LoongArch/kexec_file: Add "mem" parameter to limit memory usage of
>>      kdump kernel
>>    LoongArch: Enable CONFIG_KEXEC_FILE
>>
>>   arch/loongarch/Kconfig                     |   8 +
>>   arch/loongarch/configs/loongson3_defconfig |   1 +
>>   arch/loongarch/include/asm/image.h         |  58 +++++
>>   arch/loongarch/include/asm/kexec.h         |  12 ++
>>   arch/loongarch/kernel/Makefile             |   1 +
>>   arch/loongarch/kernel/kexec_image.c        | 112 ++++++++++
>>   arch/loongarch/kernel/machine_kexec.c      |  33 ++-
>>   arch/loongarch/kernel/machine_kexec_file.c | 234 +++++++++++++++++++++
>>   8 files changed, 448 insertions(+), 11 deletions(-)
>>   create mode 100644 arch/loongarch/include/asm/image.h
>>   create mode 100644 arch/loongarch/kernel/kexec_image.c
>>   create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
>>
>> --
>> 2.34.1
>>
>>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 3/6] LoongArch/kexec_file: Add initrd loading
  2025-08-12  4:05     ` Youling Tang
@ 2025-08-12  6:25       ` Yao Zi
  0 siblings, 0 replies; 30+ messages in thread
From: Yao Zi @ 2025-08-12  6:25 UTC (permalink / raw)
  To: Youling Tang, Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

On Tue, Aug 12, 2025 at 12:05:30PM +0800, Youling Tang wrote:
> Hi, Yao
> On 2025/8/12 01:58, Yao Zi wrote:
> > On Mon, Aug 11, 2025 at 05:26:56PM +0800, Youling Tang wrote:
> > > From: Youling Tang <tangyouling@kylinos.cn>
> > > 
> > > Add inird loading support and pass it to the second kernel via the
> > > cmdline 'initrd=start,size'.
> > I think This won't work if the exec'ed kernel enables
> > CONFIG_CMDLINE_FORCE. Is it possible to mimic libstub's behavior of
> > installing a configuration table LINUX_EFI_INITRD_MEDIA_GUID?
> The command line passed by kexec to the second kernel has no effect if
> CONFIG_CMDLINE_FORCE is enabled, which is not quite suitable for the
> kexec scenario.
> 
> Currently, the initrd, elfcorehdr, and mem parameters will all be passed
> through the command line to maintain consistency with the implementation
> behavior of kexec-tools. It is possible that the content of systab will
> be modified in the future and some parts will be integrated into systab
> (the current cmdline mode will be better compatible with the elf kernel).
> > 
> > > Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> > > ---
> > >   arch/loongarch/kernel/machine_kexec_file.c | 71 ++++++++++++++++++++++
> > >   1 file changed, 71 insertions(+)
> > > 
> > > diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
> > > index bc91ae0afa4c..e1240644f529 100644
> > > --- a/arch/loongarch/kernel/machine_kexec_file.c
> > > +++ b/arch/loongarch/kernel/machine_kexec_file.c
> > > @@ -34,13 +34,84 @@ int arch_kimage_file_post_load_cleanup(struct kimage *image)
> > >   	return kexec_image_post_load_cleanup_default(image);
> > >   }
> > > +/* Adds the "initrd=start,size" command line parameter to command line. */
> > > +static void cmdline_add_initrd(struct kimage *image, unsigned long *cmdline_tmplen,
> > > +				char *modified_cmdline, unsigned long initrd)
> > > +{
> > > +	int initrd_strlen;
> > > +
> > > +	initrd_strlen = sprintf(modified_cmdline + (*cmdline_tmplen), "initrd=0x%lx,0x%lx ",
> > modified_cmdline is allocated as COMMAND_LINE_SIZE bytes, thus I think
> > it's possible to overflow the buffer.
> At this point, modified_cmdline can clearly know that it only stores
> the additional commands we add (initrd,mem,elfcorehdr), and will not
> exceed COMMAND_LINE_SIZE.
> > 
> > > +		initrd, image->initrd_buf_len);
> > > +	*cmdline_tmplen += initrd_strlen;
> > > +}
> > > +
> > > +/*
> > > + * Tries to add the initrd to the image. If it is not possible to find
> > > + * valid locations, this function will undo changes to the image and return non
> > > + * zero.
> > > + */
> > >   int load_other_segments(struct kimage *image,
> > >   			unsigned long kernel_load_addr,
> > >   			unsigned long kernel_size,
> > >   			char *initrd, unsigned long initrd_len,
> > >   			char *cmdline, unsigned long cmdline_len)
> > >   {
> > > +	struct kexec_buf kbuf;
> > > +	unsigned long orig_segments = image->nr_segments;
> > > +	char *modified_cmdline = NULL;
> > > +	unsigned long cmdline_tmplen = 0;
> > > +	unsigned long initrd_load_addr = 0;
> > > +	int ret = 0;
> > > +
> > > +
> > > +	kbuf.image = image;
> > > +	/* not allocate anything below the kernel */
> > > +	kbuf.buf_min = kernel_load_addr + kernel_size;
> > > +
> > > +	modified_cmdline = kzalloc(COMMAND_LINE_SIZE, GFP_KERNEL);
> > > +	if (!modified_cmdline)
> > > +		return -EINVAL;
> > > +
> > > +	/* Ensure it's nul terminated */
> > > +	modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
> > > +
> > > +	/* load initrd */
> > > +	if (initrd) {
> > > +		kbuf.buffer = initrd;
> > > +		kbuf.bufsz = initrd_len;
> > > +		kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> > > +		kbuf.memsz = initrd_len;
> > > +		kbuf.buf_align = 0;
> > > +		/* within 1GB-aligned window of up to 32GB in size */
> > > +		kbuf.buf_max = round_down(kernel_load_addr, SZ_1G)
> > > +						+ (unsigned long)SZ_1G * 32;
> > > +		kbuf.top_down = false;
> > > +
> > > +		ret = kexec_add_buffer(&kbuf);
> > > +		if (ret)
> > > +			goto out_err;
> > > +		initrd_load_addr = kbuf.mem;
> > > +
> > > +		kexec_dprintk("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
> > > +			      initrd_load_addr, kbuf.bufsz, kbuf.memsz);
> > > +
> > > +		/* Add the initrd=start,size parameter to the command line */
> > > +		cmdline_add_initrd(image, &cmdline_tmplen, modified_cmdline, initrd_load_addr);
> > > +	}
> > > +
> > > +	if (cmdline_len + cmdline_tmplen > COMMAND_LINE_SIZE) {
> > It's too later to check for overflowing here, where the data after
> > modified_cmdline may already be overwritten.
> At this point, we append the original command line to modified_cmdline,
> so it is appropriate to determine whether the command line length exceeds
> the limit.

Thanks, I misunderstood the code logic: before cmdline_add_initrd
appends new arguments, modified_cmdline is empty instead of containing
a copy of cmdline, so this is fine. Sorry for the noise.

Best regards,
Yao Zi

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-12  6:15     ` Youling Tang
@ 2025-08-12  7:06       ` Youling Tang
  2025-08-12  9:43         ` Yao Zi
  0 siblings, 1 reply; 30+ messages in thread
From: Youling Tang @ 2025-08-12  7:06 UTC (permalink / raw)
  To: Yao Zi, Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

On 2025/8/12 14:15, Youling Tang wrote:
> Hi, Yao
> On 2025/8/12 01:06, Yao Zi wrote:
>> On Mon, Aug 11, 2025 at 05:26:55PM +0800, Youling Tang wrote:
>>> From: Youling Tang <tangyouling@kylinos.cn>
>>>
>>> This patch adds support for kexec_file on LoongArch.
>>>
>>> The image_load() as two parts:
>>> - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
>>> - the second part loads other segments (eg: initrd, cmdline)
>>>
>>> Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images are 
>>> supported,
>>> but ELF format is not supported.
>>>
>>> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
>>> ---
>>>   arch/loongarch/Kconfig                     |   8 ++
>>>   arch/loongarch/include/asm/image.h         |  18 ++++
>>>   arch/loongarch/include/asm/kexec.h         |  12 +++
>>>   arch/loongarch/kernel/Makefile             |   1 +
>>>   arch/loongarch/kernel/kexec_image.c        | 112 
>>> +++++++++++++++++++++
>>>   arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
>>>   arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
>>>   7 files changed, 219 insertions(+), 11 deletions(-)
>>>   create mode 100644 arch/loongarch/kernel/kexec_image.c
>>>   create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
>> ...
>>
>>> diff --git a/arch/loongarch/include/asm/image.h 
>>> b/arch/loongarch/include/asm/image.h
>>> index 1f090736e71d..829e1ecb1f5d 100644
>>> --- a/arch/loongarch/include/asm/image.h
>>> +++ b/arch/loongarch/include/asm/image.h
>>> @@ -36,5 +36,23 @@ struct loongarch_image_header {
>>>       uint32_t pe_header;
>>>   };
>>>   +static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'};
>>> +static const uint8_t loongarch_pe_machtype[6] = {'P', 'E', 0x0, 
>>> 0x0, 0x64, 0x62};
>> loongarch_pe_machtype isn't used at all.
> It will be removed.
>>
>>> +
>>> +/**
>>> + * loongarch_header_check_pe_sig - Helper to check the loongarch 
>>> image header.
>>> + *
>>> + * Returns non-zero if 'MZ' signature is found.
>>> + */
>>> +
>>> +static inline int loongarch_header_check_pe_sig(const struct 
>>> loongarch_image_header *h)
>>> +{
>>> +    if (!h)
>>> +        return 0;
>>> +
>>> +    return (h->pe_sig[0] == loongarch_image_pe_sig[0]
>>> +        && h->pe_sig[1] == loongarch_image_pe_sig[1]);
>> This could be simplified with a memcmp(). Also, this check isn't strict
>> enough: PE files for any architectures, and even legacy MS-DOS COM
>> executables all start with "MZ".
>>
>>> +}
>>> +
>>>   #endif /* __ASSEMBLY__ */
>>>   #endif /* __ASM_IMAGE_H */
>> ...
>>
>>> diff --git a/arch/loongarch/kernel/kexec_image.c 
>>> b/arch/loongarch/kernel/kexec_image.c
>>> new file mode 100644
>>> index 000000000000..fdd1845b4e2e
>>> --- /dev/null
>>> +++ b/arch/loongarch/kernel/kexec_image.c
>>> @@ -0,0 +1,112 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/*
>>> + * Kexec image loader for LoongArch
>>> +
>>> + * Author: Youling Tang <tangyouling@kylinos.cn>
>>> + * Copyright (C) 2025 KylinSoft Corporation.
>>> + */
>>> +
>>> +#define pr_fmt(fmt)    "kexec_file(Image): " fmt
>>> +
>>> +#include <linux/err.h>
>>> +#include <linux/errno.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/kexec.h>
>>> +#include <linux/pe.h>
>>> +#include <linux/string.h>
>>> +#include <asm/byteorder.h>
>>> +#include <asm/cpufeature.h>
>>> +#include <asm/image.h>
>>> +
>>> +static int image_probe(const char *kernel_buf, unsigned long 
>>> kernel_len)
>>> +{
>>> +    const struct loongarch_image_header *h =
>>> +        (const struct loongarch_image_header *)(kernel_buf);
>> Parentheses around "kernel_buf" are unnecessary.
> It will be removed.
>>
>>> +    if (!h || (kernel_len < sizeof(*h))) {
>> Comparisons have higher priority than logic operations, so this pair of
>> parentheses is redundant, too.
> Yes, but the parentheses will be retained for greater readability.
>>
>>> +        pr_err("No loongarch image header.\n");
>>> +        return -EINVAL;
>>> +    }
>>> +
>>> +    if (!loongarch_header_check_pe_sig(h)) {
>>> +        pr_err("Bad loongarch PE image header.\n");
>>> +        return -EINVAL;
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static void *image_load(struct kimage *image,
>>> +                char *kernel, unsigned long kernel_len,
>>> +                char *initrd, unsigned long initrd_len,
>>> +                char *cmdline, unsigned long cmdline_len)
>>> +{
>>> +    struct loongarch_image_header *h;
>>> +    struct kexec_buf kbuf;
>>> +    unsigned long text_offset, kernel_segment_number;
>>> +    struct kexec_segment *kernel_segment;
>>> +    int ret;
>>> +
>>> +    h = (struct loongarch_image_header *)kernel;
>>> +    if (!h->image_size)
>>> +        return ERR_PTR(-EINVAL);
>>> +
>>> +    /* Load the kernel */
>>> +    kbuf.image = image;
>>> +    kbuf.buf_min = 0;
>>> +    kbuf.buf_max = ULONG_MAX;
>>> +    kbuf.top_down = false;
>>> +
>>> +    kbuf.buffer = kernel;
>>> +    kbuf.bufsz = kernel_len;
>>> +    kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
>>> +    kbuf.memsz = le64_to_cpu(h->image_size);
>>> +    text_offset = le64_to_cpu(h->text_offset);
>>> +    kbuf.buf_align = SZ_2M;
>> I think this aligment is unnecessary for relocatable LoongArch kernels:
>> it should be enough to align to the page size. See also my comments
>> below.
>>
>>> +    kernel_segment_number = image->nr_segments;
>>> +
>>> +    /*
>>> +     * The location of the kernel segment may make it impossible to 
>>> satisfy
>>> +     * the other segment requirements, so we try repeatedly to find a
>>> +     * location that will work.
>>> +     */
>>> +    while ((ret = kexec_add_buffer(&kbuf)) == 0) {
>>> +        /* Try to load additional data */
>>> +        kernel_segment = &image->segment[kernel_segment_number];
>>> +        ret = load_other_segments(image, kernel_segment->mem,
>>> +                      kernel_segment->memsz, initrd,
>>> +                      initrd_len, cmdline, cmdline_len);
>>> +        if (!ret)
>>> +            break;
>>> +
>>> +        /*
>>> +         * We couldn't find space for the other segments; erase the
>>> +         * kernel segment and try the next available hole.
>>> +         */
>>> +        image->nr_segments -= 1;
>>> +        kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
>>> +        kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
>>> +    }
>>> +
>>> +    if (ret) {
>>> +        pr_err("Could not find any suitable kernel location!");
>>> +        return ERR_PTR(ret);
>>> +    }
>>> +
>>> +    kernel_segment = &image->segment[kernel_segment_number];
>>> +
>>> +    /* Make sure the second kernel jumps to the correct 
>>> "kernel_entry". */
>>> +    image->start = kernel_segment->mem + h->kernel_entry - 
>>> text_offset;
>> A non-relocatable loongarch kernel cannot be loaded to arbitrary
>> address. Thus this loading function seems to only work for relocatable
>> kernels, maybe it's better to leave a comment indicating the limitation.
>>
>> For now, we don't seem to have a way to find out whether the kernel is
>> relocatable (for example, a flag in kernel image header), so it's
>> impossible to point out whether the loaded kernel boots fine with
>> arbitrary loading address...
> LoongArch enables the relocation of the kernel when the kdump
> feature is enabled.
>
> config ARCH_SELECTS_CRASH_DUMP
>         def_bool y
>         depends on CRASH_DUMP
>         select RELOCATABLE
>
When enabling KEXEC_FILE, the RELOCATABLE configuration should
also be enabled. Both kexec and kdump require this.

Youling.
> After enabling the relocation, LoongArch is the PIE kernel. For
> more details, please refer to commit d8da19fbdedd ("LoongArch:
> Add support for kernel relocation")
>>> +    kexec_dprintk("Loaded kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
>>> +              kernel_segment->mem, kbuf.bufsz,
>>> +              kernel_segment->memsz);
>>> +
>>> +    return NULL;
>>> +}
>>> +
>>> +const struct kexec_file_ops kexec_image_ops = {
>>> +    .probe = image_probe,
>>> +    .load = image_load,
>>> +};
>>> diff --git a/arch/loongarch/kernel/machine_kexec.c 
>>> b/arch/loongarch/kernel/machine_kexec.c
>>> index f9381800e291..008f43e26120 100644
>>> --- a/arch/loongarch/kernel/machine_kexec.c
>>> +++ b/arch/loongarch/kernel/machine_kexec.c
>>> @@ -70,18 +70,28 @@ int machine_kexec_prepare(struct kimage *kimage)
>> ...
>>
>>> -    if (!kimage->arch.cmdline_ptr) {
>>> -        pr_err("Command line not included in the provided image\n");
>>> -        return -EINVAL;
>>> +        if (!kimage->arch.cmdline_ptr) {
>>> +            pr_err("Command line not included in the provided 
>>> image\n");
>>> +            return -EINVAL;
>>> +        }
>>>       }
>>>         /* kexec/kdump need a safe page to save reboot_code_buffer */
>>> @@ -288,7 +298,8 @@ void machine_kexec(struct kimage *image)
>>>       local_irq_disable();
>>>         pr_notice("EFI boot flag 0x%lx\n", efi_boot);
>>> -    pr_notice("Command line at 0x%lx\n", cmdline_ptr);
>>> +    pr_notice("Command line addr at 0x%lx\n", cmdline_ptr);
>>> +    pr_notice("Command line at %s\n", (char *)cmdline_ptr);
>> The printed message doesn't match meaning of the pointer: you're
>> printing the content of cmdline_ptr, instead of its address, thus
>> "Command line at" sounds confusing to me.
> I will correct it.
>
> Thanks,
> Youling.
>>
>> Furthermore, this chunk isn't related to "support for kexec_file", I
>> think it's better to separate it into another patch (or even another
>> series).
>>
>>>       pr_notice("System table at 0x%lx\n", systable_ptr);
>>>       pr_notice("We will call new kernel at 0x%lx\n", start_addr);
>>>       pr_notice("Bye ...\n");
>> Best regards,
>> Yao Zi

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-12  2:39     ` Huacai Chen
@ 2025-08-12  7:56       ` Yao Zi
  0 siblings, 0 replies; 30+ messages in thread
From: Yao Zi @ 2025-08-12  7:56 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Youling Tang, WANG Xuerui, Baoquan He, kexec, loongarch,
	linux-kernel, Youling Tang

On Tue, Aug 12, 2025 at 10:39:59AM +0800, Huacai Chen wrote:
> On Tue, Aug 12, 2025 at 1:09 AM Yao Zi <ziyao@disroot.org> wrote:
> >
> > On Mon, Aug 11, 2025 at 05:26:55PM +0800, Youling Tang wrote:
> > > From: Youling Tang <tangyouling@kylinos.cn>
> > >
> > > This patch adds support for kexec_file on LoongArch.
> > >
> > > The image_load() as two parts:
> > > - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
> > > - the second part loads other segments (eg: initrd, cmdline)
> > >
> > > Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images are supported,
> > > but ELF format is not supported.
> > >
> > > Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> > > ---
> > >  arch/loongarch/Kconfig                     |   8 ++
> > >  arch/loongarch/include/asm/image.h         |  18 ++++
> > >  arch/loongarch/include/asm/kexec.h         |  12 +++
> > >  arch/loongarch/kernel/Makefile             |   1 +
> > >  arch/loongarch/kernel/kexec_image.c        | 112 +++++++++++++++++++++
> > >  arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
> > >  arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
> > >  7 files changed, 219 insertions(+), 11 deletions(-)
> > >  create mode 100644 arch/loongarch/kernel/kexec_image.c
> > >  create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
> >
> > > diff --git a/arch/loongarch/kernel/kexec_image.c b/arch/loongarch/kernel/kexec_image.c
> > > new file mode 100644
> > > index 000000000000..fdd1845b4e2e
> > > --- /dev/null
> > > +++ b/arch/loongarch/kernel/kexec_image.c
> > > @@ -0,0 +1,112 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * Kexec image loader for LoongArch
> > > +
> > > + * Author: Youling Tang <tangyouling@kylinos.cn>
> > > + * Copyright (C) 2025 KylinSoft Corporation.
> > > + */
> > > +
> > > +#define pr_fmt(fmt)  "kexec_file(Image): " fmt
> > > +
> > > +#include <linux/err.h>
> > > +#include <linux/errno.h>
> > > +#include <linux/kernel.h>
> > > +#include <linux/kexec.h>
> > > +#include <linux/pe.h>
> > > +#include <linux/string.h>
> > > +#include <asm/byteorder.h>
> > > +#include <asm/cpufeature.h>
> > > +#include <asm/image.h>
> > > +
> > > +static int image_probe(const char *kernel_buf, unsigned long kernel_len)
> > > +{
> > > +     const struct loongarch_image_header *h =
> > > +             (const struct loongarch_image_header *)(kernel_buf);
> >
> > Parentheses around "kernel_buf" are unnecessary.
> >
> > > +     if (!h || (kernel_len < sizeof(*h))) {
> >
> > Comparisons have higher priority than logic operations, so this pair of
> > parentheses is redundant, too.
> But the kernel coding style suggest to use parentheses in this case.

Could you please quote the original text? I have read through
Documentation/process/coding-style.rst again but didn't find similar
suggestions...

And git grep '[[:alnum:]]\+ || [[:alnum:]_]\+ [<>]=\?' results in more
than 7000 matches, including 25 in arch/loongarch...

Anyway, this is a little nitpick. I'm just pointing out the expression
is equal to "!h || kernel_len < sizeof(*h)", and whether it's simplified
is fine to me.

> >
> > > +             pr_err("No loongarch image header.\n");
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     if (!loongarch_header_check_pe_sig(h)) {
> > > +             pr_err("Bad loongarch PE image header.\n");
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     return 0;
> > > +}

...

> > > diff --git a/arch/loongarch/kernel/machine_kexec.c b/arch/loongarch/kernel/machine_kexec.c
> > > index f9381800e291..008f43e26120 100644
> > > --- a/arch/loongarch/kernel/machine_kexec.c
> > > +++ b/arch/loongarch/kernel/machine_kexec.c
> > > @@ -70,18 +70,28 @@ int machine_kexec_prepare(struct kimage *kimage)
> >
> > ...
> >
> > > -     if (!kimage->arch.cmdline_ptr) {
> > > -             pr_err("Command line not included in the provided image\n");
> > > -             return -EINVAL;
> > > +             if (!kimage->arch.cmdline_ptr) {
> > > +                     pr_err("Command line not included in the provided image\n");
> > > +                     return -EINVAL;
> > > +             }
> > >       }
> > >
> > >       /* kexec/kdump need a safe page to save reboot_code_buffer */
> > > @@ -288,7 +298,8 @@ void machine_kexec(struct kimage *image)
> > >       local_irq_disable();
> > >
> > >       pr_notice("EFI boot flag 0x%lx\n", efi_boot);
> > > -     pr_notice("Command line at 0x%lx\n", cmdline_ptr);
> > > +     pr_notice("Command line addr at 0x%lx\n", cmdline_ptr);
> > > +     pr_notice("Command line at %s\n", (char *)cmdline_ptr);
> >
> > The printed message doesn't match meaning of the pointer: you're
> > printing the content of cmdline_ptr, instead of its address, thus
> > "Command line at" sounds confusing to me.
> >
> > Furthermore, this chunk isn't related to "support for kexec_file", I
> > think it's better to separate it into another patch (or even another
> > series).
> Separating is not necessary from my point of view, indeed I suggest to
> squash patches in this series.

I realized this comment is a little nitpicking, too, so I'm going to say
either is fine to me.

> Huacai

Best regards,
Yao Zi

> >
> > >       pr_notice("System table at 0x%lx\n", systable_ptr);
> > >       pr_notice("We will call new kernel at 0x%lx\n", start_addr);
> > >       pr_notice("Bye ...\n");
> >
> > Best regards,
> > Yao Zi
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-12  1:53       ` Yanteng Si
@ 2025-08-12  9:32         ` Youling Tang
  2025-08-13  1:15           ` Yanteng Si
  0 siblings, 1 reply; 30+ messages in thread
From: Youling Tang @ 2025-08-12  9:32 UTC (permalink / raw)
  To: Yanteng Si, Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

Hi, Yanteng
On 2025/8/12 09:53, Yanteng Si wrote:
> 在 8/12/25 9:21 AM, Youling Tang 写道:
>> Hi, Huacai
>> On 2025/8/11 22:07, Huacai Chen wrote:
>>> Hi, Youling,
>>>
>>> On Mon, Aug 11, 2025 at 5:28 PM Youling Tang 
>>> <youling.tang@linux.dev> wrote:
>>>> From: Youling Tang <tangyouling@kylinos.cn>
>>>>
>>>> This patch adds support for kexec_file on LoongArch.
>>>>
>>>> The image_load() as two parts:
>>>> - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
>>>> - the second part loads other segments (eg: initrd, cmdline)
>>>>
>>>> Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images are 
>>>> supported,
>>>> but ELF format is not supported.
>>>>
>>>> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
>>>> ---
>>>>   arch/loongarch/Kconfig                     |   8 ++
>>>>   arch/loongarch/include/asm/image.h         |  18 ++++
>>>>   arch/loongarch/include/asm/kexec.h         |  12 +++
>>>>   arch/loongarch/kernel/Makefile             |   1 +
>>>>   arch/loongarch/kernel/kexec_image.c        | 112 
>>>> +++++++++++++++++++++
>>>>   arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
>>>>   arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
>>>>   7 files changed, 219 insertions(+), 11 deletions(-)
>>>>   create mode 100644 arch/loongarch/kernel/kexec_image.c
>>>>   create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
>>>>
>>>> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
>>>> index f0abc38c40ac..fd50c83f7827 100644
>>>> --- a/arch/loongarch/Kconfig
>>>> +++ b/arch/loongarch/Kconfig
>>>> @@ -625,6 +625,14 @@ config CPU_HAS_PREFETCH
>>>>   config ARCH_SUPPORTS_KEXEC
>>>>          def_bool y
>>>>
>>>> +config ARCH_SUPPORTS_KEXEC_FILE
>>>> +       def_bool 64BIT
>>>> +
>>>> +config ARCH_SELECTS_KEXEC_FILE
>>>> +       def_bool y
>>>> +       depends on KEXEC_FILE
>>>> +       select HAVE_IMA_KEXEC if IMA
>>>> +
>>>>   config ARCH_SUPPORTS_CRASH_DUMP
>>>>          def_bool y
>>>>
>>>> diff --git a/arch/loongarch/include/asm/image.h 
>>>> b/arch/loongarch/include/asm/image.h
>>>> index 1f090736e71d..829e1ecb1f5d 100644
>>>> --- a/arch/loongarch/include/asm/image.h
>>>> +++ b/arch/loongarch/include/asm/image.h
>>>> @@ -36,5 +36,23 @@ struct loongarch_image_header {
>>>>          uint32_t pe_header;
>>>>   };
>>>>
>>>> +static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'};
>>>> +static const uint8_t loongarch_pe_machtype[6] = {'P', 'E', 0x0, 
>>>> 0x0, 0x64, 0x62};
>>>> +
>>>> +/**
>>>> + * loongarch_header_check_pe_sig - Helper to check the loongarch 
>>>> image header.
>>>> + *
>>>> + * Returns non-zero if 'MZ' signature is found.
>>>> + */
>>>> +
>>>> +static inline int loongarch_header_check_pe_sig(const struct 
>>>> loongarch_image_header *h)
>>>> +{
>>>> +       if (!h)
>>>> +               return 0;
>>>> +
>>>> +       return (h->pe_sig[0] == loongarch_image_pe_sig[0]
>>>> +               && h->pe_sig[1] == loongarch_image_pe_sig[1]);
>>>> +}
>>>> +
>>>>   #endif /* __ASSEMBLY__ */
>>>>   #endif /* __ASM_IMAGE_H */
>>>> diff --git a/arch/loongarch/include/asm/kexec.h 
>>>> b/arch/loongarch/include/asm/kexec.h
>>>> index cf95cd3eb2de..3ef8517a3670 100644
>>>> --- a/arch/loongarch/include/asm/kexec.h
>>>> +++ b/arch/loongarch/include/asm/kexec.h
>>>> @@ -41,6 +41,18 @@ struct kimage_arch {
>>>>          unsigned long systable_ptr;
>>>>   };
>>>>
>>>> +#ifdef CONFIG_KEXEC_FILE
>>>> +extern const struct kexec_file_ops kexec_image_ops;
>>>> +
>>>> +int arch_kimage_file_post_load_cleanup(struct kimage *image);
>>>> +#define arch_kimage_file_post_load_cleanup 
>>>> arch_kimage_file_post_load_cleanup
>>>> +
>>>> +extern int load_other_segments(struct kimage *image,
>>>> +               unsigned long kernel_load_addr, unsigned long 
>>>> kernel_size,
>>>> +               char *initrd, unsigned long initrd_len,
>>>> +               char *cmdline, unsigned long cmdline_len);
>>> I think the RISC-V naming "load_extra_segments" is better.
>> This name is also fine, but I prefer it to be consistent with
>> that in kexec-tools.
> I have looked at the code of kexec-tools, and it seems that you 
> referenced a great deal of ARM code when implementing the LoongArch part.
>
>
>>>
>>>> +#endif
>>>> +
>>>>   typedef void (*do_kexec_t)(unsigned long efi_boot,
>>>>                             unsigned long cmdline_ptr,
>>>>                             unsigned long systable_ptr,
>>>> diff --git a/arch/loongarch/kernel/Makefile 
>>>> b/arch/loongarch/kernel/Makefile
>>>> index 6f5a4574a911..bd9405ee3888 100644
>>>> --- a/arch/loongarch/kernel/Makefile
>>>> +++ b/arch/loongarch/kernel/Makefile
>>>> @@ -62,6 +62,7 @@ obj-$(CONFIG_MAGIC_SYSRQ)     += sysrq.o
>>>>   obj-$(CONFIG_RELOCATABLE)      += relocate.o
>>>>
>>>>   obj-$(CONFIG_KEXEC_CORE)       += machine_kexec.o relocate_kernel.o
>>>> +obj-$(CONFIG_KEXEC_FILE)       += machine_kexec_file.o kexec_image.o
>>> We only support the efi format, so we don't need to split a
>>> kexec_image.c like RISC-V, just put everything into
>>> machine_kexec_file.c is OK.
>> I hope it is separated and consistent with other architectures.
>> For instance, arm64 only supports one type.
> The ARM64 architecture has a long history, and we shouldn't be 
> constrained by it.
Support for kexec_elf.c in ELF format may be considered for
addition in the future.

Thanks,
Youling.
>
>
> Thanks,
> Yanteng
>>
>> Youling.
>>>
>>> Huacai

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-12  7:06       ` Youling Tang
@ 2025-08-12  9:43         ` Yao Zi
  2025-08-13  2:18           ` Youling Tang
  0 siblings, 1 reply; 30+ messages in thread
From: Yao Zi @ 2025-08-12  9:43 UTC (permalink / raw)
  To: Youling Tang, Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

On Tue, Aug 12, 2025 at 03:06:23PM +0800, Youling Tang wrote:
> On 2025/8/12 14:15, Youling Tang wrote:
> > Hi, Yao
> > On 2025/8/12 01:06, Yao Zi wrote:
> > > On Mon, Aug 11, 2025 at 05:26:55PM +0800, Youling Tang wrote:
> > > > From: Youling Tang <tangyouling@kylinos.cn>
> > > > 
> > > > This patch adds support for kexec_file on LoongArch.
> > > > 
> > > > The image_load() as two parts:
> > > > - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
> > > > - the second part loads other segments (eg: initrd, cmdline)
> > > > 
> > > > Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images
> > > > are supported,
> > > > but ELF format is not supported.
> > > > 
> > > > Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> > > > ---
> > > >   arch/loongarch/Kconfig                     |   8 ++
> > > >   arch/loongarch/include/asm/image.h         |  18 ++++
> > > >   arch/loongarch/include/asm/kexec.h         |  12 +++
> > > >   arch/loongarch/kernel/Makefile             |   1 +
> > > >   arch/loongarch/kernel/kexec_image.c        | 112
> > > > +++++++++++++++++++++
> > > >   arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
> > > >   arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
> > > >   7 files changed, 219 insertions(+), 11 deletions(-)
> > > >   create mode 100644 arch/loongarch/kernel/kexec_image.c
> > > >   create mode 100644 arch/loongarch/kernel/machine_kexec_file.c

...

> > > > diff --git a/arch/loongarch/kernel/kexec_image.c
> > > > b/arch/loongarch/kernel/kexec_image.c
> > > > new file mode 100644
> > > > index 000000000000..fdd1845b4e2e
> > > > --- /dev/null
> > > > +++ b/arch/loongarch/kernel/kexec_image.c

...

> > > > +    /*
> > > > +     * The location of the kernel segment may make it
> > > > impossible to satisfy
> > > > +     * the other segment requirements, so we try repeatedly to find a
> > > > +     * location that will work.
> > > > +     */
> > > > +    while ((ret = kexec_add_buffer(&kbuf)) == 0) {
> > > > +        /* Try to load additional data */
> > > > +        kernel_segment = &image->segment[kernel_segment_number];
> > > > +        ret = load_other_segments(image, kernel_segment->mem,
> > > > +                      kernel_segment->memsz, initrd,
> > > > +                      initrd_len, cmdline, cmdline_len);
> > > > +        if (!ret)
> > > > +            break;
> > > > +
> > > > +        /*
> > > > +         * We couldn't find space for the other segments; erase the
> > > > +         * kernel segment and try the next available hole.
> > > > +         */
> > > > +        image->nr_segments -= 1;
> > > > +        kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
> > > > +        kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> > > > +    }
> > > > +
> > > > +    if (ret) {
> > > > +        pr_err("Could not find any suitable kernel location!");
> > > > +        return ERR_PTR(ret);
> > > > +    }
> > > > +
> > > > +    kernel_segment = &image->segment[kernel_segment_number];
> > > > +
> > > > +    /* Make sure the second kernel jumps to the correct
> > > > "kernel_entry". */
> > > > +    image->start = kernel_segment->mem + h->kernel_entry -
> > > > text_offset;
> > > A non-relocatable loongarch kernel cannot be loaded to arbitrary
> > > address. Thus this loading function seems to only work for relocatable
> > > kernels, maybe it's better to leave a comment indicating the limitation.
> > > 
> > > For now, we don't seem to have a way to find out whether the kernel is
> > > relocatable (for example, a flag in kernel image header), so it's
> > > impossible to point out whether the loaded kernel boots fine with
> > > arbitrary loading address...
> > LoongArch enables the relocation of the kernel when the kdump
> > feature is enabled.
> > 
> > config ARCH_SELECTS_CRASH_DUMP
> >         def_bool y
> >         depends on CRASH_DUMP
> >         select RELOCATABLE
> > 

This only means the currently-running kernel is relocatable, not the one
being exec'ed, right?

> When enabling KEXEC_FILE, the RELOCATABLE configuration should
> also be enabled. Both kexec and kdump require this.

I'm not sure whether you're talking about the running kernel or the one
that is going to be exec'ed. This method of kernel loading requires the
exec'ed kernel being relocatable, not the currently running one.

And I think it's totally reasonable to use KEXEC_FILE for non-crash-dump
purpose, for example, linuxboot. It'll be confusing to the user if the
system just hangs after booting a non-relocatable kernel, which is hard
to debug.

Thus IMHO we should ideally refuse to load non-relocatable kernels, or
add a FIXME comment to indicate the situation that it's impossible to
determine whether the exec'ed image is relocatable.

> Youling.
> > After enabling the relocation, LoongArch is the PIE kernel. For
> > more details, please refer to commit d8da19fbdedd ("LoongArch:
> > Add support for kernel relocation")

Best regards.
Yao Zi

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-12  9:32         ` Youling Tang
@ 2025-08-13  1:15           ` Yanteng Si
  0 siblings, 0 replies; 30+ messages in thread
From: Yanteng Si @ 2025-08-13  1:15 UTC (permalink / raw)
  To: Youling Tang, Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang


在 8/12/25 5:32 PM, Youling Tang 写道:
> Hi, Yanteng
> On 2025/8/12 09:53, Yanteng Si wrote:
>> 在 8/12/25 9:21 AM, Youling Tang 写道:
>>> Hi, Huacai
>>> On 2025/8/11 22:07, Huacai Chen wrote:
>>>> Hi, Youling,
>>>>
>>>> On Mon, Aug 11, 2025 at 5:28 PM Youling Tang <youling.tang@linux.dev> wrote:
>>>>> From: Youling Tang <tangyouling@kylinos.cn>
>>>>>
>>>>> This patch adds support for kexec_file on LoongArch.
>>>>>
>>>>> The image_load() as two parts:
>>>>> - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
>>>>> - the second part loads other segments (eg: initrd, cmdline)
>>>>>
>>>>> Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images are supported,
>>>>> but ELF format is not supported.
>>>>>
>>>>> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
>>>>> ---
>>>>>   arch/loongarch/Kconfig                     |   8 ++
>>>>>   arch/loongarch/include/asm/image.h         |  18 ++++
>>>>>   arch/loongarch/include/asm/kexec.h         |  12 +++
>>>>>   arch/loongarch/kernel/Makefile             |   1 +
>>>>>   arch/loongarch/kernel/kexec_image.c        | 112 +++++++++++++++++++++
>>>>>   arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
>>>>>   arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
>>>>>   7 files changed, 219 insertions(+), 11 deletions(-)
>>>>>   create mode 100644 arch/loongarch/kernel/kexec_image.c
>>>>>   create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
>>>>>
>>>>> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
>>>>> index f0abc38c40ac..fd50c83f7827 100644
>>>>> --- a/arch/loongarch/Kconfig
>>>>> +++ b/arch/loongarch/Kconfig
>>>>> @@ -625,6 +625,14 @@ config CPU_HAS_PREFETCH
>>>>>   config ARCH_SUPPORTS_KEXEC
>>>>>          def_bool y
>>>>>
>>>>> +config ARCH_SUPPORTS_KEXEC_FILE
>>>>> +       def_bool 64BIT
>>>>> +
>>>>> +config ARCH_SELECTS_KEXEC_FILE
>>>>> +       def_bool y
>>>>> +       depends on KEXEC_FILE
>>>>> +       select HAVE_IMA_KEXEC if IMA
>>>>> +
>>>>>   config ARCH_SUPPORTS_CRASH_DUMP
>>>>>          def_bool y
>>>>>
>>>>> diff --git a/arch/loongarch/include/asm/image.h b/arch/loongarch/include/asm/image.h
>>>>> index 1f090736e71d..829e1ecb1f5d 100644
>>>>> --- a/arch/loongarch/include/asm/image.h
>>>>> +++ b/arch/loongarch/include/asm/image.h
>>>>> @@ -36,5 +36,23 @@ struct loongarch_image_header {
>>>>>          uint32_t pe_header;
>>>>>   };
>>>>>
>>>>> +static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'};
>>>>> +static const uint8_t loongarch_pe_machtype[6] = {'P', 'E', 0x0, 0x0, 0x64, 0x62};
>>>>> +
>>>>> +/**
>>>>> + * loongarch_header_check_pe_sig - Helper to check the loongarch image header.
>>>>> + *
>>>>> + * Returns non-zero if 'MZ' signature is found.
>>>>> + */
>>>>> +
>>>>> +static inline int loongarch_header_check_pe_sig(const struct loongarch_image_header *h)
>>>>> +{
>>>>> +       if (!h)
>>>>> +               return 0;
>>>>> +
>>>>> +       return (h->pe_sig[0] == loongarch_image_pe_sig[0]
>>>>> +               && h->pe_sig[1] == loongarch_image_pe_sig[1]);
>>>>> +}
>>>>> +
>>>>>   #endif /* __ASSEMBLY__ */
>>>>>   #endif /* __ASM_IMAGE_H */
>>>>> diff --git a/arch/loongarch/include/asm/kexec.h b/arch/loongarch/include/asm/kexec.h
>>>>> index cf95cd3eb2de..3ef8517a3670 100644
>>>>> --- a/arch/loongarch/include/asm/kexec.h
>>>>> +++ b/arch/loongarch/include/asm/kexec.h
>>>>> @@ -41,6 +41,18 @@ struct kimage_arch {
>>>>>          unsigned long systable_ptr;
>>>>>   };
>>>>>
>>>>> +#ifdef CONFIG_KEXEC_FILE
>>>>> +extern const struct kexec_file_ops kexec_image_ops;
>>>>> +
>>>>> +int arch_kimage_file_post_load_cleanup(struct kimage *image);
>>>>> +#define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup
>>>>> +
>>>>> +extern int load_other_segments(struct kimage *image,
>>>>> +               unsigned long kernel_load_addr, unsigned long kernel_size,
>>>>> +               char *initrd, unsigned long initrd_len,
>>>>> +               char *cmdline, unsigned long cmdline_len);
>>>> I think the RISC-V naming "load_extra_segments" is better.
>>> This name is also fine, but I prefer it to be consistent with
>>> that in kexec-tools.
>> I have looked at the code of kexec-tools, and it seems that you referenced a great deal of ARM code when implementing the LoongArch part.
>>
>>
>>>>
>>>>> +#endif
>>>>> +
>>>>>   typedef void (*do_kexec_t)(unsigned long efi_boot,
>>>>>                             unsigned long cmdline_ptr,
>>>>>                             unsigned long systable_ptr,
>>>>> diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
>>>>> index 6f5a4574a911..bd9405ee3888 100644
>>>>> --- a/arch/loongarch/kernel/Makefile
>>>>> +++ b/arch/loongarch/kernel/Makefile
>>>>> @@ -62,6 +62,7 @@ obj-$(CONFIG_MAGIC_SYSRQ)     += sysrq.o
>>>>>   obj-$(CONFIG_RELOCATABLE)      += relocate.o
>>>>>
>>>>>   obj-$(CONFIG_KEXEC_CORE)       += machine_kexec.o relocate_kernel.o
>>>>> +obj-$(CONFIG_KEXEC_FILE)       += machine_kexec_file.o kexec_image.o
>>>> We only support the efi format, so we don't need to split a
>>>> kexec_image.c like RISC-V, just put everything into
>>>> machine_kexec_file.c is OK.
>>> I hope it is separated and consistent with other architectures.
>>> For instance, arm64 only supports one type.
>> The ARM64 architecture has a long history, and we shouldn't be constrained by it.
> Support for kexec_elf.c in ELF format may be considered for
> addition in the future.

Ok, I see.


Thanks,

Yanteng

>
> Thanks,
> Youling.
>>
>>
>> Thanks,
>> Yanteng
>>>
>>> Youling.
>>>>
>>>> Huacai

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-12  9:43         ` Yao Zi
@ 2025-08-13  2:18           ` Youling Tang
  2025-08-13  3:24             ` Yao Zi
  0 siblings, 1 reply; 30+ messages in thread
From: Youling Tang @ 2025-08-13  2:18 UTC (permalink / raw)
  To: Yao Zi, Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

Hi, Yao
On 2025/8/12 17:43, Yao Zi wrote:
> On Tue, Aug 12, 2025 at 03:06:23PM +0800, Youling Tang wrote:
>> On 2025/8/12 14:15, Youling Tang wrote:
>>> Hi, Yao
>>> On 2025/8/12 01:06, Yao Zi wrote:
>>>> On Mon, Aug 11, 2025 at 05:26:55PM +0800, Youling Tang wrote:
>>>>> From: Youling Tang <tangyouling@kylinos.cn>
>>>>>
>>>>> This patch adds support for kexec_file on LoongArch.
>>>>>
>>>>> The image_load() as two parts:
>>>>> - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
>>>>> - the second part loads other segments (eg: initrd, cmdline)
>>>>>
>>>>> Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images
>>>>> are supported,
>>>>> but ELF format is not supported.
>>>>>
>>>>> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
>>>>> ---
>>>>>    arch/loongarch/Kconfig                     |   8 ++
>>>>>    arch/loongarch/include/asm/image.h         |  18 ++++
>>>>>    arch/loongarch/include/asm/kexec.h         |  12 +++
>>>>>    arch/loongarch/kernel/Makefile             |   1 +
>>>>>    arch/loongarch/kernel/kexec_image.c        | 112
>>>>> +++++++++++++++++++++
>>>>>    arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
>>>>>    arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
>>>>>    7 files changed, 219 insertions(+), 11 deletions(-)
>>>>>    create mode 100644 arch/loongarch/kernel/kexec_image.c
>>>>>    create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
> ...
>
>>>>> diff --git a/arch/loongarch/kernel/kexec_image.c
>>>>> b/arch/loongarch/kernel/kexec_image.c
>>>>> new file mode 100644
>>>>> index 000000000000..fdd1845b4e2e
>>>>> --- /dev/null
>>>>> +++ b/arch/loongarch/kernel/kexec_image.c
> ...
>
>>>>> +    /*
>>>>> +     * The location of the kernel segment may make it
>>>>> impossible to satisfy
>>>>> +     * the other segment requirements, so we try repeatedly to find a
>>>>> +     * location that will work.
>>>>> +     */
>>>>> +    while ((ret = kexec_add_buffer(&kbuf)) == 0) {
>>>>> +        /* Try to load additional data */
>>>>> +        kernel_segment = &image->segment[kernel_segment_number];
>>>>> +        ret = load_other_segments(image, kernel_segment->mem,
>>>>> +                      kernel_segment->memsz, initrd,
>>>>> +                      initrd_len, cmdline, cmdline_len);
>>>>> +        if (!ret)
>>>>> +            break;
>>>>> +
>>>>> +        /*
>>>>> +         * We couldn't find space for the other segments; erase the
>>>>> +         * kernel segment and try the next available hole.
>>>>> +         */
>>>>> +        image->nr_segments -= 1;
>>>>> +        kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
>>>>> +        kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
>>>>> +    }
>>>>> +
>>>>> +    if (ret) {
>>>>> +        pr_err("Could not find any suitable kernel location!");
>>>>> +        return ERR_PTR(ret);
>>>>> +    }
>>>>> +
>>>>> +    kernel_segment = &image->segment[kernel_segment_number];
>>>>> +
>>>>> +    /* Make sure the second kernel jumps to the correct
>>>>> "kernel_entry". */
>>>>> +    image->start = kernel_segment->mem + h->kernel_entry -
>>>>> text_offset;
>>>> A non-relocatable loongarch kernel cannot be loaded to arbitrary
>>>> address. Thus this loading function seems to only work for relocatable
>>>> kernels, maybe it's better to leave a comment indicating the limitation.
>>>>
>>>> For now, we don't seem to have a way to find out whether the kernel is
>>>> relocatable (for example, a flag in kernel image header), so it's
>>>> impossible to point out whether the loaded kernel boots fine with
>>>> arbitrary loading address...
>>> LoongArch enables the relocation of the kernel when the kdump
>>> feature is enabled.
>>>
>>> config ARCH_SELECTS_CRASH_DUMP
>>>          def_bool y
>>>          depends on CRASH_DUMP
>>>          select RELOCATABLE
>>>
> This only means the currently-running kernel is relocatable, not the one
> being exec'ed, right?
No.
>> When enabling KEXEC_FILE, the RELOCATABLE configuration should
>> also be enabled. Both kexec and kdump require this.
> I'm not sure whether you're talking about the running kernel or the one
> that is going to be exec'ed. This method of kernel loading requires the
> exec'ed kernel being relocatable, not the currently running one.
>
> And I think it's totally reasonable to use KEXEC_FILE for non-crash-dump
> purpose, for example, linuxboot. It'll be confusing to the user if the
> system just hangs after booting a non-relocatable kernel, which is hard
> to debug.
>
> Thus IMHO we should ideally refuse to load non-relocatable kernels, or
> add a FIXME comment to indicate the situation that it's impossible to
> determine whether the exec'ed image is relocatable.
The first kernel and the second kernel are generally the same kernel
(the same image). When KEXEC_FILE is enabled and RELOCATEABLE
is enabled by default, it has been forcibly guaranteed that both the
first kernel and the second kernel are relocatable kernels regardless
of kexec/kdump operations.

Unless the second kernel it loads is an older version of the kernel (the
older version of the kernel does not use the default configuration, with
CONFIG_KEXEC enabled but CONFIG_CRASH_DUMP disabled, this is not acorrect
usage).

Thanks,
Youling.
>> Youling.
>>> After enabling the relocation, LoongArch is the PIE kernel. For
>>> more details, please refer to commit d8da19fbdedd ("LoongArch:
>>> Add support for kernel relocation")
> Best regards.
> Yao Zi

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-13  2:18           ` Youling Tang
@ 2025-08-13  3:24             ` Yao Zi
  0 siblings, 0 replies; 30+ messages in thread
From: Yao Zi @ 2025-08-13  3:24 UTC (permalink / raw)
  To: Youling Tang, Huacai Chen
  Cc: WANG Xuerui, Baoquan He, kexec, loongarch, linux-kernel,
	Youling Tang

On Wed, Aug 13, 2025 at 10:18:12AM +0800, Youling Tang wrote:
> Hi, Yao
> On 2025/8/12 17:43, Yao Zi wrote:
> > On Tue, Aug 12, 2025 at 03:06:23PM +0800, Youling Tang wrote:
> > > On 2025/8/12 14:15, Youling Tang wrote:
> > > > Hi, Yao
> > > > On 2025/8/12 01:06, Yao Zi wrote:
> > > > > On Mon, Aug 11, 2025 at 05:26:55PM +0800, Youling Tang wrote:
> > > > > > From: Youling Tang <tangyouling@kylinos.cn>
> > > > > > 
> > > > > > This patch adds support for kexec_file on LoongArch.
> > > > > > 
> > > > > > The image_load() as two parts:
> > > > > > - the first part loads the kernel image (vmlinuz.efi or vmlinux.efi)
> > > > > > - the second part loads other segments (eg: initrd, cmdline)
> > > > > > 
> > > > > > Currently, pez(vmlinuz.efi) and pei(vmlinux.efi) format images
> > > > > > are supported,
> > > > > > but ELF format is not supported.
> > > > > > 
> > > > > > Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> > > > > > ---
> > > > > >    arch/loongarch/Kconfig                     |   8 ++
> > > > > >    arch/loongarch/include/asm/image.h         |  18 ++++
> > > > > >    arch/loongarch/include/asm/kexec.h         |  12 +++
> > > > > >    arch/loongarch/kernel/Makefile             |   1 +
> > > > > >    arch/loongarch/kernel/kexec_image.c        | 112
> > > > > > +++++++++++++++++++++
> > > > > >    arch/loongarch/kernel/machine_kexec.c      |  33 ++++--
> > > > > >    arch/loongarch/kernel/machine_kexec_file.c |  46 +++++++++
> > > > > >    7 files changed, 219 insertions(+), 11 deletions(-)
> > > > > >    create mode 100644 arch/loongarch/kernel/kexec_image.c
> > > > > >    create mode 100644 arch/loongarch/kernel/machine_kexec_file.c
> > ...
> > 
> > > > > > diff --git a/arch/loongarch/kernel/kexec_image.c
> > > > > > b/arch/loongarch/kernel/kexec_image.c
> > > > > > new file mode 100644
> > > > > > index 000000000000..fdd1845b4e2e
> > > > > > --- /dev/null
> > > > > > +++ b/arch/loongarch/kernel/kexec_image.c
> > ...
> > 
> > > > > > +    /*
> > > > > > +     * The location of the kernel segment may make it
> > > > > > impossible to satisfy
> > > > > > +     * the other segment requirements, so we try repeatedly to find a
> > > > > > +     * location that will work.
> > > > > > +     */
> > > > > > +    while ((ret = kexec_add_buffer(&kbuf)) == 0) {
> > > > > > +        /* Try to load additional data */
> > > > > > +        kernel_segment = &image->segment[kernel_segment_number];
> > > > > > +        ret = load_other_segments(image, kernel_segment->mem,
> > > > > > +                      kernel_segment->memsz, initrd,
> > > > > > +                      initrd_len, cmdline, cmdline_len);
> > > > > > +        if (!ret)
> > > > > > +            break;
> > > > > > +
> > > > > > +        /*
> > > > > > +         * We couldn't find space for the other segments; erase the
> > > > > > +         * kernel segment and try the next available hole.
> > > > > > +         */
> > > > > > +        image->nr_segments -= 1;
> > > > > > +        kbuf.buf_min = kernel_segment->mem + kernel_segment->memsz;
> > > > > > +        kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
> > > > > > +    }
> > > > > > +
> > > > > > +    if (ret) {
> > > > > > +        pr_err("Could not find any suitable kernel location!");
> > > > > > +        return ERR_PTR(ret);
> > > > > > +    }
> > > > > > +
> > > > > > +    kernel_segment = &image->segment[kernel_segment_number];
> > > > > > +
> > > > > > +    /* Make sure the second kernel jumps to the correct
> > > > > > "kernel_entry". */
> > > > > > +    image->start = kernel_segment->mem + h->kernel_entry -
> > > > > > text_offset;
> > > > > A non-relocatable loongarch kernel cannot be loaded to arbitrary
> > > > > address. Thus this loading function seems to only work for relocatable
> > > > > kernels, maybe it's better to leave a comment indicating the limitation.
> > > > > 
> > > > > For now, we don't seem to have a way to find out whether the kernel is
> > > > > relocatable (for example, a flag in kernel image header), so it's
> > > > > impossible to point out whether the loaded kernel boots fine with
> > > > > arbitrary loading address...
> > > > LoongArch enables the relocation of the kernel when the kdump
> > > > feature is enabled.
> > > > 
> > > > config ARCH_SELECTS_CRASH_DUMP
> > > >          def_bool y
> > > >          depends on CRASH_DUMP
> > > >          select RELOCATABLE
> > > > 
> > This only means the currently-running kernel is relocatable, not the one
> > being exec'ed, right?
> No.
> > > When enabling KEXEC_FILE, the RELOCATABLE configuration should
> > > also be enabled. Both kexec and kdump require this.
> > I'm not sure whether you're talking about the running kernel or the one
> > that is going to be exec'ed. This method of kernel loading requires the
> > exec'ed kernel being relocatable, not the currently running one.
> > 
> > And I think it's totally reasonable to use KEXEC_FILE for non-crash-dump
> > purpose, for example, linuxboot. It'll be confusing to the user if the
> > system just hangs after booting a non-relocatable kernel, which is hard
> > to debug.
> > 
> > Thus IMHO we should ideally refuse to load non-relocatable kernels, or
> > add a FIXME comment to indicate the situation that it's impossible to
> > determine whether the exec'ed image is relocatable.
> The first kernel and the second kernel are generally the same kernel
> (the same image).

This isn't true. There're real-world cases using kexec-file to load and
boot an unrelated kernel image. Please refer to petitboot[1] and
linuxboot[2] which uses kexec to act as a bootloader.

> When KEXEC_FILE is enabled and RELOCATEABLE
> is enabled by default, it has been forcibly guaranteed that both the
> first kernel and the second kernel are relocatable kernels regardless
> of kexec/kdump operations.

This cannot be guaranteed since the first and second kernel could be
completely unrelated. Please see my previous comment.

> Unless the second kernel it loads is an older version of the kernel (the
> older version of the kernel does not use the default configuration, with
> CONFIG_KEXEC enabled but CONFIG_CRASH_DUMP disabled,

> this is not acorrect usage).

This may be incorrect for kdump's use case, but kexec-file isn't only
meant to be used with kdump: it just loads an arbitrary kernel image and
executes it, no matter whether it's for capturing a dump, booting a
newer or older kernel, or etc, and there's no guarantee about features
enabled in the second kernel. It's incorrect to assume the user only
loads relocatable images with kexec-file.

> Thanks,
> Youling.
> > > Youling.
> > > > After enabling the relocation, LoongArch is the PIE kernel. For
> > > > more details, please refer to commit d8da19fbdedd ("LoongArch:
> > > > Add support for kernel relocation")
> > Best regards.
> > Yao Zi
> 

Thanks,
Yao Zi

[1]: https://github.com/open-power/petitboot
[2]: https://github.com/linuxboot/linuxboot

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 2/6] LoongArch: Add kexec_file support
  2025-08-11  9:26 ` [PATCH 2/6] LoongArch: Add kexec_file support Youling Tang
  2025-08-11 14:07   ` Huacai Chen
  2025-08-11 17:06   ` Yao Zi
@ 2025-08-16  5:37   ` kernel test robot
  2 siblings, 0 replies; 30+ messages in thread
From: kernel test robot @ 2025-08-16  5:37 UTC (permalink / raw)
  To: Youling Tang, Huacai Chen
  Cc: oe-kbuild-all, WANG Xuerui, Baoquan He, kexec, loongarch,
	linux-kernel, youling.tang, Youling Tang

Hi Youling,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.17-rc1 next-20250815]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Youling-Tang/LoongArch-Add-struct-loongarch_image_header-for-kernel-image/20250811-174725
base:   linus/master
patch link:    https://lore.kernel.org/r/20250811092659.14903-3-youling.tang%40linux.dev
patch subject: [PATCH 2/6] LoongArch: Add kexec_file support
config: loongarch-randconfig-r121-20250816 (https://download.01.org/0day-ci/archive/20250816/202508161329.M5Axl1XA-lkp@intel.com/config)
compiler: loongarch64-linux-gcc (GCC) 15.1.0
reproduce: (https://download.01.org/0day-ci/archive/20250816/202508161329.M5Axl1XA-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202508161329.M5Axl1XA-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from arch/loongarch/kernel/kexec_image.c:19:
>> arch/loongarch/include/asm/image.h:40:22: warning: 'loongarch_pe_machtype' defined but not used [-Wunused-const-variable=]
      40 | static const uint8_t loongarch_pe_machtype[6] = {'P', 'E', 0x0, 0x0, 0x64, 0x62};
         |                      ^~~~~~~~~~~~~~~~~~~~~

sparse warnings: (new ones prefixed by >>)
>> arch/loongarch/kernel/kexec_image.c:63:22: sparse: sparse: cast to restricted __le64
   arch/loongarch/kernel/kexec_image.c:64:23: sparse: sparse: cast to restricted __le64

vim +/loongarch_pe_machtype +40 arch/loongarch/include/asm/image.h

    38	
    39	static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'};
  > 40	static const uint8_t loongarch_pe_machtype[6] = {'P', 'E', 0x0, 0x0, 0x64, 0x62};
    41	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2025-08-16  5:38 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-11  9:26 [PATCH 0/6] Add kexec_file support for LoongArch Youling Tang
2025-08-11  9:26 ` [PATCH 1/6] LoongArch: Add struct loongarch_image_header for kernel image Youling Tang
2025-08-11  9:26 ` [PATCH 2/6] LoongArch: Add kexec_file support Youling Tang
2025-08-11 14:07   ` Huacai Chen
2025-08-12  1:21     ` Youling Tang
2025-08-12  1:53       ` Yanteng Si
2025-08-12  9:32         ` Youling Tang
2025-08-13  1:15           ` Yanteng Si
2025-08-12  2:53       ` Huacai Chen
2025-08-11 17:06   ` Yao Zi
2025-08-12  2:39     ` Huacai Chen
2025-08-12  7:56       ` Yao Zi
2025-08-12  6:15     ` Youling Tang
2025-08-12  7:06       ` Youling Tang
2025-08-12  9:43         ` Yao Zi
2025-08-13  2:18           ` Youling Tang
2025-08-13  3:24             ` Yao Zi
2025-08-16  5:37   ` kernel test robot
2025-08-11  9:26 ` [PATCH 3/6] LoongArch/kexec_file: Add initrd loading Youling Tang
2025-08-11 14:12   ` Huacai Chen
2025-08-12  2:38     ` Youling Tang
2025-08-12  3:03       ` Huacai Chen
2025-08-11 17:58   ` Yao Zi
2025-08-12  4:05     ` Youling Tang
2025-08-12  6:25       ` Yao Zi
2025-08-11  9:26 ` [PATCH 4/6] LoongArch/kexec_file: Add crash dump support Youling Tang
2025-08-11  9:26 ` [PATCH 5/6] LoongArch/kexec_file: Add "mem" parameter to limit memory usage of kdump kernel Youling Tang
2025-08-11  9:26 ` [PATCH 6/6] LoongArch: Enable CONFIG_KEXEC_FILE Youling Tang
2025-08-11 16:20 ` [PATCH 0/6] Add kexec_file support for LoongArch Vincent Li
2025-08-12  6:21   ` Youling Tang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).