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-tangyoul...@loongson.cn/T/#t

Signed-off-by: Youling Tang <tangyoul...@loongson.cn>
---
 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@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to