On LoongArch, we can use the same kernel image as 1st kernel when [1] is merged, but we have to modify the entry point as well as segments' addresses in the kernel's elf header (or pei format vmlinux.efi) in order to load them into correct places. [1]: https://lore.kernel.org/loongarch/1677150391-12838-1-git-send-email-tangyouling@xxxxxxxxxxx/T/#t Signed-off-by: Youling Tang <tangyouling@xxxxxxxxxxx> --- kexec/arch/loongarch/crashdump-loongarch.c | 22 ++++++++++++++++++++++ kexec/arch/loongarch/crashdump-loongarch.h | 1 + kexec/arch/loongarch/kexec-elf-loongarch.c | 8 ++++++++ kexec/arch/loongarch/kexec-loongarch.c | 3 ++- kexec/arch/loongarch/kexec-pei-loongarch.c | 7 +++++++ 5 files changed, 40 insertions(+), 1 deletion(-) 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..45387ca 100644 --- a/kexec/arch/loongarch/kexec-elf-loongarch.c +++ b/kexec/arch/loongarch/kexec-elf-loongarch.c @@ -90,6 +90,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); diff --git a/kexec/arch/loongarch/kexec-loongarch.c b/kexec/arch/loongarch/kexec-loongarch.c index 4c7361c..f47c998 100644 --- a/kexec/arch/loongarch/kexec-loongarch.c +++ b/kexec/arch/loongarch/kexec-loongarch.c @@ -253,7 +253,8 @@ 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); + mem_min : crash_reserved_mem[usablemem_rgns.size - 1].start) + + loongarch_mem.text_offset; hole = _ALIGN_UP(hole, MiB(1)); hole_end = hole + loongarch_mem.text_offset + loongarch_mem.image_size; 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__, -- 2.37.1 _______________________________________________ kexec mailing list kexec@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec