This is an automated email from the ASF dual-hosted git repository. jerpelea pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit b07c19775a631bd3d38c52430092f306baff779c Author: Marco Casaroli <[email protected]> AuthorDate: Sun Nov 1 11:11:25 2026 +0100 arch/x86_64: Map a region into the page tables that its addresses use. x86_64_create_region() fills the page tables (PT) of a region. It starts each PT at the index of the address in the page directory (PD) instead of its index in the PT, so the inner loop always maps up to 512 pages into the same PT. When the region crosses a 2 MiB boundary, the pages after it go into the first entries of that PT again: they replace the mappings of the lower addresses there (text and data of the program), and the addresses after the boundary stay unmapped. The outer loop also counts its steps of 512 pages from 0, so it ends too early for a region that does not start a PT. For example a heap of 2 MiB at 0x8000f0000 (qemu-intel64:knsh_romfs, CONFIG_ELF_STACKSIZE 2 MiB): mm_initialize() faults on the last word of the heap when the program starts. Start each PT at the index of the address in it, and loop until the whole size is mapped. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- arch/x86_64/src/common/x86_64_addrenv.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/arch/x86_64/src/common/x86_64_addrenv.c b/arch/x86_64/src/common/x86_64_addrenv.c index 51a442192d2..63f6d9b76e0 100644 --- a/arch/x86_64/src/common/x86_64_addrenv.c +++ b/arch/x86_64/src/common/x86_64_addrenv.c @@ -237,8 +237,6 @@ static int x86_64_create_region(arch_addrenv_t *addrenv, uintptr_t vaddr, uint32_t ptlevel; int npages; int nmapped; - int i; - int j; /* Only one entry in PML4 supported now */ @@ -261,9 +259,11 @@ static int x86_64_create_region(arch_addrenv_t *addrenv, uintptr_t vaddr, map_spgtables(addrenv, vaddr); - /* Begin allocating memory for the page tables */ + /* Begin allocating memory for the page tables. Each PT is filled from + * the index of vaddr in it. + */ - for (i = 0; i < npages; i += X86_MMU_ENTRIES_PER_PGT) + while (nmapped < size) { /* Get the current final level entry (PT) corresponding to this vaddr */ @@ -289,11 +289,11 @@ static int x86_64_create_region(arch_addrenv_t *addrenv, uintptr_t vaddr, ptlast = x86_64_pgvaddr(paddr); - /* Then allocate memory for the region data */ + /* Then allocate memory for the region data, up to the end of this + * PT + */ - for (j = X86_MMU_VADDR_INDEX(vaddr, ptlevel); - j < X86_MMU_ENTRIES_PER_PGT && nmapped < size; - j++) + do { paddr = mm_pgalloc(1); if (!paddr) @@ -311,6 +311,7 @@ static int x86_64_create_region(arch_addrenv_t *addrenv, uintptr_t vaddr, nmapped += MM_PGSIZE; vaddr += MM_PGSIZE; } + while (nmapped < size && X86_MMU_VADDR_INDEX(vaddr, ptlevel + 1) != 0); } /* Flush the data cache, so the changes are committed to memory */
