LoongArch: Fix entry point in kernel image header
authorJiaxun Yang <jiaxun.yang@flygoat.com>
Mon, 3 Jun 2024 07:45:53 +0000 (15:45 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Mon, 3 Jun 2024 07:45:53 +0000 (15:45 +0800)
Currently kernel entry in head.S is in DMW address range, firmware is
instructed to jump to this address after loading the kernel image.

However kernel should not make any assumption on firmware's DMW
setting, thus the entry point should be a physical address falls into
direct translation region.

Fix by converting entry address to physical and amend entry calculation
logic in libstub accordingly.

BTW, use ABSOLUTE() to calculate variables to make Clang/LLVM happy.

Cc: stable@vger.kernel.org
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/kernel/head.S
arch/loongarch/kernel/vmlinux.lds.S
drivers/firmware/efi/libstub/loongarch.c

index c4f7de2e28054ceb6458c964c26e86596cea8602..4677ea8fa8e98cad8b11b5ea89d7811500be738e 100644 (file)
@@ -22,7 +22,7 @@
 _head:
        .word   MZ_MAGIC                /* "MZ", MS-DOS header */
        .org    0x8
-       .dword  kernel_entry            /* Kernel entry point */
+       .dword  _kernel_entry           /* Kernel entry point (physical address) */
        .dword  _kernel_asize           /* Kernel image effective size */
        .quad   PHYS_LINK_KADDR         /* Kernel image load offset from start of RAM */
        .org    0x38                    /* 0x20 ~ 0x37 reserved */
index e8e97dbf9ca40ff243e33f1d2cfa9fdbb59d54b4..3c7595342730ed2c1e76c343e16553180fbd167d 100644 (file)
@@ -6,6 +6,7 @@
 
 #define PAGE_SIZE _PAGE_SIZE
 #define RO_EXCEPTION_TABLE_ALIGN       4
+#define PHYSADDR_MASK                  0xffffffffffff /* 48-bit */
 
 /*
  * Put .bss..swapper_pg_dir as the first thing in .bss. This will
@@ -142,10 +143,11 @@ SECTIONS
 
 #ifdef CONFIG_EFI_STUB
        /* header symbols */
-       _kernel_asize = _end - _text;
-       _kernel_fsize = _edata - _text;
-       _kernel_vsize = _end - __initdata_begin;
-       _kernel_rsize = _edata - __initdata_begin;
+       _kernel_entry = ABSOLUTE(kernel_entry & PHYSADDR_MASK);
+       _kernel_asize = ABSOLUTE(_end - _text);
+       _kernel_fsize = ABSOLUTE(_edata - _text);
+       _kernel_vsize = ABSOLUTE(_end - __initdata_begin);
+       _kernel_rsize = ABSOLUTE(_edata - __initdata_begin);
 #endif
 
        .gptab.sdata : {
index 684c9354637c6541c1d695ab93e80551f6c5cc1e..d0ef93551c44f64affb5a152b277a8b0c4e827fb 100644 (file)
@@ -41,7 +41,7 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
 unsigned long __weak kernel_entry_address(unsigned long kernel_addr,
                efi_loaded_image_t *image)
 {
-       return *(unsigned long *)(kernel_addr + 8) - VMLINUX_LOAD_ADDRESS + kernel_addr;
+       return *(unsigned long *)(kernel_addr + 8) - PHYSADDR(VMLINUX_LOAD_ADDRESS) + kernel_addr;
 }
 
 efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,