[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 <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-05-08 14:22:13 +01:00
parent 5e518c744e
commit 5b19ddbb3c

View File

@@ -312,7 +312,7 @@ apply_relocs_done:
* *
* Returns: * Returns:
* *
* a0 - Selected paging mode (0=no paging) * a0 - Virtual address offset
* pc - Updated to a virtual address if paging enabled * pc - Updated to a virtual address if paging enabled
* *
*/ */
@@ -428,7 +428,7 @@ paging_mode_names:
* *
* Returns: * Returns:
* *
* a0 - Selected paging mode (0=no paging) * a0 - Virtual address offset
* pc - Updated to a virtual address if paging enabled * pc - Updated to a virtual address if paging enabled
* *
* A 4kB 64-bit page table contains 512 8-byte PTEs. We choose to use * 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: enable_paging_64:
/* Register usage: /* Register usage:
* *
* a0 - return value (enabled paging level) * a0 - return value (virtual address offset)
* a1 - currently attempted paging level * a1 - currently attempted paging level
* a2 - page table base address * a2 - enabled paging level
* a3 - PTE pointer * a3 - page table base address
* a4 - PTE stride * a4 - PTE pointer
* a5 - PTE stride
*/ */
progress " paging:" progress " paging:"
mv a2, a0 mv a3, a0
li a1, SATP_MODE_SV57 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: enable_paging_64_loop:
/* Calculate PTE stride for identity map at this paging level /* 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 == 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 * 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 slli a5, a1, 3
add a4, a4, a1 add a5, a5, a1
addi a4, a4, -44 addi a5, a5, -44
li t0, 1 li t0, 1
sll a4, t0, a4 sll a5, t0, a5
/* Construct PTE[0-255] for identity map */ /* Construct PTE[0-255] for identity map */
mv a3, a2 mv a4, a3
li t0, ( PTE_COUNT / 2 ) li t0, ( PTE_COUNT / 2 )
li t1, PTE_LEAF li t1, PTE_LEAF
1: STOREN t1, (a3) 1: STOREN t1, (a4)
addi a3, a3, PTE_SIZE addi a4, a4, PTE_SIZE
add t1, t1, a4 add t1, t1, a5
addi t0, t0, -1 addi t0, t0, -1
bgtz t0, 1b bgtz t0, 1b
/* Zero PTE[256-511] */ /* Zero PTE[256-511] */
li t0, ( PTE_COUNT / 2 ) li t0, ( PTE_COUNT / 2 )
1: STOREN zero, (a3) 1: STOREN zero, (a4)
addi a3, a3, PTE_SIZE addi a4, a4, PTE_SIZE
addi t0, t0, -1 addi t0, t0, -1
bgtz t0, 1b bgtz t0, 1b
/* Construct PTE[511] as next level page table pointer */ /* 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 ori t0, t0, PTE_V
STOREN t0, -PTE_SIZE(a3) STOREN t0, -PTE_SIZE(a4)
/* Calculate PTE[x] address for iPXE virtual address map */ /* Calculate PTE[x] address for iPXE virtual address map */
la t0, prefix_virt la t0, prefix_virt
@@ -542,15 +550,15 @@ enable_paging_64_loop:
srli t0, t0, VPN1_LSB srli t0, t0, VPN1_LSB
andi t0, t0, ( PTE_COUNT - 1 ) andi t0, t0, ( PTE_COUNT - 1 )
slli t0, t0, PTE_SIZE_LOG2 slli t0, t0, PTE_SIZE_LOG2
add a3, a2, t0 add a4, a3, t0
/* Calculate PTE stride for iPXE virtual address map /* Calculate PTE stride for iPXE virtual address map
* *
* PPN[1] LSB is PTE bit 19 in all paging modes, and so the * PPN[1] LSB is PTE bit 19 in all paging modes, and so the
* stride is always ( 1 << 19 ) * stride is always ( 1 << 19 )
*/ */
li a4, 1 li a5, 1
slli a4, a4, PTE_PPN1_LSB slli a5, a5, PTE_PPN1_LSB
/* Construct PTE[x-y] for iPXE virtual address map */ /* Construct PTE[x-y] for iPXE virtual address map */
la t0, _prefix la t0, _prefix
@@ -558,37 +566,32 @@ enable_paging_64_loop:
ori t0, t0, PTE_LEAF ori t0, t0, PTE_LEAF
la t1, _ebss la t1, _ebss
srli t1, t1, PTE_PPN_SHIFT srli t1, t1, PTE_PPN_SHIFT
1: STOREN t0, (a3) 1: STOREN t0, (a4)
addi a3, a3, PTE_SIZE addi a4, a4, PTE_SIZE
add t0, t0, a4 add t0, t0, a5
ble t0, t1, 1b ble t0, t1, 1b
/* Attempt to enable paging, and read back active paging level */ /* Attempt to enable paging, and read back active paging level */
slli t0, a1, SATP_MODE_SHIFT slli t0, a1, SATP_MODE_SHIFT
srli t1, a2, PAGE_SHIFT srli t1, a3, PAGE_SHIFT
or t0, t0, t1 or t0, t0, t1
csrrw zero, satp, t0 csrrw zero, satp, t0
sfence.vma sfence.vma
csrrw a0, satp, t0 csrrw a2, satp, t0
srli a0, a0, SATP_MODE_SHIFT srli a2, a2, SATP_MODE_SHIFT
/* Loop until we successfully enable paging, or run out of levels */ /* Loop until we successfully enable paging, or run out of levels */
beq a0, a1, 1f beq a2, a1, 1f
addi a1, a1, -1 addi a1, a1, -1
li t0, SATP_MODE_SV39 li t0, SATP_MODE_SV39
bge a1, t0, enable_paging_64_loop bge a1, t0, enable_paging_64_loop
j enable_paging_64_done mv a0, zero
1: 1:
/* Adjust return address to a virtual address */ /* Adjust return address to a virtual address */
la t0, _prefix sub ra, ra, a0
sub ra, ra, t0
la t0, prefix_virt
LOADN t0, (t0)
add ra, ra, t0
enable_paging_64_done:
/* Return, with or without paging enabled */ /* Return, with or without paging enabled */
paging_mode_name a0 paging_mode_name a2
ret ret
.size enable_paging_64, . - enable_paging_64 .size enable_paging_64, . - enable_paging_64
@@ -611,7 +614,7 @@ enable_paging_64_done:
* *
* Returns: * Returns:
* *
* a0 - Selected paging mode (0=no paging) * a0 - Virtual address offset
* pc - Updated to a virtual address if paging enabled * pc - Updated to a virtual address if paging enabled
* *
* A 4kB 32-bit page table contains 1024 4-byte PTEs. We choose to * 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: enable_paging_32:
/* Register usage: /* Register usage:
* *
* a0 - return value (enabled paging level) * a0 - return value (virtual address offset)
* a1 - virtual address offset * a1 - enabled paging level
* a2 - page table base address * a2 - page table base address
* a3 - PTE pointer * a3 - PTE pointer
* a4 - saved content of temporarily modified PTE * a4 - saved content of temporarily modified PTE
@@ -645,12 +648,12 @@ enable_paging_32:
la t0, prefix_virt la t0, prefix_virt
LOADN t0, (t0) LOADN t0, (t0)
la t1, _prefix la t1, _prefix
sub a1, t1, t0 sub a0, t1, t0
/* Construct PTEs for circular map */ /* Construct PTEs for circular map */
mv a3, a2 mv a3, a2
li t0, PTE_COUNT li t0, PTE_COUNT
mv t1, a1 mv t1, a0
ori t1, t1, ( PTE_LEAF << PTE_PPN_SHIFT ) ori t1, t1, ( PTE_LEAF << PTE_PPN_SHIFT )
li t2, ( 1 << ( PTE_PPN1_LSB + PTE_PPN_SHIFT ) ) li t2, ( 1 << ( PTE_PPN1_LSB + PTE_PPN_SHIFT ) )
1: srli t3, t1, PTE_PPN_SHIFT 1: srli t3, t1, PTE_PPN_SHIFT
@@ -671,11 +674,11 @@ enable_paging_32:
STOREN t0, (a3) STOREN t0, (a3)
/* Adjust PTE pointer to a virtual address */ /* 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 */ /* Attempt to enable paging, and read back active paging level */
la t0, 1f la t0, 1f
sub t0, t0, a1 sub t0, t0, a0
li t1, ( SATP_MODE_SV32 << SATP_MODE_SHIFT ) li t1, ( SATP_MODE_SV32 << SATP_MODE_SHIFT )
srli t2, a2, PAGE_SHIFT srli t2, a2, PAGE_SHIFT
or t1, t1, t2 or t1, t1, t2
@@ -684,22 +687,25 @@ enable_paging_32:
enable_paging_32_xstart: enable_paging_32_xstart:
csrrw zero, satp, t1 csrrw zero, satp, t1
sfence.vma sfence.vma
csrrw a0, satp, t1 csrrw a1, satp, t1
beqz a0, enable_paging_32_done beqz a1, 2f
jr t0 jr t0
1: /* Restore temporarily modified PTE */ 1: /* Restore temporarily modified PTE */
STOREN a4, (a3) STOREN a4, (a3)
sfence.vma sfence.vma
/* End of transition code */ /* End of transition code */
.equ enable_paging_32_xlen, . - enable_paging_32_xstart .equ enable_paging_32_xlen, . - enable_paging_32_xstart
li a0, 1 2: srli a1, a1, SATP_MODE_SHIFT
/* Adjust return address */ /* Clear virtual address offset if paging is not enabled */
sub ra, ra, a1 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 */ /* Return, with or without paging enabled */
paging_mode_name a0 paging_mode_name a1
ret ret
.size enable_paging_32, . - enable_paging_32 .size enable_paging_32, . - enable_paging_32