From: Michael Brown Date: Thu, 8 May 2025 13:22:13 +0000 (+0100) Subject: [riscv] Return virtual address offset from enable_paging() X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5b19ddbb3c1cbd6fa4f7c444caa466f2d5c458be;p=thirdparty%2Fipxe.git [riscv] Return virtual address offset from enable_paging() Once paging has been enabled, there is no direct way to determine the virtual address offset without external knowledge. (The paging mode, if needed, can be read directly from the SATP CSR.) Change the return value from enable_paging() to provide the virtual address offset. Signed-off-by: Michael Brown --- diff --git a/src/arch/riscv/prefix/libprefix.S b/src/arch/riscv/prefix/libprefix.S index 989986893..4250b0db0 100644 --- a/src/arch/riscv/prefix/libprefix.S +++ b/src/arch/riscv/prefix/libprefix.S @@ -312,7 +312,7 @@ apply_relocs_done: * * Returns: * - * a0 - Selected paging mode (0=no paging) + * a0 - Virtual address offset * pc - Updated to a virtual address if paging enabled * */ @@ -428,7 +428,7 @@ paging_mode_names: * * Returns: * - * a0 - Selected paging mode (0=no paging) + * a0 - Virtual address offset * pc - Updated to a virtual address if paging enabled * * A 4kB 64-bit page table contains 512 8-byte PTEs. We choose to use @@ -489,15 +489,23 @@ paging_mode_names: enable_paging_64: /* Register usage: * - * a0 - return value (enabled paging level) + * a0 - return value (virtual address offset) * a1 - currently attempted paging level - * a2 - page table base address - * a3 - PTE pointer - * a4 - PTE stride + * a2 - enabled paging level + * a3 - page table base address + * a4 - PTE pointer + * a5 - PTE stride */ progress " paging:" - mv a2, a0 + mv a3, a0 li a1, SATP_MODE_SV57 + + /* Calculate virtual address offset */ + la t0, prefix_virt + LOADN t0, (t0) + la t1, _prefix + sub a0, t1, t0 + enable_paging_64_loop: /* Calculate PTE stride for identity map at this paging level @@ -506,35 +514,35 @@ enable_paging_64_loop: * a1 == 9 == Sv48: PPN[3] LSB is PTE bit 37 => stride := 1 << 37 * a1 == 8 == Sv39: PPN[2] LSB is PTE bit 28 => stride := 1 << 28 * - * and so we calculate stride a4 := ( 1 << ( 9 * a1 - 44 ) ) + * and so we calculate stride a5 := ( 1 << ( 9 * a1 - 44 ) ) */ - slli a4, a1, 3 - add a4, a4, a1 - addi a4, a4, -44 + slli a5, a1, 3 + add a5, a5, a1 + addi a5, a5, -44 li t0, 1 - sll a4, t0, a4 + sll a5, t0, a5 /* Construct PTE[0-255] for identity map */ - mv a3, a2 + mv a4, a3 li t0, ( PTE_COUNT / 2 ) li t1, PTE_LEAF -1: STOREN t1, (a3) - addi a3, a3, PTE_SIZE - add t1, t1, a4 +1: STOREN t1, (a4) + addi a4, a4, PTE_SIZE + add t1, t1, a5 addi t0, t0, -1 bgtz t0, 1b /* Zero PTE[256-511] */ li t0, ( PTE_COUNT / 2 ) -1: STOREN zero, (a3) - addi a3, a3, PTE_SIZE +1: STOREN zero, (a4) + addi a4, a4, PTE_SIZE addi t0, t0, -1 bgtz t0, 1b /* Construct PTE[511] as next level page table pointer */ - srli t0, a2, PTE_PPN_SHIFT + srli t0, a3, PTE_PPN_SHIFT ori t0, t0, PTE_V - STOREN t0, -PTE_SIZE(a3) + STOREN t0, -PTE_SIZE(a4) /* Calculate PTE[x] address for iPXE virtual address map */ la t0, prefix_virt @@ -542,15 +550,15 @@ enable_paging_64_loop: srli t0, t0, VPN1_LSB andi t0, t0, ( PTE_COUNT - 1 ) slli t0, t0, PTE_SIZE_LOG2 - add a3, a2, t0 + add a4, a3, t0 /* Calculate PTE stride for iPXE virtual address map * * PPN[1] LSB is PTE bit 19 in all paging modes, and so the * stride is always ( 1 << 19 ) */ - li a4, 1 - slli a4, a4, PTE_PPN1_LSB + li a5, 1 + slli a5, a5, PTE_PPN1_LSB /* Construct PTE[x-y] for iPXE virtual address map */ la t0, _prefix @@ -558,37 +566,32 @@ enable_paging_64_loop: ori t0, t0, PTE_LEAF la t1, _ebss srli t1, t1, PTE_PPN_SHIFT -1: STOREN t0, (a3) - addi a3, a3, PTE_SIZE - add t0, t0, a4 +1: STOREN t0, (a4) + addi a4, a4, PTE_SIZE + add t0, t0, a5 ble t0, t1, 1b /* Attempt to enable paging, and read back active paging level */ slli t0, a1, SATP_MODE_SHIFT - srli t1, a2, PAGE_SHIFT + srli t1, a3, PAGE_SHIFT or t0, t0, t1 csrrw zero, satp, t0 sfence.vma - csrrw a0, satp, t0 - srli a0, a0, SATP_MODE_SHIFT + csrrw a2, satp, t0 + srli a2, a2, SATP_MODE_SHIFT /* Loop until we successfully enable paging, or run out of levels */ - beq a0, a1, 1f + beq a2, a1, 1f addi a1, a1, -1 li t0, SATP_MODE_SV39 bge a1, t0, enable_paging_64_loop - j enable_paging_64_done + mv a0, zero 1: /* Adjust return address to a virtual address */ - la t0, _prefix - sub ra, ra, t0 - la t0, prefix_virt - LOADN t0, (t0) - add ra, ra, t0 + sub ra, ra, a0 -enable_paging_64_done: /* Return, with or without paging enabled */ - paging_mode_name a0 + paging_mode_name a2 ret .size enable_paging_64, . - enable_paging_64 @@ -611,7 +614,7 @@ enable_paging_64_done: * * Returns: * - * a0 - Selected paging mode (0=no paging) + * a0 - Virtual address offset * pc - Updated to a virtual address if paging enabled * * A 4kB 32-bit page table contains 1024 4-byte PTEs. We choose to @@ -632,8 +635,8 @@ enable_paging_64_done: enable_paging_32: /* Register usage: * - * a0 - return value (enabled paging level) - * a1 - virtual address offset + * a0 - return value (virtual address offset) + * a1 - enabled paging level * a2 - page table base address * a3 - PTE pointer * a4 - saved content of temporarily modified PTE @@ -645,12 +648,12 @@ enable_paging_32: la t0, prefix_virt LOADN t0, (t0) la t1, _prefix - sub a1, t1, t0 + sub a0, t1, t0 /* Construct PTEs for circular map */ mv a3, a2 li t0, PTE_COUNT - mv t1, a1 + mv t1, a0 ori t1, t1, ( PTE_LEAF << PTE_PPN_SHIFT ) li t2, ( 1 << ( PTE_PPN1_LSB + PTE_PPN_SHIFT ) ) 1: srli t3, t1, PTE_PPN_SHIFT @@ -671,11 +674,11 @@ enable_paging_32: STOREN t0, (a3) /* Adjust PTE pointer to a virtual address */ - sub a3, a3, a1 + sub a3, a3, a0 /* Attempt to enable paging, and read back active paging level */ la t0, 1f - sub t0, t0, a1 + sub t0, t0, a0 li t1, ( SATP_MODE_SV32 << SATP_MODE_SHIFT ) srli t2, a2, PAGE_SHIFT or t1, t1, t2 @@ -684,22 +687,25 @@ enable_paging_32: enable_paging_32_xstart: csrrw zero, satp, t1 sfence.vma - csrrw a0, satp, t1 - beqz a0, enable_paging_32_done + csrrw a1, satp, t1 + beqz a1, 2f jr t0 1: /* Restore temporarily modified PTE */ STOREN a4, (a3) sfence.vma /* End of transition code */ .equ enable_paging_32_xlen, . - enable_paging_32_xstart - li a0, 1 +2: srli a1, a1, SATP_MODE_SHIFT - /* Adjust return address */ - sub ra, ra, a1 + /* Clear virtual address offset if paging is not enabled */ + bnez a1, 1f + mv a0, zero +1: + /* Adjust return address to a virtual address */ + sub ra, ra, a0 -enable_paging_32_done: /* Return, with or without paging enabled */ - paging_mode_name a0 + paging_mode_name a1 ret .size enable_paging_32, . - enable_paging_32