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 55cd85c9aba arch/arm64: Map a region that does not start at a page
table boundary.
55cd85c9aba is described below
commit 55cd85c9aba7ec073250ccebddfb947290e8b3af
Author: Marco Casaroli <[email protected]>
AuthorDate: Fri Oct 9 00:17:03 2026 +0200
arch/arm64: Map a region that does not start at a page table boundary.
create_region() mapped up to ENTRIES_PER_PGT pages through one final
level table, from whatever address the region started at. The text
region starts one page after the reserved area, so a region that
crossed the end of the table wrapped around and mapped its last pages
over the first entries of the same table. In a program with more than
about 2 MB of text, the reserved area became read-only and the kernel
faulted in umm_initialize().
Walk the region one final level table at a time.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <[email protected]>
---
arch/arm64/src/common/arm64_addrenv_mmu.c | 40 ++++++++++++++++++++-----------
1 file changed, 26 insertions(+), 14 deletions(-)
diff --git a/arch/arm64/src/common/arm64_addrenv_mmu.c
b/arch/arm64/src/common/arm64_addrenv_mmu.c
index 686ebb04ede..c4f4e3c79d0 100644
--- a/arch/arm64/src/common/arm64_addrenv_mmu.c
+++ b/arch/arm64/src/common/arm64_addrenv_mmu.c
@@ -267,14 +267,13 @@ static int create_region(arch_addrenv_t *addrenv,
uintptr_t vaddr,
uintptr_t ptlast;
uintptr_t ptprev;
uintptr_t paddr;
+ uintptr_t vend;
+ uintptr_t tend;
uint32_t ptlevel;
int npages;
- int nmapped;
- int i;
- int j;
- nmapped = 0;
npages = MM_NPAGES(size);
+ vend = vaddr + ((uintptr_t)npages << MM_PGSHIFT);
ptlevel = MMU_PGT_LEVEL_MAX - 1;
ptprev = arm64_pgvaddr(addrenv->spgtables[ptlevel]);
@@ -284,8 +283,19 @@ static int create_region(arch_addrenv_t *addrenv,
uintptr_t vaddr,
/* Begin allocating memory for the page tables */
- for (i = 0; i < npages; i += ENTRIES_PER_PGT)
+ while (vaddr < vend)
{
+ /* One final level table maps ENTRIES_PER_PGT pages. The region need
+ * not start at the beginning of a table, so stop at the end of this
+ * one and look up the next.
+ */
+
+ tend = (vaddr | ((ENTRIES_PER_PGT << MM_PGSHIFT) - 1)) + 1;
+ if (tend > vend || tend == 0)
+ {
+ tend = vend;
+ }
+
/* Get the current final level entry corresponding to this vaddr */
paddr = mmu_pte_to_paddr(mmu_ln_getentry(ptlevel, ptprev, vaddr));
@@ -313,13 +323,7 @@ static int create_region(arch_addrenv_t *addrenv,
uintptr_t vaddr,
/* Then allocate memory for the region data */
- for (j = 0;
-#ifdef CONFIG_PAGING
- j < 1;
-#else
- j < ENTRIES_PER_PGT && nmapped < size;
-#endif
- j++)
+ do
{
paddr = mm_pgalloc(1);
if (!paddr)
@@ -334,9 +338,17 @@ static int create_region(arch_addrenv_t *addrenv,
uintptr_t vaddr,
/* Then map the virtual address to the physical address */
mmu_ln_setentry(ptlevel + 1, ptlast, paddr, vaddr, mmuflags);
- nmapped += MM_PGSIZE;
- vaddr += MM_PGSIZE;
+ vaddr += MM_PGSIZE;
}
+#ifdef CONFIG_PAGING
+ while (0);
+
+ /* Only the first page of each table; the rest come on demand */
+
+ vaddr = tend;
+#else
+ while (vaddr < tend);
+#endif
}
/* Synchronize data and instruction pipelines */