]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[riscv] Zero SATP after any failed attempt to enable paging
authorMichael Brown <mcb30@ipxe.org>
Mon, 2 Jun 2025 07:08:02 +0000 (08:08 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 2 Jun 2025 07:09:15 +0000 (08:09 +0100)
The RISC-V specification states that "if SATP is written with an
unsupported mode, the entire write has no effect; no fields in SATP
are modified".  We currently rely on this specified behaviour when
calculating the early UART base address: if SATP has a non-zero value
then we assume that paging must be enabled.

The XuanTie C910 CPU (as used in the Lichee Pi 4A) does not conform to
this specified behaviour.  Writing SATP with an unsupported mode will
leave SATP.MODE as zero (i.e. bare physical addressing) but the write
to SATP.PPN will still take effect, leaving SATP with an illegal
non-zero value.

Work around this misbehaviour by explicitly writing zero to SATP if we
detect that the mode change has not taken effect (e.g. because the CPU
does not support the requested paging mode).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/riscv/prefix/libprefix.S

index 8fa9a67812b9a6ca5295115abdeb852c3fcbaae8..583f2711703a3cc02b56eb16311b941c3f2ebfb2 100644 (file)
@@ -896,13 +896,14 @@ enable_paging_64_loop:
        slli    t0, a1, SATP_MODE_SHIFT
        srli    t1, a0, PAGE_SHIFT
        or      t0, t0, t1
-       csrrw   zero, satp, t0
+       csrw    satp, t0
        sfence.vma
-       csrrw   a2, satp, t0
+       csrr    a2, satp
        srli    a2, a2, SATP_MODE_SHIFT
 
        /* Loop until we successfully enable paging, or run out of levels */
        beq     a2, a1, 1f
+       csrw    satp, zero
        addi    a1, a1, -1
        li      t0, SATP_MODE_SV39
        bge     a1, t0, enable_paging_64_loop
@@ -1074,9 +1075,9 @@ enable_paging_32:
        .balign enable_paging_32_xalign
        /* Start of transition code */
 enable_paging_32_xstart:
-       csrrw   zero, satp, t1
+       csrw    satp, t1
        sfence.vma
-       csrrw   a1, satp, t1
+       csrr    a1, satp
        beqz    a1, 2f
        jr      t0
 1:     /* Restore temporarily modified PTE */
@@ -1086,8 +1087,9 @@ enable_paging_32_xstart:
        .equ    enable_paging_32_xlen, . - enable_paging_32_xstart
 2:     srli    a1, a1, SATP_MODE_SHIFT
 
-       /* Clear virtual address offset if paging is not enabled */
+       /* Zero SATP and virtual address offset if paging is not enabled */
        bnez    a1, 1f
+       csrw    satp, zero
        mv      tp, zero
 1:
        /* Adjust return address to a virtual address */