Date: Tue, 8 Jan 2008 13:48:51 -0600 (CST) From: Mark Tinguely <tinguely@casselton.net> To: freebsd-arm@freebsd.org, mlfbsd@ci0.org Subject: ARM pmap cache flushed after PT modification. Message-ID: <200801081948.m08Jmpoa006156@casselton.net>
index | next in thread | raw e-mail
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.
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200801081948.m08Jmpoa006156>
