int up_addrenv_ustackselect(FAR const struct tcb_s *tcb) { uintptr_t vaddr; uintptr_t paddr; int i; DEBUGASSERT(tcb); for (vaddr = CONFIG_ARCH_STACK_VBASE, i = 0; i < ARCH_TEXT_NSECTS; vaddr += ARCH_STACK_NSECTS, i++) { /* Set (or clear) the new page table entry */ paddr = (uintptr_t)tcb->xcp.ustack[i]; if (paddr) { mmu_l1_setentry(paddr, vaddr, MMU_L1_PGTABFLAGS); } else { mmu_l1_clrentry(vaddr); } } return OK; }
int up_addrenv_select(FAR const group_addrenv_t *addrenv, FAR save_addrenv_t *oldenv) { uintptr_t vaddr; uintptr_t paddr; int i; DEBUGASSERT(addrenv); for (vaddr = CONFIG_ARCH_TEXT_VBASE, i = 0; i < ARCH_TEXT_NSECTS; vaddr += SECTION_SIZE, i++) { /* Save the old L1 page table entry */ if (oldenv) { oldenv->text[i] = mmu_l1_getentry(vaddr); } /* Set (or clear) the new page table entry */ paddr = (uintptr_t)addrenv->text[i]; if (paddr) { mmu_l1_setentry(paddr, vaddr, MMU_L1_PGTABFLAGS); } else { mmu_l1_clrentry(vaddr); } } for (vaddr = CONFIG_ARCH_DATA_VBASE, i = 0; i < ARCH_DATA_NSECTS; vaddr += SECTION_SIZE, i++) { /* Save the old L1 page table entry */ if (oldenv) { oldenv->data[i] = mmu_l1_getentry(vaddr); } /* Set (or clear) the new page table entry */ paddr = (uintptr_t)addrenv->data[i]; if (paddr) { mmu_l1_setentry(paddr, vaddr, MMU_L1_PGTABFLAGS); } else { mmu_l1_clrentry(vaddr); } } #ifdef CONFIG_BUILD_KERNEL for (vaddr = CONFIG_ARCH_HEAP_VBASE, i = 0; i < ARCH_HEAP_NSECTS; vaddr += SECTION_SIZE, i++) { /* Save the old L1 page table entry */ if (oldenv) { oldenv->heap[i] = mmu_l1_getentry(vaddr); } /* Set (or clear) the new page table entry */ paddr = (uintptr_t)addrenv->heap[i]; if (paddr) { mmu_l1_setentry(paddr, vaddr, MMU_L1_PGTABFLAGS); } else { mmu_l1_clrentry(vaddr); } } #ifdef CONFIG_MM_SHM for (vaddr = CONFIG_ARCH_SHM_VBASE, i = 0; i < ARCH_SHM_NSECTS; vaddr += SECTION_SIZE, i++) { /* Save the old L1 page table entry */ if (oldenv) { oldenv->shm[i] = mmu_l1_getentry(vaddr); } /* Set (or clear) the new page table entry */ paddr = (uintptr_t)addrenv->shm[i]; if (paddr) { mmu_l1_setentry(paddr, vaddr, MMU_L1_PGTABFLAGS); } else { mmu_l1_clrentry(vaddr); } } #endif #endif return OK; }
void arm_addrenv_destroy_region(FAR uintptr_t **list, unsigned int listlen, uintptr_t vaddr) { irqstate_t flags; uintptr_t paddr; FAR uint32_t *l2table; #ifndef CONFIG_ARCH_PGPOOL_MAPPING uint32_t l1save; #endif int i; int j; bvdbg("listlen=%d vaddr=%08lx\n", listlen, (unsigned long)vaddr); for (i = 0; i < listlen; vaddr += SECTION_SIZE, list++, i++) { /* Unhook the L2 page table from the L1 page table */ mmu_l1_clrentry(vaddr); /* Has this page table been allocated? */ paddr = (uintptr_t)list[i]; if (paddr != 0) { flags = irqsave(); #ifdef CONFIG_ARCH_PGPOOL_MAPPING /* Get the virtual address corresponding to the physical page address */ l2table = (FAR uint32_t *)arm_pgvaddr(paddr); #else /* Temporarily map the page into the virtual address space */ l1save = mmu_l1_getentry(ARCH_SCRATCH_VBASE); mmu_l1_setentry(paddr & ~SECTION_MASK, ARCH_SCRATCH_VBASE, MMU_MEMFLAGS); l2table = (FAR uint32_t *)(ARCH_SCRATCH_VBASE | (paddr & SECTION_MASK)); #endif /* Return the allocated pages to the page allocator */ for (j = 0; j < ENTRIES_PER_L2TABLE; j++) { paddr = *l2table++; if (paddr != 0) { paddr &= PTE_SMALL_PADDR_MASK; mm_pgfree(paddr, 1); } } #ifndef CONFIG_ARCH_PGPOOL_MAPPING /* Restore the scratch section L1 page table entry */ mmu_l1_restore(ARCH_SCRATCH_VBASE, l1save); #endif irqrestore(flags); /* And free the L2 page table itself */ mm_pgfree((uintptr_t)list[i], 1); } } }