Hi all,
This series fixed some issues on bootloader - kernel interface.
The first two fixed booting with devicetree, the last two enhanced kernel's tolerance on different bootloader implementation.
Please review.
Thanks
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- Changes in v2: - Enhance PATCH 3-4 based on off list discussions with Huacai & co. - Link to v1: https://lore.kernel.org/r/20240521-loongarch-booting-fixes-v1-0-659c201c0370...
--- Jiaxun Yang (4): LoongArch: Fix built-in DTB detection LoongArch: smp: Add all CPUs enabled by fdt to NUMA node 0 LoongArch: Fix entry point in image header LoongArch: Override higher address bits in JUMP_VIRT_ADDR
arch/loongarch/include/asm/stackframe.h | 2 +- arch/loongarch/kernel/head.S | 2 +- arch/loongarch/kernel/setup.c | 6 ++++-- arch/loongarch/kernel/smp.c | 5 ++++- drivers/firmware/efi/libstub/loongarch.c | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) --- base-commit: 124cfbcd6d185d4f50be02d5f5afe61578916773 change-id: 20240521-loongarch-booting-fixes-366e13e7ca55
Best regards,
fdt_check_header(__dtb_start) will always success because kernel provided a dummy dtb here, thus fdt passed from firmware will never be taken.
Fix by trying to utilise __dtb_start only when CONFIG_BUILTIN_DTB is enabled.
Fixes: 5f346a6e5970 ("LoongArch: Allow device trees be built into the kernel") Cc: stable@vger.kernel.org Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- arch/loongarch/kernel/setup.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index 60e0fe97f61a..ea6d5db6c878 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -275,16 +275,18 @@ static void __init arch_reserve_crashkernel(void) static void __init fdt_setup(void) { #ifdef CONFIG_OF_EARLY_FLATTREE - void *fdt_pointer; + void *fdt_pointer = NULL;
/* ACPI-based systems do not require parsing fdt */ if (acpi_os_get_root_pointer()) return;
+#ifdef CONFIG_BUILTIN_DTB /* Prefer to use built-in dtb, checking its legality first. */ if (!fdt_check_header(__dtb_start)) fdt_pointer = __dtb_start; - else +#endif + if (!fdt_pointer) fdt_pointer = efi_fdt_pointer(); /* Fallback to firmware dtb */
if (!fdt_pointer || fdt_check_header(fdt_pointer))
NUMA enabled kernel on FDT based machine fails to boot because CPUs are all in NUMA_NO_NODE and mm subsystem won't accept that.
Fix by adding them to default NUMA node for now.
Cc: stable@vger.kernel.org Fixes: 88d4d957edc7 ("LoongArch: Add FDT booting support from efi system table") Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- arch/loongarch/kernel/smp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index 0dfe2388ef41..866757b76ecb 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -273,7 +273,6 @@ static void __init fdt_smp_setup(void)
if (cpuid == loongson_sysconf.boot_cpu_id) { cpu = 0; - numa_add_cpu(cpu); } else { cpu = cpumask_next_zero(-1, cpu_present_mask); } @@ -283,6 +282,10 @@ static void __init fdt_smp_setup(void) set_cpu_present(cpu, true); __cpu_number_map[cpuid] = cpu; __cpu_logical_map[cpu] = cpuid; + + early_numa_add_cpu(cpu, 0); + set_cpuid_to_node(cpuid, 0); + numa_add_cpu(cpu); }
loongson_sysconf.nr_cpus = num_processors;
Hi, Jiaxun,
On Wed, May 22, 2024 at 2:30 PM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
NUMA enabled kernel on FDT based machine fails to boot because CPUs are all in NUMA_NO_NODE and mm subsystem won't accept that.
Fix by adding them to default NUMA node for now.
Cc: stable@vger.kernel.org Fixes: 88d4d957edc7 ("LoongArch: Add FDT booting support from efi system table") Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
arch/loongarch/kernel/smp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index 0dfe2388ef41..866757b76ecb 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -273,7 +273,6 @@ static void __init fdt_smp_setup(void)
if (cpuid == loongson_sysconf.boot_cpu_id) { cpu = 0;
numa_add_cpu(cpu); } else { cpu = cpumask_next_zero(-1, cpu_present_mask); }
@@ -283,6 +282,10 @@ static void __init fdt_smp_setup(void) set_cpu_present(cpu, true); __cpu_number_map[cpuid] = cpu; __cpu_logical_map[cpu] = cpuid;
early_numa_add_cpu(cpu, 0);
set_cpuid_to_node(cpuid, 0);
numa_add_cpu(cpu);
What's wrong exactly? Real machine has no problem here, and at least numa_add_cpu() should not be called for non-zero cpu so early, because it need per-cpu area be setup. I guess the root cause is that there is something wrong and "cpuid == loongson_sysconf.boot_cpu_id" is skipped.
Huacai
} loongson_sysconf.nr_cpus = num_processors;
-- 2.43.0
Currently kernel entry in head.S is in DMW address range, firmware is instructed to jump to this address after loading the 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 applying a calculation to the entry and amend entry calculation logic in libstub accordingly.
Note that due to relocation restriction TO_PHYS can't be used in assembly, we can only do plus and minus here.
Cc: stable@vger.kernel.org Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- v2: Fix efistub --- arch/loongarch/kernel/head.S | 2 +- drivers/firmware/efi/libstub/loongarch.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S index c4f7de2e2805..1a83564023e1 100644 --- a/arch/loongarch/kernel/head.S +++ b/arch/loongarch/kernel/head.S @@ -22,7 +22,7 @@ _head: .word MZ_MAGIC /* "MZ", MS-DOS header */ .org 0x8 - .dword kernel_entry /* Kernel entry point */ + .dword PHYS_LINK_KADDR + (kernel_entry - _head) /* Kernel entry point */ .dword _kernel_asize /* Kernel image effective size */ .quad PHYS_LINK_KADDR /* Kernel image load offset from start of RAM */ .org 0x38 /* 0x20 ~ 0x37 reserved */ diff --git a/drivers/firmware/efi/libstub/loongarch.c b/drivers/firmware/efi/libstub/loongarch.c index 684c9354637c..60c145121393 100644 --- a/drivers/firmware/efi/libstub/loongarch.c +++ b/drivers/firmware/efi/libstub/loongarch.c @@ -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) - TO_PHYS(VMLINUX_LOAD_ADDRESS) + kernel_addr; }
efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
Hi, Jiaxun,
On Wed, May 22, 2024 at 2:30 PM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
Currently kernel entry in head.S is in DMW address range, firmware is instructed to jump to this address after loading the 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 applying a calculation to the entry and amend entry calculation logic in libstub accordingly.
Note that due to relocation restriction TO_PHYS can't be used in assembly, we can only do plus and minus here.
Cc: stable@vger.kernel.org Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
v2: Fix efistub
arch/loongarch/kernel/head.S | 2 +- drivers/firmware/efi/libstub/loongarch.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S index c4f7de2e2805..1a83564023e1 100644 --- a/arch/loongarch/kernel/head.S +++ b/arch/loongarch/kernel/head.S @@ -22,7 +22,7 @@ _head: .word MZ_MAGIC /* "MZ", MS-DOS header */ .org 0x8
.dword kernel_entry /* Kernel entry point */
.dword PHYS_LINK_KADDR + (kernel_entry - _head) /* Kernel entry point */
It could be better to calculate it in the link script, just as _kernel_asize.
Huacai
.dword _kernel_asize /* Kernel image effective size */ .quad PHYS_LINK_KADDR /* Kernel image load offset from start of RAM */ .org 0x38 /* 0x20 ~ 0x37 reserved */
diff --git a/drivers/firmware/efi/libstub/loongarch.c b/drivers/firmware/efi/libstub/loongarch.c index 684c9354637c..60c145121393 100644 --- a/drivers/firmware/efi/libstub/loongarch.c +++ b/drivers/firmware/efi/libstub/loongarch.c @@ -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) - TO_PHYS(VMLINUX_LOAD_ADDRESS) + kernel_addr;
}
efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
-- 2.43.0
In JUMP_VIRT_ADDR we are performing an or calculation on address value directly from pcaddi.
This will only work if we are currently running from direct 1:1 mapping addresses or firmware's DMW is configured exactly same as kernel. Still, we should not rely on such assumption.
Fix by overriding higher bits in address comes from pcaddi, so we can get rid of or operator.
Cc: stable@vger.kernel.org Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- v2: Overriding address with bstrins --- arch/loongarch/include/asm/stackframe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/loongarch/include/asm/stackframe.h b/arch/loongarch/include/asm/stackframe.h index 45b507a7b06f..51dec8b17d16 100644 --- a/arch/loongarch/include/asm/stackframe.h +++ b/arch/loongarch/include/asm/stackframe.h @@ -42,7 +42,7 @@ .macro JUMP_VIRT_ADDR temp1 temp2 li.d \temp1, CACHE_BASE pcaddi \temp2, 0 - or \temp1, \temp1, \temp2 + bstrins.d \temp1, \temp2, (DMW_PABITS - 1), 0 jirl zero, \temp1, 0xc .endm
Hi, Jiaxun,
On Wed, May 22, 2024 at 2:30 PM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
In JUMP_VIRT_ADDR we are performing an or calculation on address value directly from pcaddi.
This will only work if we are currently running from direct 1:1 mapping addresses or firmware's DMW is configured exactly same as kernel. Still, we should not rely on such assumption.
Fix by overriding higher bits in address comes from pcaddi, so we can get rid of or operator.
Cc: stable@vger.kernel.org Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
v2: Overriding address with bstrins
arch/loongarch/include/asm/stackframe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/loongarch/include/asm/stackframe.h b/arch/loongarch/include/asm/stackframe.h index 45b507a7b06f..51dec8b17d16 100644 --- a/arch/loongarch/include/asm/stackframe.h +++ b/arch/loongarch/include/asm/stackframe.h @@ -42,7 +42,7 @@ .macro JUMP_VIRT_ADDR temp1 temp2 li.d \temp1, CACHE_BASE pcaddi \temp2, 0
or \temp1, \temp1, \temp2
bstrins.d \temp1, \temp2, (DMW_PABITS - 1), 0 jirl zero, \temp1, 0xc .endm
Can we align the first parameter about the first parameter?
Huacai
-- 2.43.0
linux-stable-mirror@lists.linaro.org