ARM pmap cache flushed after PT modification.
Mark Tinguely
tinguely at casselton.net
Tue Jan 8 11:48:56 PST 2008
Since caches for ARM processor before version 6 use virtually indexed,
virtual tagged caches, the cache should be written back (flushed) before
altering the page table.
See between the VVVV and ^^^^ the order is clear page tables, then write
back the caches.
void
pmap_remove_pages(pmap_t pmap)
{
struct pv_entry *pv, *npv;
struct l2_bucket *l2b = NULL;
vm_page_t m;
pt_entry_t *pt;
vm_page_lock_queues();
PMAP_LOCK(pmap);
for (pv = TAILQ_FIRST(&pmap->pm_pvlist); pv; pv = npv) {
if (pv->pv_flags & PVF_WIRED) {
/* The page is wired, cannot remove it now. */
npv = TAILQ_NEXT(pv, pv_plist);
continue;
}
pmap->pm_stats.resident_count--;
l2b = pmap_get_l2_bucket(pmap, pv->pv_va);
KASSERT(l2b != NULL, ("No L2 bucket in pmap_remove_pages"));
pt = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
m = PHYS_TO_VM_PAGE(*pt & L2_ADDR_MASK);
#ifdef ARM_USE_SMALL_ALLOC
KASSERT((vm_offset_t)m >= alloc_firstaddr, ("Trying to access non-existent page va %x pte %x", pv->pv_va, *pt));
#else
KASSERT((vm_offset_t)m >= KERNBASE, ("Trying to access non-existent page va %x pte %x", pv->pv_va, *pt));
#endif
VVVVVVVVVV page table cleared
*pt = 0;
^^^^^^^^^^ page table cleared
PTE_SYNC(pt);
npv = TAILQ_NEXT(pv, pv_plist);
pmap_nuke_pv(m, pmap, pv);
if (TAILQ_EMPTY(&m->md.pv_list))
vm_page_flag_clear(m, PG_WRITEABLE);
pmap_free_pv_entry(pv);
pmap_free_l2_bucket(pmap, l2b, 1);
}
vm_page_unlock_queues();
VVVVVVVVVVVVVVVVVVVVVVVV cache written back
cpu_idcache_wbinv_all();
^^^^^^^^^^^^^^^^^^^^^^^^ cache written back
cpu_tlb_flushID();
cpu_cpwait();
PMAP_UNLOCK(pmap);
}
--Mark Tinguely.
More information about the freebsd-arm
mailing list