summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2006-07-18 03:17:12 +0000
committeralc <alc@FreeBSD.org>2006-07-18 03:17:12 +0000
commitf0337456d9cd24e1649d4d85f5324c8d8bb8ebd6 (patch)
tree331eebc7b155a77d2a732254f34e635ff4e04c69 /sys/i386
parent3f582797ac4997a615e29dfbc443454cf01d5636 (diff)
downloadFreeBSD-src-f0337456d9cd24e1649d4d85f5324c8d8bb8ebd6.zip
FreeBSD-src-f0337456d9cd24e1649d4d85f5324c8d8bb8ebd6.tar.gz
MFamd64
pmap_clear_ptes() is already convoluted. This will worsen with the implementation of superpages. Eliminate it and add pmap_clear_write(). There are no functional changes. Checked by: md5
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/pmap.c105
1 files changed, 69 insertions, 36 deletions
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 24ae059..d8d5f61 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -266,7 +266,7 @@ static struct mtx PMAP2mutex;
static void free_pv_entry(pmap_t pmap, pv_entry_t pv);
static pv_entry_t get_pv_entry(pmap_t locked_pmap, int try);
-static void pmap_clear_ptes(vm_page_t m, int bit);
+static void pmap_clear_write(vm_page_t m);
static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va,
vm_page_t m, vm_prot_t prot, vm_page_t mpte);
@@ -3064,55 +3064,42 @@ pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr)
}
/*
- * Clear the given bit in each of the given page's ptes. The bit is
- * expressed as a 32-bit mask. Consequently, if the pte is 64 bits in
- * size, only a bit within the least significant 32 can be cleared.
+ * Clear the write and modified bits in each of the given page's mappings.
*/
static __inline void
-pmap_clear_ptes(vm_page_t m, int bit)
+pmap_clear_write(vm_page_t m)
{
pv_entry_t pv;
pmap_t pmap;
- pt_entry_t pbits, *pte;
+ pt_entry_t oldpte, *pte;
- if ((m->flags & PG_FICTITIOUS) ||
- (bit == PG_RW && (m->flags & PG_WRITEABLE) == 0))
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ if ((m->flags & PG_FICTITIOUS) != 0 ||
+ (m->flags & PG_WRITEABLE) == 0)
return;
-
sched_pin();
- mtx_assert(&vm_page_queue_mtx, MA_OWNED);
- /*
- * Loop over all current mappings setting/clearing as appropos If
- * setting RO do we need to clear the VAC?
- */
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
pmap = PV_PMAP(pv);
PMAP_LOCK(pmap);
pte = pmap_pte_quick(pmap, pv->pv_va);
retry:
- pbits = *pte;
- if (pbits & bit) {
- if (bit == PG_RW) {
- /*
- * Regardless of whether a pte is 32 or 64 bits
- * in size, PG_RW and PG_M are among the least
- * significant 32 bits.
- */
- if (!atomic_cmpset_int((u_int *)pte, pbits,
- pbits & ~(PG_RW | PG_M)))
- goto retry;
- if (pbits & PG_M) {
- vm_page_dirty(m);
- }
- } else {
- atomic_clear_int((u_int *)pte, bit);
- }
+ oldpte = *pte;
+ if ((oldpte & PG_RW) != 0) {
+ /*
+ * Regardless of whether a pte is 32 or 64 bits
+ * in size, PG_RW and PG_M are among the least
+ * significant 32 bits.
+ */
+ if (!atomic_cmpset_int((u_int *)pte, oldpte,
+ oldpte & ~(PG_RW | PG_M)))
+ goto retry;
+ if ((oldpte & PG_M) != 0)
+ vm_page_dirty(m);
pmap_invalidate_page(pmap, pv->pv_va);
}
PMAP_UNLOCK(pmap);
}
- if (bit == PG_RW)
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_flag_clear(m, PG_WRITEABLE);
sched_unpin();
}
@@ -3126,7 +3113,7 @@ pmap_page_protect(vm_page_t m, vm_prot_t prot)
{
if ((prot & VM_PROT_WRITE) == 0) {
if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
- pmap_clear_ptes(m, PG_RW);
+ pmap_clear_write(m);
} else {
pmap_remove_all(m);
}
@@ -3186,7 +3173,30 @@ pmap_ts_referenced(vm_page_t m)
void
pmap_clear_modify(vm_page_t m)
{
- pmap_clear_ptes(m, PG_M);
+ pv_entry_t pv;
+ pmap_t pmap;
+ pt_entry_t *pte;
+
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ if ((m->flags & PG_FICTITIOUS) != 0)
+ return;
+ sched_pin();
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte = pmap_pte_quick(pmap, pv->pv_va);
+ if ((*pte & PG_M) != 0) {
+ /*
+ * Regardless of whether a pte is 32 or 64 bits
+ * in size, PG_M is among the least significant
+ * 32 bits.
+ */
+ atomic_clear_int((u_int *)pte, PG_M);
+ pmap_invalidate_page(pmap, pv->pv_va);
+ }
+ PMAP_UNLOCK(pmap);
+ }
+ sched_unpin();
}
/*
@@ -3197,7 +3207,30 @@ pmap_clear_modify(vm_page_t m)
void
pmap_clear_reference(vm_page_t m)
{
- pmap_clear_ptes(m, PG_A);
+ pv_entry_t pv;
+ pmap_t pmap;
+ pt_entry_t *pte;
+
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ if ((m->flags & PG_FICTITIOUS) != 0)
+ return;
+ sched_pin();
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte = pmap_pte_quick(pmap, pv->pv_va);
+ if ((*pte & PG_A) != 0) {
+ /*
+ * Regardless of whether a pte is 32 or 64 bits
+ * in size, PG_A is among the least significant
+ * 32 bits.
+ */
+ atomic_clear_int((u_int *)pte, PG_A);
+ pmap_invalidate_page(pmap, pv->pv_va);
+ }
+ PMAP_UNLOCK(pmap);
+ }
+ sched_unpin();
}
/*
OpenPOWER on IntegriCloud