From f0337456d9cd24e1649d4d85f5324c8d8bb8ebd6 Mon Sep 17 00:00:00 2001 From: alc Date: Tue, 18 Jul 2006 03:17:12 +0000 Subject: 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 --- sys/i386/i386/pmap.c | 105 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 36 deletions(-) (limited to 'sys') 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(); } /* -- cgit v1.1