summaryrefslogtreecommitdiffstats
path: root/sys/alpha
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>2001-09-09 16:36:59 +0000
committerdfr <dfr@FreeBSD.org>2001-09-09 16:36:59 +0000
commit774ebbef7e7777c5faf88d649e116db19aff0058 (patch)
treee080633f45130eb22642e758c899e5b84ec9443c /sys/alpha
parentcf1db3ca684843192b96cfe705c390ab67450818 (diff)
downloadFreeBSD-src-774ebbef7e7777c5faf88d649e116db19aff0058.zip
FreeBSD-src-774ebbef7e7777c5faf88d649e116db19aff0058.tar.gz
Fix some problems with the reference/modified tracking which I introduced
with the last change to the way the pmap_emulate_reference() works. This should fix a number of memory corruption problems and also should stop the mtimes of executables changing all the time.
Diffstat (limited to 'sys/alpha')
-rw-r--r--sys/alpha/alpha/pmap.c55
1 files changed, 51 insertions, 4 deletions
diff --git a/sys/alpha/alpha/pmap.c b/sys/alpha/alpha/pmap.c
index ecaba7b..eed5e5e 100644
--- a/sys/alpha/alpha/pmap.c
+++ b/sys/alpha/alpha/pmap.c
@@ -1787,6 +1787,12 @@ pmap_remove_pte(pmap_t pmap, pt_entry_t* ptq, vm_offset_t va)
pmap->pm_stats.resident_count -= 1;
if (oldpte & PG_MANAGED) {
m = PHYS_TO_VM_PAGE(pmap_pte_pa(&oldpte));
+ if ((oldpte & PG_FOW) == 0) {
+ if (pmap_track_modified(va))
+ vm_page_dirty(m);
+ }
+ if ((oldpte & PG_FOR) == 0)
+ vm_page_flag_set(m, PG_REFERENCED);
return pmap_remove_entry(pmap, m, va);
} else {
return pmap_unuse_pt(pmap, va, NULL);
@@ -1911,6 +1917,16 @@ pmap_remove_all(vm_page_t m)
if (tpte & PG_W)
pv->pv_pmap->pm_stats.wired_count--;
+ /*
+ * Update the vm_page_t clean and reference bits.
+ */
+ if ((tpte & PG_FOW) == 0) {
+ if (pmap_track_modified(pv->pv_va))
+ vm_page_dirty(m);
+ }
+ if ((tpte & PG_FOR) == 0)
+ vm_page_flag_set(m, PG_REFERENCED);
+
pmap_invalidate_page(pv->pv_pmap, pv->pv_va);
TAILQ_REMOVE(&pv->pv_pmap->pm_pvlist, pv, pv_plist);
@@ -1982,7 +1998,21 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
}
if (pmap_pte_prot(pte) != newprot) {
- pmap_pte_set_prot(pte, newprot);
+ pt_entry_t oldpte = *pte;
+ vm_page_t m = NULL;
+ if ((oldpte & PG_FOR) == 0) {
+ m = PHYS_TO_VM_PAGE(pmap_pte_pa(pte));
+ vm_page_flag_set(m, PG_REFERENCED);
+ oldpte |= (PG_FOR | PG_FOE);
+ }
+ if ((oldpte & PG_FOW) == 0) {
+ m = PHYS_TO_VM_PAGE(pmap_pte_pa(pte));
+ if (pmap_track_modified(sva))
+ vm_page_dirty(m);
+ oldpte |= PG_FOW;
+ }
+ oldpte = (oldpte & ~PG_PROT) | newprot;
+ *pte = oldpte;
pmap_invalidate_page(pmap, sva);
}
@@ -2066,6 +2096,19 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
if (mpte)
mpte->hold_count--;
+ /*
+ * We might be turning off write access to the page,
+ * so we go ahead and sense modify status.
+ */
+ if (origpte & PG_MANAGED) {
+ if ((origpte & PG_FOW) != PG_FOW
+ && pmap_track_modified(va)) {
+ vm_page_t om;
+ om = PHYS_TO_VM_PAGE(opa);
+ vm_page_dirty(om);
+ }
+ }
+
managed = origpte & PG_MANAGED;
goto validate;
}
@@ -2105,9 +2148,13 @@ validate:
if (managed) {
/*
- * Set up referenced/modified emulation for the new mapping
+ * Set up referenced/modified emulation for the new
+ * mapping. Any old referenced/modified emulation
+ * results for the old mapping will have been recorded
+ * either in pmap_remove_pte() or above in the code
+ * which handles protection and/or wiring changes.
*/
- newpte |= origpte & (PG_FOR | PG_FOW | PG_FOE);
+ newpte |= (PG_FOR | PG_FOW | PG_FOE);
}
if (wired)
@@ -2218,7 +2265,7 @@ retry:
/*
* Now validate mapping with RO protection
*/
- *pte = pmap_phys_to_pte(VM_PAGE_TO_PHYS(m)) | PG_V | PG_KRE | PG_URE | PG_MANAGED;
+ *pte = pmap_phys_to_pte(VM_PAGE_TO_PHYS(m)) | PG_V | PG_KRE | PG_URE | PG_MANAGED | PG_FOR | PG_FOE | PG_FOW;
alpha_pal_imb(); /* XXX overkill? */
return mpte;
OpenPOWER on IntegriCloud