mirror of
https://github.com/apache/nuttx.git
synced 2026-10-10 07:40:27 +00:00
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 <marco.casaroli@gmail.com>
This commit is contained in:
parent
3515e44845
commit
55cd85c9ab
1 changed files with 26 additions and 14 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue