Fix loongarch64 kdump image size overflow issue.

Signed-off-by: Ming Wang <wangming01@loongson.cn>
This commit is contained in:
Ming Wang 2025-01-06 15:08:17 +08:00
parent d32942056f
commit 494f36b4e4
4 changed files with 281 additions and 5 deletions

View File

@ -0,0 +1,26 @@
From fe71ffabcc7e5787b0bcf0b4cfcdab83182b84fd Mon Sep 17 00:00:00 2001
From: Ming Wang <wangming01@loongson.cn>
Date: Mon, 14 Oct 2024 16:23:08 +0800
Subject: [PATCH] Fix incorrect page exclusion in exclude_nodata_pages()
Signed-off-by: Ming Wang <wangming01@loongson.cn>
---
makedumpfile-1.7.4/makedumpfile.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/makedumpfile-1.7.4/makedumpfile.c b/makedumpfile-1.7.4/makedumpfile.c
index a6ec9d4..4ddbf4d 100644
--- a/makedumpfile-1.7.4/makedumpfile.c
+++ b/makedumpfile-1.7.4/makedumpfile.c
@@ -5192,7 +5192,7 @@ exclude_nodata_pages(struct cycle *cycle)
NULL, &file_size)) {
unsigned long long pfn, pfn_end;
- pfn = paddr_to_pfn(phys_start + file_size);
+ pfn = paddr_to_pfn(roundup(phys_start + file_size, PAGESIZE()));
pfn_end = paddr_to_pfn(roundup(phys_end, PAGESIZE()));
if (pfn < cycle->start_pfn)
--
2.41.0

8
kdump.sysconfig.loongarch64 Executable file → Normal file
View File

@ -21,7 +21,7 @@ KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug quiet log_buf_len rd_s
# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="nr_cpus=1 init 3 irqpoll reset_devices cgroup_disable=memory udev.children-max=2 panic=10 novmcoredd"
KDUMP_COMMANDLINE_APPEND="nr_cpus=1 init 3 irqpoll reset_devices cgroup_disable=memory udev.children-max=2 panic=10 novmcoredd nokaslr"
# Any additional kexec arguments required. In most situations, this should
# be left empty
@ -34,7 +34,7 @@ KEXEC_ARGS=""
#KDUMP_BOOTDIR="/boot"
#What is the image type used for kdump
KDUMP_IMG="vmlinux"
KDUMP_IMG="vmlinuz"
#Please replace with the capture kernel to be reboot and the
#the corresponding initrd only for LoongArch architecture
@ -43,10 +43,10 @@ KDUMP_IMG="vmlinux"
# DEFAULT_TARGET_INITRD="/boot/initramfs-4.19.190-4.lns8.loongarch64+kdump.img"
# If a DEFAULT_KDUMP_KERNEL is not specified, the default is set to
# "/boot/vmlinux-$(uname -r)+kdump"
DEFAULT_KDUMP_KERNEL=""
# DEFAULT_KDUMP_KERNEL=""
# If a DEFAULT_TARGET_INITRD is not specified, the default is set to
# "/boot/initramfs-$(uname -r)+kdump.img"
DEFAULT_TARGET_INITRD=""
# DEFAULT_TARGET_INITRD=""
# Logging is controlled by following variables in the first kernel:
# - @var KDUMP_STDLOGLVL - logging level to standard error (console output)

View File

@ -4,7 +4,7 @@
Name: kexec-tools
Version: 2.0.26
Release: 9
Release: 10
License: GPLv2
Summary: The kexec/kdump userspace component
URL: https://www.kernel.org/
@ -86,6 +86,8 @@ Patch0007: kexec-tools-fix-riscv-support.patch
%ifarch loongarch64
Patch0008: Add-loongarch-iomem.h.patch
Patch0009: Fix-incorrect-page-exclusion-in-exclude_nodata_pages.patch
Patch0010: loongarch64-fix-kernel-image-size-error.patch
%endif
%description
@ -295,6 +297,9 @@ done
%endif
%changelog
* Mon Jan 6 2025 Ming Wang <wangming01@loongson.cn> - 2.0.26-10
- Fix loongarch kdump image size overflow issue.
* Fri Sep 20 2024 chenguokai <chenguokai123@live.com> - 2.0.26-9
- Fix multiple issues of riscv image format & initrd support

View File

@ -0,0 +1,245 @@
From 510981a6b810c18d1bc3f5917ad743f3a6c85cf7 Mon Sep 17 00:00:00 2001
From: Ming Wang <wangming01@loongson.cn>
Date: Fri, 17 May 2024 10:39:31 +0800
Subject: [PATCH] kexec: loongarch: fix some issue.
Signed-off-by: Hongchen Zhang <zhanghongchen@loongson.cn>
Signed-off-by: Ming Wang <wangming01@loongson.cn>
---
kexec/arch/loongarch/crashdump-loongarch.c | 22 ++++++++++++
kexec/arch/loongarch/crashdump-loongarch.h | 1 +
kexec/arch/loongarch/kexec-elf-loongarch.c | 40 +++++++++++++++++++---
kexec/arch/loongarch/kexec-loongarch.c | 22 ++++++++----
kexec/arch/loongarch/kexec-pei-loongarch.c | 7 ++++
kexec/kexec-syscall.h | 2 +-
6 files changed, 82 insertions(+), 12 deletions(-)
diff --git a/kexec/arch/loongarch/crashdump-loongarch.c b/kexec/arch/loongarch/crashdump-loongarch.c
index aaf6cf3..81250e4 100644
--- a/kexec/arch/loongarch/crashdump-loongarch.c
+++ b/kexec/arch/loongarch/crashdump-loongarch.c
@@ -183,6 +183,28 @@ int load_crashdump_segments(struct kexec_info *info)
return 0;
}
+/*
+ * e_entry and p_paddr are actually in virtual address space.
+ * Those values will be translated to physcal addresses by using
+ * virt_to_phys() in add_segment().
+ * So let's fix up those values for later use so the memory base will be
+ * correctly replaced with crash_reserved_mem[usablemem_rgns.size - 1].start.
+ */
+void fixup_elf_addrs(struct mem_ehdr *ehdr)
+{
+ struct mem_phdr *phdr;
+ int i;
+
+ ehdr->e_entry += crash_reserved_mem[usablemem_rgns.size - 1].start;
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ phdr = &ehdr->e_phdr[i];
+ if (phdr->p_type != PT_LOAD)
+ continue;
+ phdr->p_paddr += crash_reserved_mem[usablemem_rgns.size - 1].start;
+ }
+}
+
int get_crash_kernel_load_range(uint64_t *start, uint64_t *end)
{
if (!usablemem_rgns.size)
diff --git a/kexec/arch/loongarch/crashdump-loongarch.h b/kexec/arch/loongarch/crashdump-loongarch.h
index 3eb4e0a..25ff24b 100644
--- a/kexec/arch/loongarch/crashdump-loongarch.h
+++ b/kexec/arch/loongarch/crashdump-loongarch.h
@@ -8,6 +8,7 @@ extern struct memory_range elfcorehdr_mem;
int load_crashdump_segments(struct kexec_info *info);
int is_crashkernel_mem_reserved(void);
+void fixup_elf_addrs(struct mem_ehdr *ehdr);
int get_crash_kernel_load_range(uint64_t *start, uint64_t *end);
#define PAGE_OFFSET 0x9000000000000000ULL
diff --git a/kexec/arch/loongarch/kexec-elf-loongarch.c b/kexec/arch/loongarch/kexec-elf-loongarch.c
index 2bf128f..7e84d03 100644
--- a/kexec/arch/loongarch/kexec-elf-loongarch.c
+++ b/kexec/arch/loongarch/kexec-elf-loongarch.c
@@ -54,6 +54,7 @@ int elf_loongarch_load(int argc, char **argv, const char *kernel_buf,
unsigned long kernel_segment;
struct mem_ehdr ehdr;
int result;
+ int i;
result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0);
@@ -62,6 +63,26 @@ int elf_loongarch_load(int argc, char **argv, const char *kernel_buf,
goto exit;
}
+ /* Find and process the loongarch image header. */
+ for (i = 0; i < ehdr.e_phnum; i++) {
+ struct mem_phdr *phdr = &ehdr.e_phdr[i];
+
+ if (phdr->p_type != PT_LOAD)
+ continue;
+
+ header = (const struct loongarch_image_header *)(
+ kernel_buf + phdr->p_offset);
+
+ if (!loongarch_process_image_header(header))
+ break;
+ }
+
+ if (i == ehdr.e_phnum) {
+ dbgprintf("%s: Valid loongarch image header not found\n", __func__);
+ result = EFAILED;
+ goto exit;
+ }
+
kernel_segment = loongarch_locate_kernel_segment(info);
if (kernel_segment == ULONG_MAX) {
@@ -72,13 +93,12 @@ int elf_loongarch_load(int argc, char **argv, const char *kernel_buf,
dbgprintf("%s: kernel_segment: %016lx\n", __func__, kernel_segment);
dbgprintf("%s: image_size: %016lx\n", __func__,
- kernel_size);
+ loongarch_mem.image_size);
dbgprintf("%s: text_offset: %016lx\n", __func__,
loongarch_mem.text_offset);
dbgprintf("%s: phys_offset: %016lx\n", __func__,
loongarch_mem.phys_offset);
- dbgprintf("%s: PE format: %s\n", __func__,
- (loongarch_header_check_pe_sig(header) ? "yes" : "no"));
+ dbgprintf("%s: PE format: no\n", __func__);
/* create and initialize elf core header segment */
if (info->kexec_flags & KEXEC_ON_CRASH) {
@@ -90,6 +110,14 @@ int elf_loongarch_load(int argc, char **argv, const char *kernel_buf,
}
}
+ /* load the kernel */
+ if (info->kexec_flags & KEXEC_ON_CRASH)
+ /*
+ * offset addresses in elf header in order to load
+ * vmlinux (elf_exec) into crash kernel's memory.
+ */
+ fixup_elf_addrs(&ehdr);
+
info->entry = (void *)virt_to_phys(ehdr.e_entry);
result = elf_exec_load(&ehdr, info);
@@ -99,8 +127,12 @@ int elf_loongarch_load(int argc, char **argv, const char *kernel_buf,
goto exit;
}
+ /* for vmlinuz kernel image */
+ if (kernel_size < MiB(16))
+ kernel_size = MiB(64);
+
/* load additional data */
- result = loongarch_load_other_segments(info, kernel_segment + kernel_size);
+ result = loongarch_load_other_segments(info, kernel_segment + loongarch_mem.image_size);
exit:
free_elf_info(&ehdr);
diff --git a/kexec/arch/loongarch/kexec-loongarch.c b/kexec/arch/loongarch/kexec-loongarch.c
index 4c7361c..6485080 100644
--- a/kexec/arch/loongarch/kexec-loongarch.c
+++ b/kexec/arch/loongarch/kexec-loongarch.c
@@ -221,6 +221,10 @@ int arch_process_options(int argc, char **argv)
cmdline = get_command_line();
remove_parameter(cmdline, "kexec");
remove_parameter(cmdline, "initrd");
+ remove_parameter(cmdline, "rd_start");
+ remove_parameter(cmdline, "rd_size");
+ remove_parameter(cmdline, "vfio_iommu_type1.allow_unsafe_interrupts");
+ remove_parameter(cmdline, "nokaslr");
break;
case OPT_INITRD:
arch_options.initrd_file = optarg;
@@ -253,8 +257,9 @@ unsigned long loongarch_locate_kernel_segment(struct kexec_info *info)
unsigned long hole_end;
hole = (crash_reserved_mem[usablemem_rgns.size - 1].start < mem_min ?
- mem_min : crash_reserved_mem[usablemem_rgns.size - 1].start);
- hole = _ALIGN_UP(hole, MiB(1));
+ mem_min : crash_reserved_mem[usablemem_rgns.size - 1].start) +
+ loongarch_mem.text_offset;
+ hole = _ALIGN_UP(hole, MiB(16));
hole_end = hole + loongarch_mem.text_offset + loongarch_mem.image_size;
if ((hole_end > mem_max) ||
@@ -265,7 +270,7 @@ unsigned long loongarch_locate_kernel_segment(struct kexec_info *info)
} else {
hole = locate_hole(info,
loongarch_mem.text_offset + loongarch_mem.image_size,
- MiB(1), 0, ULONG_MAX, 1);
+ MiB(16), 0, ULONG_MAX, 1);
if (hole == ULONG_MAX)
dbgprintf("%s: locate_hole failed\n", __func__);
@@ -283,6 +288,7 @@ int loongarch_load_other_segments(struct kexec_info *info, unsigned long hole_mi
unsigned long initrd_min, hole_max;
char *initrd_buf = NULL;
unsigned long pagesize = getpagesize();
+ int i;
if (arch_options.command_line) {
if (strlen(arch_options.command_line) >
@@ -320,15 +326,17 @@ int loongarch_load_other_segments(struct kexec_info *info, unsigned long hole_mi
cmdline_add_elfcorehdr(cmdline, elfcorehdr_mem.start,
elfcorehdr_mem.end - elfcorehdr_mem.start + 1);
- cmdline_add_mem(cmdline, crash_reserved_mem[usablemem_rgns.size - 1].start,
- crash_reserved_mem[usablemem_rgns.size - 1].end -
- crash_reserved_mem[usablemem_rgns.size - 1].start + 1);
+ for(i = 0;i < usablemem_rgns.size; i++) {
+ cmdline_add_mem(cmdline, crash_reserved_mem[i].start,
+ crash_reserved_mem[i].end -
+ crash_reserved_mem[i].start + 1);
+ }
}
cmdline[sizeof(cmdline) - 1] = 0;
add_buffer(info, cmdline, sizeof(cmdline), sizeof(cmdline),
sizeof(void *), _ALIGN_UP(hole_min, getpagesize()),
- 0xffffffff, 1);
+ hole_max, 1);
dbgprintf("%s:%d: command_line: %s\n", __func__, __LINE__, cmdline);
diff --git a/kexec/arch/loongarch/kexec-pei-loongarch.c b/kexec/arch/loongarch/kexec-pei-loongarch.c
index f86ac61..1a11103 100644
--- a/kexec/arch/loongarch/kexec-pei-loongarch.c
+++ b/kexec/arch/loongarch/kexec-pei-loongarch.c
@@ -66,6 +66,13 @@ int pei_loongarch_load(int argc, char **argv, const char *buf,
kernel_entry = virt_to_phys(loongarch_header_kernel_entry(header));
+ if (info->kexec_flags & KEXEC_ON_CRASH)
+ /*
+ * offset addresses in order to load vmlinux.efi into
+ * crash kernel's memory.
+ */
+ kernel_entry += crash_reserved_mem[usablemem_rgns.size - 1].start;
+
dbgprintf("%s: kernel_segment: %016lx\n", __func__, kernel_segment);
dbgprintf("%s: kernel_entry: %016lx\n", __func__, kernel_entry);
dbgprintf("%s: image_size: %016lx\n", __func__,
diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
index e392c01..f18b014 100644
--- a/kexec/kexec-syscall.h
+++ b/kexec/kexec-syscall.h
@@ -59,7 +59,7 @@
#endif
#endif /*ifndef __NR_kexec_load*/
-#ifdef __arm__
+#if defined(__arm__) || defined(__loongarch__)
#undef __NR_kexec_file_load
#endif
--
2.43.0