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>
next in thread | raw e-mail | index | archive | help
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.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200801081948.m08Jmpoa006156>