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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Jun 2024 11:49:15 +0000 (13:49 +0200)
[ Upstream commit beb2800074c15362cf9f6c7301120910046d6556 ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/loongarch/kernel/head.S
arch/loongarch/kernel/vmlinux.lds.S
drivers/firmware/efi/libstub/loongarch.c

index 0ecab4216392899cf8655d0d67228cb280c6df02..e336fbc4eb9675ce5d33c29d2f786833de9aaf02 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 a5d0cd2035da04c9797bf5cee73a04ecd0b52bda..d5afd0c80a49990ef8c7c3b499014d033d940bf9 100644 (file)
@@ -5,6 +5,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
@@ -139,10 +140,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,