svn commit: r240241 - head/sys/mips/mips
Alan Cox
alc at FreeBSD.org
Sat Sep 8 17:43:21 UTC 2012
Author: alc
Date: Sat Sep 8 17:43:20 2012
New Revision: 240241
URL: http://svn.freebsd.org/changeset/base/240241
Log:
pmap_remove:
Avoid re-walking the page table from the root for every PTE examined.
Tidy up some of pmap_remove()'s helper functions.
pmap_enter:
Set PV_TABLE_REF whenever the physical page being mapped is managed, not
just when it is writeable.
Only call pmap_update_page() when the old mapping was valid. If there was
no prior valid mapping, then pmap_update_page() serves no useful purpose.
However, it will interrupt every processor that has the pmap active.
pmap_enter_quick_locked:
Always set PTE_RO.
pmap_emulate_modified:
Don't set PV_TABLE_REF.
Eliminate a nonsensical comment.
Modified:
head/sys/mips/mips/pmap.c
Modified: head/sys/mips/mips/pmap.c
==============================================================================
--- head/sys/mips/mips/pmap.c Sat Sep 8 16:47:52 2012 (r240240)
+++ head/sys/mips/mips/pmap.c Sat Sep 8 17:43:20 2012 (r240241)
@@ -1677,6 +1677,11 @@ pmap_remove_pte(struct pmap *pmap, pt_en
rw_assert(&pvh_global_lock, RA_WLOCKED);
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ /*
+ * Write back all cache lines from the page being unmapped.
+ */
+ mips_dcache_wbinv_range_index(va, PAGE_SIZE);
+
oldpte = *ptq;
if (is_kernel_pmap(pmap))
*ptq = PTE_G;
@@ -1723,24 +1728,13 @@ pmap_remove_page(struct pmap *pmap, vm_o
ptq = pmap_pde_to_pte(pde, va);
/*
- * if there is no pte for this address, just skip it!!!
+ * If there is no pte for this address, just skip it!
*/
- if (!pte_test(ptq, PTE_V)) {
+ if (!pte_test(ptq, PTE_V))
return;
- }
- /*
- * Write back all caches from the page being destroyed
- */
- mips_dcache_wbinv_range_index(va, PAGE_SIZE);
-
- /*
- * get a local va for mappings for this pmap.
- */
(void)pmap_remove_pte(pmap, ptq, va, *pde);
pmap_invalidate_page(pmap, va);
-
- return;
}
/*
@@ -1789,9 +1783,12 @@ pmap_remove(struct pmap *pmap, vm_offset
continue;
if (va_next > eva)
va_next = eva;
- for (pte = pmap_pde_to_pte(pde, sva); sva != va_next;
- pte++, sva += PAGE_SIZE) {
- pmap_remove_page(pmap, sva);
+ for (pte = pmap_pde_to_pte(pde, sva); sva != va_next; pte++,
+ sva += PAGE_SIZE) {
+ if (!pte_test(pte, PTE_V))
+ continue;
+ pmap_remove_pte(pmap, pte, sva, *pde);
+ pmap_invalidate_page(pmap, sva);
}
}
out:
@@ -2035,6 +2032,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va,
mpte->wire_count--;
if (pte_test(&origpte, PTE_MANAGED)) {
+ m->md.pv_flags |= PV_TABLE_REF;
om = m;
newpte |= PTE_MANAGED;
if (!pte_test(&newpte, PTE_RO))
@@ -2070,6 +2068,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va,
* Enter on the PV list if part of our managed memory.
*/
if ((m->oflags & VPO_UNMANAGED) == 0) {
+ m->md.pv_flags |= PV_TABLE_REF;
if (pv == NULL)
pv = get_pv_entry(pmap, FALSE);
pv->pv_va = va;
@@ -2087,8 +2086,6 @@ pmap_enter(pmap_t pmap, vm_offset_t va,
pmap->pm_stats.wired_count++;
validate:
- if ((access & VM_PROT_WRITE) != 0)
- m->md.pv_flags |= PV_TABLE_REF;
#ifdef PMAP_DEBUG
printf("pmap_enter: va: %p -> pa: %p\n", (void *)va, (void *)pa);
@@ -2099,8 +2096,8 @@ validate:
* update the pte.
*/
if (origpte != newpte) {
+ *pte = newpte;
if (pte_test(&origpte, PTE_V)) {
- *pte = newpte;
if (pte_test(&origpte, PTE_MANAGED) && opa != pa) {
if (om->md.pv_flags & PV_TABLE_REF)
vm_page_aflag_set(om, PGA_REFERENCED);
@@ -2116,11 +2113,9 @@ validate:
if (pte_test(&origpte, PTE_MANAGED) &&
TAILQ_EMPTY(&om->md.pv_list))
vm_page_aflag_clear(om, PGA_WRITEABLE);
- } else {
- *pte = newpte;
+ pmap_update_page(pmap, va, newpte);
}
}
- pmap_update_page(pmap, va, newpte);
/*
* Sync I & D caches for executable pages. Do this only if the
@@ -2239,7 +2234,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_
/*
* Now validate mapping with RO protection
*/
- *pte = TLBLO_PA_TO_PFN(pa) | PTE_V;
+ *pte = PTE_RO | TLBLO_PA_TO_PFN(pa) | PTE_V;
if ((m->oflags & VPO_UNMANAGED) == 0)
*pte |= PTE_MANAGED;
@@ -2251,7 +2246,6 @@ pmap_enter_quick_locked(pmap_t pmap, vm_
if (is_kernel_pmap(pmap))
*pte |= PTE_G;
else {
- *pte |= PTE_RO;
/*
* Sync I & D caches. Do this only if the target pmap
* belongs to the current process. Otherwise, an
@@ -3255,9 +3249,7 @@ init_pte_prot(vm_page_t m, vm_prot_t acc
int
pmap_emulate_modified(pmap_t pmap, vm_offset_t va)
{
- vm_page_t m;
pt_entry_t *pte;
- vm_paddr_t pa;
PMAP_LOCK(pmap);
pte = pmap_pte(pmap, va);
@@ -3275,7 +3267,6 @@ pmap_emulate_modified(pmap_t pmap, vm_of
panic("pmap_emulate_modified: invalid pte");
#endif
if (pte_test(pte, PTE_RO)) {
- /* write to read only page in the kernel */
PMAP_UNLOCK(pmap);
return (1);
}
@@ -3283,9 +3274,6 @@ pmap_emulate_modified(pmap_t pmap, vm_of
tlb_update(pmap, va, *pte);
if (!pte_test(pte, PTE_MANAGED))
panic("pmap_emulate_modified: unmanaged page");
- pa = TLBLO_PTE_TO_PA(*pte);
- m = PHYS_TO_VM_PAGE(pa);
- m->md.pv_flags |= PV_TABLE_REF;
PMAP_UNLOCK(pmap);
return (0);
}
More information about the svn-src-all
mailing list