[PATCH V2 04/14] LoongArch: Adjust boot & setup for 32BIT/64BIT

Huacai Chen posted 14 patches 1 week, 6 days ago
There is a newer version of this series
[PATCH V2 04/14] LoongArch: Adjust boot & setup for 32BIT/64BIT
Posted by Huacai Chen 1 week, 6 days ago
Adjust boot & setup for both 32BIT and 64BIT, including: efi header
definition, MAX_IO_PICS definition, kernel entry and environment setup
routines, etc.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
---
 arch/loongarch/include/asm/addrspace.h |  2 +-
 arch/loongarch/include/asm/irq.h       |  5 ++++
 arch/loongarch/kernel/efi-header.S     |  4 +++
 arch/loongarch/kernel/efi.c            |  4 ++-
 arch/loongarch/kernel/env.c            |  9 ++++--
 arch/loongarch/kernel/head.S           | 39 +++++++++++---------------
 arch/loongarch/kernel/relocate.c       |  9 +++++-
 7 files changed, 45 insertions(+), 27 deletions(-)

diff --git a/arch/loongarch/include/asm/addrspace.h b/arch/loongarch/include/asm/addrspace.h
index e739dbc6329d..9766a100504a 100644
--- a/arch/loongarch/include/asm/addrspace.h
+++ b/arch/loongarch/include/asm/addrspace.h
@@ -42,7 +42,7 @@ extern unsigned long vm_map_base;
 #endif
 
 #define DMW_PABITS	48
-#define TO_PHYS_MASK	((1ULL << DMW_PABITS) - 1)
+#define TO_PHYS_MASK	((_ULL(1) << _ULL(DMW_PABITS)) - 1)
 
 /*
  * Memory above this physical address will be considered highmem.
diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h
index 12bd15578c33..cf6c82a9117b 100644
--- a/arch/loongarch/include/asm/irq.h
+++ b/arch/loongarch/include/asm/irq.h
@@ -53,7 +53,12 @@ void spurious_interrupt(void);
 #define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace
 void arch_trigger_cpumask_backtrace(const struct cpumask *mask, int exclude_cpu);
 
+#ifdef CONFIG_32BIT
+#define MAX_IO_PICS 1
+#else
 #define MAX_IO_PICS 8
+#endif
+
 #define NR_IRQS	(64 + NR_VECTORS * (NR_CPUS + MAX_IO_PICS))
 
 struct acpi_vector_group {
diff --git a/arch/loongarch/kernel/efi-header.S b/arch/loongarch/kernel/efi-header.S
index ba0bdbf86aa8..6df56241cb95 100644
--- a/arch/loongarch/kernel/efi-header.S
+++ b/arch/loongarch/kernel/efi-header.S
@@ -9,7 +9,11 @@
 	.macro	__EFI_PE_HEADER
 	.long	IMAGE_NT_SIGNATURE
 .Lcoff_header:
+#ifdef CONFIG_32BIT
+	.short	IMAGE_FILE_MACHINE_LOONGARCH32		/* Machine */
+#else
 	.short	IMAGE_FILE_MACHINE_LOONGARCH64		/* Machine */
+#endif
 	.short	.Lsection_count				/* NumberOfSections */
 	.long	0 					/* TimeDateStamp */
 	.long	0					/* PointerToSymbolTable */
diff --git a/arch/loongarch/kernel/efi.c b/arch/loongarch/kernel/efi.c
index 860a3bc030e0..52c21c895318 100644
--- a/arch/loongarch/kernel/efi.c
+++ b/arch/loongarch/kernel/efi.c
@@ -115,7 +115,9 @@ void __init efi_init(void)
 
 	efi_systab_report_header(&efi_systab->hdr, efi_systab->fw_vendor);
 
-	set_bit(EFI_64BIT, &efi.flags);
+	if (IS_ENABLED(CONFIG_64BIT))
+		set_bit(EFI_64BIT, &efi.flags);
+
 	efi_nr_tables	 = efi_systab->nr_tables;
 	efi_config_table = (unsigned long)efi_systab->tables;
 
diff --git a/arch/loongarch/kernel/env.c b/arch/loongarch/kernel/env.c
index 23bd5ae2212c..3e8a25eb901b 100644
--- a/arch/loongarch/kernel/env.c
+++ b/arch/loongarch/kernel/env.c
@@ -68,18 +68,23 @@ static int __init fdt_cpu_clk_init(void)
 
 	np = of_get_cpu_node(0, NULL);
 	if (!np)
-		return -ENODEV;
+		goto fallback;
 
 	clk = of_clk_get(np, 0);
 	of_node_put(np);
 
 	if (IS_ERR(clk))
-		return -ENODEV;
+		goto fallback;
 
 	cpu_clock_freq = clk_get_rate(clk);
 	clk_put(clk);
 
 	return 0;
+
+fallback:
+	cpu_clock_freq = 200 * 1000 * 1000;
+
+	return -ENODEV;
 }
 late_initcall(fdt_cpu_clk_init);
 
diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S
index e3865e92a917..aba548db2446 100644
--- a/arch/loongarch/kernel/head.S
+++ b/arch/loongarch/kernel/head.S
@@ -43,36 +43,29 @@ SYM_DATA(kernel_fsize, .long _kernel_fsize);
 
 SYM_CODE_START(kernel_entry)			# kernel entry point
 
-	/* Config direct window and set PG */
-	SETUP_DMWINS	t0
+	SETUP_TWINS
+	SETUP_MODES	t0
 	JUMP_VIRT_ADDR	t0, t1
-
-	/* Enable PG */
-	li.w		t0, 0xb0		# PLV=0, IE=0, PG=1
-	csrwr		t0, LOONGARCH_CSR_CRMD
-	li.w		t0, 0x04		# PLV=0, PIE=1, PWE=0
-	csrwr		t0, LOONGARCH_CSR_PRMD
-	li.w		t0, 0x00		# FPE=0, SXE=0, ASXE=0, BTE=0
-	csrwr		t0, LOONGARCH_CSR_EUEN
+	SETUP_DMWINS	t0
 
 	la.pcrel	t0, __bss_start		# clear .bss
-	st.d		zero, t0, 0
+	LONG_S		zero, t0, 0
 	la.pcrel	t1, __bss_stop - LONGSIZE
 1:
-	addi.d		t0, t0, LONGSIZE
-	st.d		zero, t0, 0
+	PTR_ADDI	t0, t0, LONGSIZE
+	LONG_S		zero, t0, 0
 	bne		t0, t1, 1b
 
 	la.pcrel	t0, fw_arg0
-	st.d		a0, t0, 0		# firmware arguments
+	PTR_S		a0, t0, 0		# firmware arguments
 	la.pcrel	t0, fw_arg1
-	st.d		a1, t0, 0
+	PTR_S		a1, t0, 0
 	la.pcrel	t0, fw_arg2
-	st.d		a2, t0, 0
+	PTR_S		a2, t0, 0
 
 #ifdef CONFIG_PAGE_SIZE_4KB
-	li.d		t0, 0
-	li.d		t1, CSR_STFILL
+	LONG_LI		t0, 0
+	LONG_LI		t1, CSR_STFILL
 	csrxchg		t0, t1, LOONGARCH_CSR_IMPCTL1
 #endif
 	/* KSave3 used for percpu base, initialized as 0 */
@@ -98,7 +91,7 @@ SYM_CODE_START(kernel_entry)			# kernel entry point
 
 	/* Jump to the new kernel: new_pc = current_pc + random_offset */
 	pcaddi		t0, 0
-	add.d		t0, t0, a0
+	PTR_ADD		t0, t0, a0
 	jirl		zero, t0, 0xc
 #endif /* CONFIG_RANDOMIZE_BASE */
 
@@ -121,12 +114,14 @@ SYM_CODE_END(kernel_entry)
  */
 SYM_CODE_START(smpboot_entry)
 
-	SETUP_DMWINS	t0
+	SETUP_TWINS
+	SETUP_MODES	t0
 	JUMP_VIRT_ADDR	t0, t1
+	SETUP_DMWINS	t0
 
 #ifdef CONFIG_PAGE_SIZE_4KB
-	li.d		t0, 0
-	li.d		t1, CSR_STFILL
+	LONG_LI		t0, 0
+	LONG_LI		t1, CSR_STFILL
 	csrxchg		t0, t1, LOONGARCH_CSR_IMPCTL1
 #endif
 	/* Enable PG */
diff --git a/arch/loongarch/kernel/relocate.c b/arch/loongarch/kernel/relocate.c
index b5e2312a2fca..c28ba45d80d6 100644
--- a/arch/loongarch/kernel/relocate.c
+++ b/arch/loongarch/kernel/relocate.c
@@ -68,18 +68,25 @@ static inline void __init relocate_absolute(long random_offset)
 
 	for (p = begin; (void *)p < end; p++) {
 		long v = p->symvalue;
-		uint32_t lu12iw, ori, lu32id, lu52id;
+		uint32_t lu12iw, ori;
+#ifdef CONFIG_64BIT
+		uint32_t lu32id, lu52id;
+#endif
 		union loongarch_instruction *insn = (void *)p->pc;
 
 		lu12iw = (v >> 12) & 0xfffff;
 		ori    = v & 0xfff;
+#ifdef CONFIG_64BIT
 		lu32id = (v >> 32) & 0xfffff;
 		lu52id = v >> 52;
+#endif
 
 		insn[0].reg1i20_format.immediate = lu12iw;
 		insn[1].reg2i12_format.immediate = ori;
+#ifdef CONFIG_64BIT
 		insn[2].reg1i20_format.immediate = lu32id;
 		insn[3].reg2i12_format.immediate = lu52id;
+#endif
 	}
 }
 
-- 
2.47.3
Re: [PATCH V2 04/14] LoongArch: Adjust boot & setup for 32BIT/64BIT
Posted by Yao Zi 1 week, 6 days ago
On Tue, Nov 18, 2025 at 07:27:18PM +0800, Huacai Chen wrote:
> Adjust boot & setup for both 32BIT and 64BIT, including: efi header
> definition, MAX_IO_PICS definition, kernel entry and environment setup
> routines, etc.
> 
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> ---
>  arch/loongarch/include/asm/addrspace.h |  2 +-
>  arch/loongarch/include/asm/irq.h       |  5 ++++
>  arch/loongarch/kernel/efi-header.S     |  4 +++
>  arch/loongarch/kernel/efi.c            |  4 ++-
>  arch/loongarch/kernel/env.c            |  9 ++++--
>  arch/loongarch/kernel/head.S           | 39 +++++++++++---------------
>  arch/loongarch/kernel/relocate.c       |  9 +++++-
>  7 files changed, 45 insertions(+), 27 deletions(-)
> 

...

> diff --git a/arch/loongarch/kernel/env.c b/arch/loongarch/kernel/env.c
> index 23bd5ae2212c..3e8a25eb901b 100644
> --- a/arch/loongarch/kernel/env.c
> +++ b/arch/loongarch/kernel/env.c
> @@ -68,18 +68,23 @@ static int __init fdt_cpu_clk_init(void)
>  
>  	np = of_get_cpu_node(0, NULL);
>  	if (!np)
> -		return -ENODEV;
> +		goto fallback;
>  
>  	clk = of_clk_get(np, 0);
>  	of_node_put(np);
>  
>  	if (IS_ERR(clk))
> -		return -ENODEV;
> +		goto fallback;
>  
>  	cpu_clock_freq = clk_get_rate(clk);
>  	clk_put(clk);
>  
>  	return 0;
> +
> +fallback:
> +	cpu_clock_freq = 200 * 1000 * 1000;

Why pick 200MHz here? And shouldn't the clock being always provided in
devicetree if it's necessary for kernel to function?

Per the schema for LoongArch CPUs (loongarch/cpus.yaml), "clocks"
property is also described as mandantory, thus I don't think such
fallback makes sense.

> +
> +	return -ENODEV;
>  }
>  late_initcall(fdt_cpu_clk_init);

Best regards,
Yao Zi
Re: [PATCH V2 04/14] LoongArch: Adjust boot & setup for 32BIT/64BIT
Posted by Huacai Chen 1 week, 5 days ago
On Wed, Nov 19, 2025 at 1:09 AM Yao Zi <ziyao@disroot.org> wrote:
>
> On Tue, Nov 18, 2025 at 07:27:18PM +0800, Huacai Chen wrote:
> > Adjust boot & setup for both 32BIT and 64BIT, including: efi header
> > definition, MAX_IO_PICS definition, kernel entry and environment setup
> > routines, etc.
> >
> > Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
> > ---
> >  arch/loongarch/include/asm/addrspace.h |  2 +-
> >  arch/loongarch/include/asm/irq.h       |  5 ++++
> >  arch/loongarch/kernel/efi-header.S     |  4 +++
> >  arch/loongarch/kernel/efi.c            |  4 ++-
> >  arch/loongarch/kernel/env.c            |  9 ++++--
> >  arch/loongarch/kernel/head.S           | 39 +++++++++++---------------
> >  arch/loongarch/kernel/relocate.c       |  9 +++++-
> >  7 files changed, 45 insertions(+), 27 deletions(-)
> >
>
> ...
>
> > diff --git a/arch/loongarch/kernel/env.c b/arch/loongarch/kernel/env.c
> > index 23bd5ae2212c..3e8a25eb901b 100644
> > --- a/arch/loongarch/kernel/env.c
> > +++ b/arch/loongarch/kernel/env.c
> > @@ -68,18 +68,23 @@ static int __init fdt_cpu_clk_init(void)
> >
> >       np = of_get_cpu_node(0, NULL);
> >       if (!np)
> > -             return -ENODEV;
> > +             goto fallback;
> >
> >       clk = of_clk_get(np, 0);
> >       of_node_put(np);
> >
> >       if (IS_ERR(clk))
> > -             return -ENODEV;
> > +             goto fallback;
> >
> >       cpu_clock_freq = clk_get_rate(clk);
> >       clk_put(clk);
> >
> >       return 0;
> > +
> > +fallback:
> > +     cpu_clock_freq = 200 * 1000 * 1000;
>
> Why pick 200MHz here? And shouldn't the clock being always provided in
> devicetree if it's necessary for kernel to function?
>
> Per the schema for LoongArch CPUs (loongarch/cpus.yaml), "clocks"
> property is also described as mandantory, thus I don't think such
> fallback makes sense.
Yes, "clocks" is mandatory in theory, but sometimes is missing in
practice, at least in QEMU. On the other hand, if "clocks" really
always exist, then the error checking in fdt_cpu_clk_init() can also
be removed. So the fallback makes sense.

Why pick 200MHz? That is because we assume the constant timer is
100MHz (which is true for all real machines), 200MHz is the minimal
multiple of 100MHz, it is more reasonable than 0MHz.

Huacai
>
> > +
> > +     return -ENODEV;
> >  }
> >  late_initcall(fdt_cpu_clk_init);
>
> Best regards,
> Yao Zi
>