]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[riscv] Construct invariant portions of page table outside the loop
authorMichael Brown <mcb30@ipxe.org>
Fri, 4 Jul 2025 13:37:31 +0000 (14:37 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 4 Jul 2025 15:10:51 +0000 (16:10 +0100)
The page table entries for the identity map vary according to the
paging level in use, and so must be constructed within the loop used
to detect the maximum supported paging level.  Other page table
entries are invariant between paging levels, and so may be constructed
just once before entering the loop.

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

index cf62338b5e20151a722a0c439e15fd467f09a2b9..0482ffe3142256c5b3bd912250fbfa802338d2ff 100644 (file)
@@ -865,6 +865,19 @@ enable_paging_64:
        la      t1, _prefix
        sub     tp, t1, t0
 
+       /* Zero PTE[0-511] */
+       li      t0, PTE_COUNT
+       mv      a3, a0
+1:     STOREN  zero, (a3)
+       addi    a3, a3, PTE_SIZE
+       addi    t0, t0, -1
+       bgtz    t0, 1b
+
+       /* Construct PTE[511] as next level page table pointer */
+       srli    t0, a0, PTE_PPN_SHIFT
+       ori     t0, t0, PTE_V
+       STOREN  t0, -PTE_SIZE(a3)
+
        /* Construct base page table entry for address zero */
        li      t0, PTE_LEAF
        STOREN  t0, (a0)
@@ -889,54 +902,6 @@ enable_paging_64:
        STOREN  t0, (a3)
 1:     mv      a0, a3
 
-       /* Find highest supported paging level */
-       li      a1, SATP_MODE_SV57
-enable_paging_64_loop:
-
-       /* Calculate PTE stride for identity map at this paging level
-        *
-        * a1 == 10 == Sv57: PPN[4] LSB is PTE bit 46  =>  stride := 1 << 46
-        * 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 ) )
-        */
-       slli    a4, a1, 3
-       add     a4, a4, a1
-       addi    a4, a4, -44
-       li      t0, 1
-       sll     a4, t0, a4
-
-       /* Calculate size of accessible physical address space
-        *
-        * The identity map comprises only the lower half of the PTEs,
-        * since virtual addresses for the higher half must have all
-        * high bits set, and so cannot form part of an identity map.
-        */
-       slli    a5, a4, ( PTE_PPN_SHIFT + ( PTE_COUNT_LOG2 - 1 ) )
-
-       /* Construct PTE[0-255] for identity map */
-       mv      a3, a0
-       li      t0, ( PTE_COUNT / 2 )
-       LOADN   t1, (a0)
-1:     STOREN  t1, (a3)
-       addi    a3, a3, PTE_SIZE
-       add     t1, t1, a4
-       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
-       addi    t0, t0, -1
-       bgtz    t0, 1b
-
-       /* Construct PTE[511] as next level page table pointer */
-       srli    t0, a0, PTE_PPN_SHIFT
-       ori     t0, t0, PTE_V
-       STOREN  t0, -PTE_SIZE(a3)
-
        /* Calculate PTE[x] address for iPXE virtual address map */
        LOADN   t0, prefix_link
        srli    t0, t0, VPN1_LSB
@@ -972,6 +937,42 @@ enable_paging_64_loop:
        add     t0, t0, a4
        ble     t0, t2, 1b
 
+       /* Find highest supported paging level */
+       li      a1, SATP_MODE_SV57
+enable_paging_64_loop:
+
+       /* Calculate PTE stride for identity map at this paging level
+        *
+        * a1 == 10 == Sv57: PPN[4] LSB is PTE bit 46  =>  stride := 1 << 46
+        * 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 ) )
+        */
+       slli    a4, a1, 3
+       add     a4, a4, a1
+       addi    a4, a4, -44
+       li      t0, 1
+       sll     a4, t0, a4
+
+       /* Calculate size of accessible physical address space
+        *
+        * The identity map comprises only the lower half of the PTEs,
+        * since virtual addresses for the higher half must have all
+        * high bits set, and so cannot form part of an identity map.
+        */
+       slli    a5, a4, ( PTE_PPN_SHIFT + ( PTE_COUNT_LOG2 - 1 ) )
+
+       /* Construct PTE[0-255] for identity map at this paging level */
+       mv      a3, a0
+       li      t0, ( PTE_COUNT / 2 )
+       LOADN   t1, (a0)
+1:     STOREN  t1, (a3)
+       addi    a3, a3, PTE_SIZE
+       add     t1, t1, a4
+       addi    t0, t0, -1
+       bgtz    t0, 1b
+
        /* Attempt to enable paging, and read back active paging level */
        slli    t0, a1, SATP_MODE_SHIFT
        srli    t1, a0, PAGE_SHIFT