From: Youling Tang <[email protected]>

Without enabling the RELOCATABLE configuration, LoongArch is a non-PIE kernel
and cannot be loaded to run at any appropriate address. So the CRASH_DUMP
feature depends on RELOCATABLE.

$ cat arch/loongarch/Kconfig
config ARCH_SELECTS_CRASH_DUMP
        def_bool y
        depends on CRASH_DUMP
        select RELOCATABLE

The relocatable kernel is determined by checking if there is a la_abs section.
Currently, only the elf format has been checked, while pei/pez is in the FIXME
state.

Signed-off-by: Youling Tang <[email protected]>
---
 kexec/arch/loongarch/kexec-elf-loongarch.c | 32 ++++++++++++++++++++++
 kexec/arch/loongarch/kexec-pei-loongarch.c |  3 ++
 2 files changed, 35 insertions(+)

diff --git a/kexec/arch/loongarch/kexec-elf-loongarch.c 
b/kexec/arch/loongarch/kexec-elf-loongarch.c
index c87f022..44b63a9 100644
--- a/kexec/arch/loongarch/kexec-elf-loongarch.c
+++ b/kexec/arch/loongarch/kexec-elf-loongarch.c
@@ -13,6 +13,7 @@
 #include <limits.h>
 #include <errno.h>
 #include <elf.h>
+#include <stdbool.h>
 
 #include "kexec.h"
 #include "kexec-elf.h"
@@ -47,6 +48,27 @@ out:
        return result;
 }
 
+/*
+ * To determine whether it is a relocatable kernel based on the ".la_abs 
"section,
+ * the CRASH_DUMP feature depends on CONFIG_RELOCATABLE in LoongArch.
+ */
+static bool laabs_section(const struct mem_ehdr *ehdr)
+{
+       struct mem_shdr *shdr, *shdr_end;
+       unsigned char *strtab;
+
+       strtab = (unsigned char *)ehdr->e_shdr[ehdr->e_shstrndx].sh_data;
+       shdr_end = &ehdr->e_shdr[ehdr->e_shnum];
+       for (shdr = ehdr->e_shdr; shdr != shdr_end; shdr++) {
+               if (shdr->sh_size &&
+                       strcmp((char *)&strtab[shdr->sh_name], ".la_abs") == 0) 
{
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 int elf_loongarch_load(int argc, char **argv, const char *kernel_buf,
        off_t kernel_size, struct kexec_info *info)
 {
@@ -63,6 +85,16 @@ int elf_loongarch_load(int argc, char **argv, const char 
*kernel_buf,
                goto exit;
        }
 
+       if (info->kexec_flags & KEXEC_ON_CRASH) {
+               bool is_relocatable_kernel = laabs_section(&ehdr);
+               if (!is_relocatable_kernel) {
+                       dbgprintf("%s: The non-relocation kernel cannot be 
loaded, "
+                                  "CONFIG_RELOCATABLE needs to be enabled\n", 
__func__);
+                       result = EFAILED;
+                       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];
diff --git a/kexec/arch/loongarch/kexec-pei-loongarch.c 
b/kexec/arch/loongarch/kexec-pei-loongarch.c
index f0e0d09..1a19a39 100644
--- a/kexec/arch/loongarch/kexec-pei-loongarch.c
+++ b/kexec/arch/loongarch/kexec-pei-loongarch.c
@@ -99,6 +99,9 @@ int pei_loongarch_load(int argc, char **argv, const char *buf,
                }
        }
 
+       /* Fixme: Loading a non-relocation kernel will cause the second kernel 
to fail
+          to start in KEXEC_ON_CRASH */
+
        /* Load the kernel */
        add_segment(info, buf, len, kernel_segment, loongarch_mem.image_size);
 
-- 
2.34.1


Reply via email to