Date: Thu, 28 Jun 2001 00:15:08 +0100 (BST) From: Doug Rabson <dfr@nlsystems.com> To: <alpha@freebsd.org> Subject: pmap_emulate_reference() Message-ID: <Pine.BSF.4.33.0106280012290.97752-100000@herring.nlsystems.com>
next in thread | raw e-mail | index | archive | help
Based on a conversation at lunch today, I decided to try rewriting pmap_emulate_reference() to avoid the need for the vm lock. Basically, I just use a couple of extra bits in the pte to store the changed/referenced state and defer the hard work to pmap_ts_referenced() etc. I haven't (obviously) tested this since I'm at Usenix but I think the principle is sound. Index: alpha/pmap.c =================================================================== RCS file: /home/ncvs/src/sys/alpha/alpha/pmap.c,v retrieving revision 1.58 diff -u -r1.58 pmap.c --- alpha/pmap.c 2001/05/21 16:09:29 1.58 +++ alpha/pmap.c 2001/06/28 00:08:08 @@ -2745,16 +2745,30 @@ int pmap_ts_referenced(vm_page_t m) { + pv_entry_t pv; + int count; + if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) return 0; - if (m->md.pv_flags & PV_TABLE_REF) { - pmap_changebit(m, PG_FOR|PG_FOE|PG_FOW, TRUE); - m->md.pv_flags &= ~PV_TABLE_REF; - return 1; + /* + * Loop over current mappings looking for any which have PG_A set. + */ + count = 0; + for (pv = TAILQ_FIRST(&m->md.pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + pte = pmap_lev3pte(pv->pv_pmap, pv->pv_va); + + if (*pte & PG_A) { + count++; + *pte &= ~PG_A; + *pte |= PG_FOR | PG_FOE; + pmap_invalidate_page(pv->pv_pmap, pv->pv_va); + } } - return 0; + return count; } /* @@ -2766,11 +2780,20 @@ boolean_t pmap_is_modified(vm_page_t m) { + pv_entry_t pv; if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) return FALSE; + + for (pv = TAILQ_FIRST(&m->md.pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + pte = pmap_lev3pte(pv->pv_pmap, pv->pv_va); + if (*pte & PG_D) + return 1; + } - return (m->md.pv_flags & PV_TABLE_MOD) != 0; + return 0; } /* @@ -2779,12 +2802,25 @@ void pmap_clear_modify(vm_page_t m) { + pv_entry_t pv; + if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) return; - if (m->md.pv_flags & PV_TABLE_MOD) { - pmap_changebit(m, PG_FOW, TRUE); - m->md.pv_flags &= ~PV_TABLE_MOD; + /* + * Loop over current mappings looking for any which have PG_A set. + */ + for (pv = TAILQ_FIRST(&m->md.pv_list); + pv; + pv = TAILQ_NEXT(pv, pv_list)) { + pte = pmap_lev3pte(pv->pv_pmap, pv->pv_va); + + if (*pte & PG_A) { + count++; + *pte &= ~(PG_A | PG_D); + *pte |= PG_FOR | PG_FOE | PG_FOW; + pmap_invalidate_page(pv->pv_pmap, pv->pv_va); + } } } @@ -2883,35 +2919,16 @@ * (1) always mark page as used, and * (2) if it was a write fault, mark page as modified. */ - m = PHYS_TO_VM_PAGE(pa); - m->md.pv_flags |= PV_TABLE_REF; - faultoff = PG_FOR | PG_FOE; - - if (user_addr && mtx_trylock(&vm_mtx)) { - vm_page_flag_set(m, PG_REFERENCED); - mtx_unlock(&vm_mtx); - } - if (write) { - m->md.pv_flags |= PV_TABLE_MOD; - vm_page_dirty(m); - faultoff |= PG_FOW; - } - pmap_changebit(m, faultoff, FALSE); - if ((*pte & faultoff) != 0) { -#if 1 - /* - * XXX dfr - don't think its possible in our pmap - */ - /* - * This is apparently normal. Why? -- cgd - * XXX because was being called on unmanaged pages? - */ - panic("warning: pmap_changebit didn't."); -#endif - *pte &= ~faultoff; - ALPHA_TBIS(v); + faultoff = PG_FOR | PG_FOE | PG_FOW; + faulton = PG_A | PG_D; + } else { + faultoff = PG_FOR | PG_FOE; + faulton = PG_A; } + + *pte = (*pte & ~faultoff) | faulton; + ALPHA_TBIS(v); } /* Index: include/pmap.h =================================================================== RCS file: /home/ncvs/src/sys/alpha/include/pmap.h,v retrieving revision 1.11 diff -u -r1.11 pmap.h --- include/pmap.h 2000/09/23 12:18:05 1.11 +++ include/pmap.h 2001/06/27 23:42:01 @@ -67,6 +67,8 @@ #define PG_W 0x00010000 /* software wired */ #define PG_MANAGED 0x00020000 /* software managed */ +#define PG_A 0x00040000 /* accessed */ +#define PG_D 0x00080000 /* dirty */ /* * Pte related macros -- Doug Rabson Mail: dfr@nlsystems.com Phone: +44 20 8348 6160 To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-alpha" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.33.0106280012290.97752-100000>