From: Youling Tang <youling.tang@linux.dev>
To: Huacai Chen <chenhuacai@kernel.org>
Cc: WANG Xuerui <kernel@xen0n.name>, Baoquan He <bhe@redhat.com>,
Yao Zi <ziyao@disroot.org>,
kexec@lists.infradead.org, loongarch@lists.linux.dev,
linux-kernel@vger.kernel.org,
Youling Tang <tangyouling@kylinos.cn>
Subject: Re: [PATCH v2 3/5] LoongArch/kexec_file: Support loading ELF binary file
Date: Thu, 21 Aug 2025 15:14:46 +0800 [thread overview]
Message-ID: <284a663f-3bdd-4dcc-b017-b1b3fe6d9eb1@linux.dev> (raw)
In-Reply-To: <20250820055700.24344-4-youling.tang@linux.dev>
On 2025/8/20 13:56, Youling Tang wrote:
> From: Youling Tang <tangyouling@kylinos.cn>
>
> This patch creates kexec_elf_ops to load ELF binary file
> for kexec_file_load() syscall.
>
> Signed-off-by: Youling Tang <tangyouling@kylinos.cn>
> ---
> arch/loongarch/Kconfig | 1 +
> arch/loongarch/include/asm/kexec.h | 1 +
> arch/loongarch/kernel/Makefile | 2 +-
> arch/loongarch/kernel/kexec_elf.c | 105 +++++++++++++++++++++
> arch/loongarch/kernel/machine_kexec_file.c | 1 +
> 5 files changed, 109 insertions(+), 1 deletion(-)
> create mode 100644 arch/loongarch/kernel/kexec_elf.c
>
> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
> index 490dc6eed749..bf2664ed7ce3 100644
> --- a/arch/loongarch/Kconfig
> +++ b/arch/loongarch/Kconfig
> @@ -632,6 +632,7 @@ config ARCH_SELECTS_KEXEC_FILE
> def_bool y
> depends on KEXEC_FILE
> select HAVE_IMA_KEXEC if IMA
> + select KEXEC_ELF
> select RELOCATABLE
>
> config ARCH_SUPPORTS_CRASH_DUMP
> diff --git a/arch/loongarch/include/asm/kexec.h b/arch/loongarch/include/asm/kexec.h
> index 34799db933fb..fecfb3015abc 100644
> --- a/arch/loongarch/include/asm/kexec.h
> +++ b/arch/loongarch/include/asm/kexec.h
> @@ -43,6 +43,7 @@ struct kimage_arch {
>
> #ifdef CONFIG_KEXEC_FILE
> extern const struct kexec_file_ops kexec_efi_ops;
> +extern const struct kexec_file_ops kexec_elf_ops;
>
> int arch_kimage_file_post_load_cleanup(struct kimage *image);
> #define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup
> diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
> index dd6183f353e6..001924877772 100644
> --- a/arch/loongarch/kernel/Makefile
> +++ b/arch/loongarch/kernel/Makefile
> @@ -62,7 +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_efi.o
> +obj-$(CONFIG_KEXEC_FILE) += machine_kexec_file.o kexec_efi.o kexec_elf.o
> obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
>
> obj-$(CONFIG_UNWINDER_GUESS) += unwind_guess.o
> diff --git a/arch/loongarch/kernel/kexec_elf.c b/arch/loongarch/kernel/kexec_elf.c
> new file mode 100644
> index 000000000000..d41ee5fd7cef
> --- /dev/null
> +++ b/arch/loongarch/kernel/kexec_elf.c
> @@ -0,0 +1,105 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Load ELF vmlinux file for the kexec_file_load syscall.
> + *
> + * Author: Youling Tang <tangyouling@kylinos.cn>
> + * Copyright (C) 2025 KylinSoft Corporation.
> + */
> +
> +#define pr_fmt(fmt) "kexec_file(ELF): " fmt
> +
> +#include <linux/elf.h>
> +#include <linux/kexec.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +#include <linux/memblock.h>
> +#include <asm/image.h>
> +#include <asm/setup.h>
> +
> +static int loongarch_kexec_elf_load(struct kimage *image, struct elfhdr *ehdr,
> + struct kexec_elf_info *elf_info,
> + struct kexec_buf *kbuf,
> + unsigned long *text_offset)
> +{
> + int ret = -1;
> + size_t i;
> +
> + /* Read in the PT_LOAD segments. */
> + for (i = 0; i < ehdr->e_phnum; i++) {
> + size_t size;
> + const struct elf_phdr *phdr;
> + struct loongarch_image_header *header;
> +
> + phdr = &elf_info->proghdrs[i];
> + if (phdr->p_type != PT_LOAD)
> + continue;
> +
> + size = phdr->p_filesz;
> + if (size > phdr->p_memsz)
> + size = phdr->p_memsz;
> +
> + kbuf->buffer = (void *)elf_info->buffer + phdr->p_offset;
> + kbuf->bufsz = size;
> + kbuf->buf_align = phdr->p_align;
> + header = (struct loongarch_image_header *)kbuf->buffer;
> + *text_offset = le64_to_cpu(header->text_offset);
> + kbuf->buf_min = *text_offset;
> + kbuf->memsz = le64_to_cpu(header->image_size);
Elf kernel resolution should not be used to struct loongarch_image_header,
members of the content contained in the inner world of CONFIG_EFI_STUB in
the arch/loongarch/kernel/head.S, should use the content inside the elf
header information, The kexec-tools tool should also be fixed.
However, there is certain content in the elf header information, and the
general kexec_elf_load() function cannot be used. Special processing of
kbuf->memsz and kbuf->memsz is required.
$ readelf -l vmlinux
...
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000010000 0x9000000000200000 0x9000000000200000
0x0000000002747a00 0x000000000287a0d8 RWE 0x10000
NOTE 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 R 0x8
phdr->p_paddr should have been a physical address, but it is a virtual
address on the current LoongArch. This will cause kexec_file to fail
when loading the kernel and need to be converted to a physical address.
Another patch is working to fix this issue[1].
From the above MemSiz, it can be seen that 0x287a0d8 has not been aligned.
Although kexec_add_buffer() will perform PAGE_SIZE alignment on kbuf->memsz,
there is still a stampeding in the loaded kernel space and initrd space.
The initrd resolution failed when starting the second kernel.
It can be known from the link script vmlinux.lds.S that,
BSS_SECTION(0, SZ_64K, 8)
. = ALIGN(PECOFF_SEGMENT_ALIGN);
It needs to be aligned according to the SZ_64K size, so that after
alignment,
its size is consistent with _kernel_asize
(loongarch_image_header->image_size).
The following modifications will be used in the next version to fix it,
--- a/arch/loongarch/kernel/kexec_elf.c
+++ b/arch/loongarch/kernel/kexec_elf.c
@@ -28,7 +28,6 @@ static int loongarch_kexec_elf_load(struct kimage
*image, struct elfhdr *ehdr,
for (i = 0; i < ehdr->e_phnum; i++) {
size_t size;
const struct elf_phdr *phdr;
- struct loongarch_image_header *header;
phdr = &elf_info->proghdrs[i];
if (phdr->p_type != PT_LOAD)
@@ -41,10 +40,9 @@ static int loongarch_kexec_elf_load(struct kimage
*image, struct elfhdr *ehdr,
kbuf->buffer = (void *)elf_info->buffer + phdr->p_offset;
kbuf->bufsz = size;
kbuf->buf_align = phdr->p_align;
- header = (struct loongarch_image_header *)kbuf->buffer;
- *text_offset = le64_to_cpu(header->text_offset);
- kbuf->buf_min = *text_offset;
- kbuf->memsz = le64_to_cpu(header->image_size);
+ *text_offset = __pa(phdr->p_paddr);
+ kbuf->buf_min = _*text_offset;
+ kbuf->memsz = ALIGN(phdr->p_memsz, SZ_64K);
kbuf->mem = KEXEC_BUF_MEM_UNKNOWN;
[1]:
https://lore.kernel.org/loongarch/00651F3A-6649-4C69-B365-352C8D323902@flygoat.com/T/#t
Thanks,
Youling.
> + kbuf->mem = KEXEC_BUF_MEM_UNKNOWN;
> + ret = kexec_add_buffer(kbuf);
> + if (ret)
> + break;
> + }
> +
> + return ret;
> +}
> +
> +static void *elf_kexec_load(struct kimage *image, char *kernel_buf,
> + unsigned long kernel_len, char *initrd,
> + unsigned long initrd_len, char *cmdline,
> + unsigned long cmdline_len)
> +{
> + int ret;
> + unsigned long text_offset = 0, kernel_segment_number;
> + struct elfhdr ehdr;
> + struct kexec_elf_info elf_info;
> + struct kexec_segment *kernel_segment;
> + struct kexec_buf kbuf;
> +
> + ret = kexec_build_elf_info(kernel_buf, kernel_len, &ehdr, &elf_info);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + /* Load the kernel */
> + kbuf.image = image;
> + kbuf.buf_max = ULONG_MAX;
> + kbuf.top_down = false;
> +
> + kernel_segment_number = image->nr_segments;
> +
> + ret = loongarch_kexec_elf_load(image, &ehdr, &elf_info, &kbuf, &text_offset);
> + if (ret)
> + goto out;
> +
> + /* 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)
> + goto out;
> +
> + /* Make sure the second kernel jumps to the correct "kernel_entry". */
> + image->start = kernel_segment->mem + __pa(ehdr.e_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);
> +
> +out:
> + kexec_free_elf_info(&elf_info);
> + return ret ? ERR_PTR(ret) : NULL;
> +}
> +
> +const struct kexec_file_ops kexec_elf_ops = {
> + .probe = kexec_elf_probe,
> + .load = elf_kexec_load,
> +};
> diff --git a/arch/loongarch/kernel/machine_kexec_file.c b/arch/loongarch/kernel/machine_kexec_file.c
> index a713acf32db8..dc6e37457559 100644
> --- a/arch/loongarch/kernel/machine_kexec_file.c
> +++ b/arch/loongarch/kernel/machine_kexec_file.c
> @@ -22,6 +22,7 @@
>
> const struct kexec_file_ops * const kexec_file_loaders[] = {
> &kexec_efi_ops,
> + &kexec_elf_ops,
> NULL
> };
>
next prev parent reply other threads:[~2025-08-21 9:39 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-20 5:56 [PATCH v2 0/5] Add kexec_file support for LoongArch Youling Tang
2025-08-20 5:56 ` [PATCH v2 1/5] LoongArch: Add struct loongarch_image_header for kernel image Youling Tang
2025-08-20 5:56 ` [PATCH v2 2/5] LoongArch: Add kexec_file support Youling Tang
2025-08-20 6:50 ` Yao Zi
2025-08-20 9:13 ` Youling Tang
2025-08-20 11:13 ` Yao Zi
2025-08-21 1:19 ` Youling Tang
2025-08-22 4:24 ` Huacai Chen
2025-08-22 2:56 ` Youling Tang
2025-08-22 4:19 ` Yao Zi
2025-08-22 6:40 ` Huacai Chen
2025-08-26 1:55 ` kernel test robot
2025-08-20 5:56 ` [PATCH v2 3/5] LoongArch/kexec_file: Support loading ELF binary file Youling Tang
2025-08-21 7:14 ` Youling Tang [this message]
2025-08-20 5:56 ` [PATCH v2 4/5] LoongArch/kexec_file: Add crash dump support Youling Tang
2025-08-20 5:57 ` [PATCH v2 5/5] LoongArch: Enable CONFIG_KEXEC_FILE Youling Tang
2025-08-22 4:13 ` [PATCH v2 0/5] Add kexec_file support for LoongArch Huacai Chen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=284a663f-3bdd-4dcc-b017-b1b3fe6d9eb1@linux.dev \
--to=youling.tang@linux.dev \
--cc=bhe@redhat.com \
--cc=chenhuacai@kernel.org \
--cc=kernel@xen0n.name \
--cc=kexec@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=loongarch@lists.linux.dev \
--cc=tangyouling@kylinos.cn \
--cc=ziyao@disroot.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.