This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 1653db7ddcc riscv: Fix page table traversal for SV39
1653db7ddcc is described below

commit 1653db7ddcc493fb625c168b020fe3d925787abc
Author: liang.huang <[email protected]>
AuthorDate: Tue Feb 3 21:57:01 2026 -0800

    riscv: Fix page table traversal for SV39
    
    With CONFIG_PAGING enabled and the RISC-V SV39 MMU active, the page fault
    handler incorrectly tracked page table levels: `ptprev` pointed to the L1
    page table while `ptlevel` indicated L2. This inconsistency caused faulty
    virtual address resolution.
    
    This commit fixes the traversal logic to ensure consistent level tracking
    across all three page table levels (L1–L3), enabling reliable page fault
    handling and on-demand paging.
    
    Additional changes:
    - Set PGT_L3_SIZE to 2048 to enable mapping up to 8MB of address space.
    - Update knsh_paging config to avoid crashes caused by excessive memory
      alignment requirements.
    - Add knsh64_paging config to verify this commit works as expected.
    
    Signed-off-by: liang.huang <[email protected]>
---
 arch/risc-v/src/common/riscv_exception.c           | 32 ++++++++++++----------
 arch/risc-v/src/qemu-rv/qemu_rv_mm_init.c          |  2 +-
 .../{knsh_paging => knsh64_paging}/defconfig       |  4 +--
 .../qemu-rv/rv-virt/configs/knsh_paging/defconfig  |  1 -
 4 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/arch/risc-v/src/common/riscv_exception.c 
b/arch/risc-v/src/common/riscv_exception.c
index 05f433f4d03..ee798506767 100644
--- a/arch/risc-v/src/common/riscv_exception.c
+++ b/arch/risc-v/src/common/riscv_exception.c
@@ -207,26 +207,30 @@ int riscv_fillpage(int mcause, void *regs, void *args)
     }
 
   satp    = READ_CSR(CSR_SATP);
-  ptprev  = riscv_pgvaddr(mmu_satp_to_paddr(satp));
-  ptlevel = ARCH_SPGTS;
-  paddr   = mmu_pte_to_paddr(mmu_ln_getentry(ptlevel, ptprev, vaddr));
-  if (!paddr)
-    {
-      /* Nothing yet, allocate one page for final level page table */
+  paddr   = mmu_satp_to_paddr(satp);
 
-      paddr = mm_pgalloc(1);
+  for (ptlevel = 1; ptlevel <= ARCH_SPGTS; ptlevel++)
+    {
+      ptprev  = riscv_pgvaddr(paddr);
+      paddr   = mmu_pte_to_paddr(mmu_ln_getentry(ptlevel, ptprev, vaddr));
       if (!paddr)
         {
-          return -ENOMEM;
-        }
+          /* Nothing yet, allocate one page for next level page table */
+
+          paddr = mm_pgalloc(1);
+          if (!paddr)
+            {
+              return -ENOMEM;
+            }
 
-      /* Map the page table to the prior level */
+          /* Map the page table to the prior level */
 
-      mmu_ln_setentry(ptlevel, ptprev, paddr, vaddr, MMU_UPGT_FLAGS);
+          mmu_ln_setentry(ptlevel, ptprev, paddr, vaddr, MMU_UPGT_FLAGS);
 
-      /* This is then used to map the final level */
+          /* This is then used to map the next level */
 
-      riscv_pgwipe(paddr);
+          riscv_pgwipe(paddr);
+        }
     }
 
   ptlast = riscv_pgvaddr(paddr);
@@ -242,7 +246,7 @@ int riscv_fillpage(int mcause, void *regs, void *args)
 
   /* Then map the virtual address to the physical address */
 
-  mmu_ln_setentry(ptlevel + 1, ptlast, paddr, vaddr, mmuflags);
+  mmu_ln_setentry(ARCH_PGT_MAX_LEVELS, ptlast, paddr, vaddr, mmuflags);
 
   return 0;
 }
diff --git a/arch/risc-v/src/qemu-rv/qemu_rv_mm_init.c 
b/arch/risc-v/src/qemu-rv/qemu_rv_mm_init.c
index bc3ab73d512..e553b40d0fa 100644
--- a/arch/risc-v/src/qemu-rv/qemu_rv_mm_init.c
+++ b/arch/risc-v/src/qemu-rv/qemu_rv_mm_init.c
@@ -82,7 +82,7 @@
 
 #define PGT_L1_SIZE     (512)  /* Enough to map 512 GiB */
 #define PGT_L2_SIZE     (512)  /* Enough to map 1 GiB */
-#define PGT_L3_SIZE     (1024) /* Enough to map 4 MiB (2MiB x 2) */
+#define PGT_L3_SIZE     (2048) /* Enough to map 8 MiB (2MiB x 4) */
 
 #define SLAB_COUNT      (sizeof(m_l3_pgtable) / RV_MMU_PAGE_SIZE)
 
diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/knsh_paging/defconfig 
b/boards/risc-v/qemu-rv/rv-virt/configs/knsh64_paging/defconfig
similarity index 97%
copy from boards/risc-v/qemu-rv/rv-virt/configs/knsh_paging/defconfig
copy to boards/risc-v/qemu-rv/rv-virt/configs/knsh64_paging/defconfig
index 4d1c9bf9040..1fca77a6dc4 100644
--- a/boards/risc-v/qemu-rv/rv-virt/configs/knsh_paging/defconfig
+++ b/boards/risc-v/qemu-rv/rv-virt/configs/knsh64_paging/defconfig
@@ -21,7 +21,7 @@ CONFIG_ARCH_ADDRENV=y
 CONFIG_ARCH_BOARD="rv-virt"
 CONFIG_ARCH_BOARD_QEMU_RV_VIRT=y
 CONFIG_ARCH_CHIP="qemu-rv"
-CONFIG_ARCH_CHIP_QEMU_RV32=y
+CONFIG_ARCH_CHIP_QEMU_RV64=y
 CONFIG_ARCH_CHIP_QEMU_RV=y
 CONFIG_ARCH_CHIP_QEMU_RV_ISA_A=y
 CONFIG_ARCH_CHIP_QEMU_RV_ISA_C=y
@@ -45,6 +45,7 @@ CONFIG_ARCH_USE_MMU=y
 CONFIG_ARCH_USE_MPU=y
 CONFIG_ARCH_USE_S_MODE=y
 CONFIG_BINFMT_ELF_EXECUTABLE=y
+CONFIG_BOARD_INITTHREAD_STACKSIZE=3072
 CONFIG_BOARD_LATE_INITIALIZE=y
 CONFIG_BOARD_LOOPSPERMSEC=6366
 CONFIG_BUILD_KERNEL=y
@@ -94,5 +95,4 @@ CONFIG_SYSTEM_NSH=y
 CONFIG_SYSTEM_NSH_PROGNAME="init"
 CONFIG_TESTING_GETPRIME=y
 CONFIG_TESTING_OSTEST=y
-CONFIG_TLS_LOG2_MAXSTACK=20
 CONFIG_USEC_PER_TICK=1000
diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/knsh_paging/defconfig 
b/boards/risc-v/qemu-rv/rv-virt/configs/knsh_paging/defconfig
index 4d1c9bf9040..bbe83b1a908 100644
--- a/boards/risc-v/qemu-rv/rv-virt/configs/knsh_paging/defconfig
+++ b/boards/risc-v/qemu-rv/rv-virt/configs/knsh_paging/defconfig
@@ -94,5 +94,4 @@ CONFIG_SYSTEM_NSH=y
 CONFIG_SYSTEM_NSH_PROGNAME="init"
 CONFIG_TESTING_GETPRIME=y
 CONFIG_TESTING_OSTEST=y
-CONFIG_TLS_LOG2_MAXSTACK=20
 CONFIG_USEC_PER_TICK=1000

Reply via email to