From 6a9a835d6fb6b6c1ea8af430d72e5dc2da07dc69 Mon Sep 17 00:00:00 2001 From: wushenhui Date: Thu, 19 Jun 2025 19:52:58 +0800 Subject: [PATCH] risc-v/mmu: Fix map_region() for incorrect page table setup when vaddr is unaligned When the vaddr parameter passed to map_region() is not aligned to the page directory, it causes incorrect address mapping for later regions. For example, in the sv32 case, `PGPOOL` started at `0x80a00000` with a size of `1024*4096B`, leading to page table errors for the range `0x80c00000~0x80e00000`. This patch fixes the issue by ensuring map_region() correctly handles unaligned vaddr cases. Signed-off-by: wushenhui --- arch/risc-v/src/qemu-rv/qemu_rv_mm_init.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) 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 54c7143587..bc3ab73d51 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 @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -57,7 +58,8 @@ #define PGT_L2_VBASE PGT_L2_PBASE #define PGT_L1_SIZE (1024) /* Enough to map 4 GiB */ -#define PGT_L2_SIZE (3072) /* Enough to map 12 MiB */ +#define PGT_L2_SIZE (4096) /* Enough to map continuous 12 MiB, + * even unaligned */ #define SLAB_COUNT (sizeof(m_l2_pgtable) / RV_MMU_PAGE_SIZE) @@ -191,18 +193,13 @@ static uintptr_t slab_alloc(void) static void map_region(uintptr_t paddr, uintptr_t vaddr, size_t size, uint32_t mmuflags) { + uintptr_t alignaddr; uintptr_t endaddr; uintptr_t pbase; - int npages; - int i; - int j; - /* How many pages */ - - npages = (size + RV_MMU_PAGE_MASK) >> RV_MMU_PAGE_SHIFT; endaddr = vaddr + size; - for (i = 0; i < npages; i += RV_MMU_PAGE_ENTRIES) + while (vaddr < endaddr) { /* See if a mapping exists ? */ @@ -223,7 +220,8 @@ static void map_region(uintptr_t paddr, uintptr_t vaddr, size_t size, /* Then add the mappings */ - for (j = 0; j < RV_MMU_PAGE_ENTRIES && vaddr < endaddr; j++) + alignaddr = ALIGN_UP_MASK(vaddr + 1, RV_MMU_SECTION_ALIGN_MASK); + while (vaddr < alignaddr && vaddr < endaddr) { mmu_ln_setentry(KMM_PBASE_IDX, pbase, paddr, vaddr, mmuflags); paddr += KMM_PAGE_SIZE;