LoongArch: Jump to the link address before enable PG
authorHuacai Chen <chenhuacai@loongson.cn>
Thu, 11 Aug 2022 12:52:12 +0000 (20:52 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Fri, 12 Aug 2022 05:10:11 +0000 (13:10 +0800)
The kernel entry points of both boot CPU (i.e., kernel_entry) and non-
boot CPUs (i.e., smpboot_entry) may be physical address from BootLoader
(in DA mode or identity-mapping PG mode). So we should jump to the link
address before PG enabled (because DA is disabled at the same time) and
just after DMW configured.

Specifically: With some older firmwares, non-boot CPUs started with PG
enabled, but this need firmware cooperation in the form of a temporary
page table, which is deemed unnecessary. OTOH, latest firmware versions
configure the non-boot CPUs to start in DA mode, so kernel-side changes
are needed.

Reviewed-by: WANG Xuerui <git@xen0n.name>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/kernel/head.S

index 7062cdf..c60eb66 100644 (file)
@@ -21,6 +21,12 @@ SYM_CODE_START(kernel_entry)                 # kernel entry point
        csrwr           t0, LOONGARCH_CSR_DMWIN0
        li.d            t0, CSR_DMW1_INIT       # CA, PLV0, 0x9000 xxxx xxxx xxxx
        csrwr           t0, LOONGARCH_CSR_DMWIN1
+
+       /* We might not get launched at the address the kernel is linked to,
+          so we jump there.  */
+       la.abs          t0, 0f
+       jr              t0
+0:
        /* Enable PG */
        li.w            t0, 0xb0                # PLV=0, IE=0, PG=1
        csrwr           t0, LOONGARCH_CSR_CRMD
@@ -29,11 +35,6 @@ SYM_CODE_START(kernel_entry)                 # kernel entry point
        li.w            t0, 0x00                # FPE=0, SXE=0, ASXE=0, BTE=0
        csrwr           t0, LOONGARCH_CSR_EUEN
 
-       /* We might not get launched at the address the kernel is linked to,
-          so we jump there.  */
-       la.abs          t0, 0f
-       jr              t0
-0:
        la              t0, __bss_start         # clear .bss
        st.d            zero, t0, 0
        la              t1, __bss_stop - LONGSIZE
@@ -74,6 +75,11 @@ SYM_CODE_START(smpboot_entry)
        csrwr           t0, LOONGARCH_CSR_DMWIN0
        li.d            t0, CSR_DMW1_INIT       # CA, PLV0
        csrwr           t0, LOONGARCH_CSR_DMWIN1
+
+       la.abs          t0, 0f
+       jr              t0
+0:
+       /* 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
@@ -85,9 +91,6 @@ SYM_CODE_START(smpboot_entry)
        ld.d            sp, t0, CPU_BOOT_STACK
        ld.d            tp, t0, CPU_BOOT_TINFO
 
-       la.abs          t0, 0f
-       jr              t0
-0:
        bl              start_secondary
 SYM_CODE_END(smpboot_entry)