Date: Thu, 28 Jun 2001 20:35:20 +0100 (BST) From: Doug Rabson <dfr@nlsystems.com> To: John Baldwin <jhb@FreeBSD.org> Cc: <alpha@FreeBSD.ORG> Subject: Re: pmap_emulate_reference() Message-ID: <Pine.BSF.4.33.0106282033460.1173-100000@herring.nlsystems.com> In-Reply-To: <XFMail.010627211630.jhb@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 27 Jun 2001, John Baldwin wrote: > > On 27-Jun-01 Doug Rabson wrote: > > On Thu, 28 Jun 2001, Doug Rabson wrote: > > > >> 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. > >> > > > > This version is a bit simpler... > > It also means that pmap_emulate_reference() won't need the vm lock anymore, > which is a big win here. Ok, this version actually compiles. I'm not planning to test it until I get home though. Index: mp_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/alpha/alpha/mp_machdep.c,v retrieving revision 1.21 diff -u -r1.21 mp_machdep.c --- mp_machdep.c 2001/06/13 20:40:24 1.21 +++ mp_machdep.c 2001/06/28 19:18:09 @@ -363,13 +363,14 @@ } all_cpus |= 1 << i; mp_ncpus++; + break; } PCPU_SET(other_cpus, all_cpus & ~(1 << boot_cpu_id)); for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) { if (i == boot_cpu_id) continue; - if (all_cpus & 1 << i) + if (all_cpus & 1 << i) smp_start_secondary(i); } } Index: pmap.c =================================================================== RCS file: /home/ncvs/src/sys/alpha/alpha/pmap.c,v retrieving revision 1.59 diff -u -r1.59 pmap.c --- pmap.c 2001/06/25 23:52:25 1.59 +++ pmap.c 2001/06/28 19:32:43 @@ -2745,16 +2745,32 @@ int pmap_ts_referenced(vm_page_t m) { + pv_entry_t pv; + pt_entry_t *pte; + 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 don't + * have PG_FOR set (i.e. ones where we have taken an emulate + * reference trap recently). + */ + 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_FOR)) { + count++; + *pte |= PG_FOR | PG_FOE; + pmap_invalidate_page(pv->pv_pmap, pv->pv_va); + } } - return 0; + return count; } /* @@ -2766,11 +2782,25 @@ boolean_t pmap_is_modified(vm_page_t m) { + pv_entry_t pv; + pt_entry_t *pte; if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) return FALSE; - return (m->md.pv_flags & PV_TABLE_MOD) != 0; + /* + * A page is modified if any mapping has had its PG_FOW flag + * cleared. + */ + 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_FOW)) + return 1; + } + + return 0; } /* @@ -2779,12 +2809,24 @@ void pmap_clear_modify(vm_page_t m) { + pv_entry_t pv; + pt_entry_t *pte; + 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 setting PG_FOW where needed. + */ + 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_FOW)) { + *pte |= PG_FOW; + pmap_invalidate_page(pv->pv_pmap, pv->pv_va); + } } } @@ -2829,7 +2871,6 @@ { pt_entry_t faultoff, *pte; vm_offset_t pa; - vm_page_t m; int user_addr; /* @@ -2883,33 +2924,14 @@ * (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) - vm_page_flag_set(m, PG_REFERENCED); - 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; + } else { + faultoff = PG_FOR | PG_FOE; } + + *pte = (*pte & ~faultoff); + ALPHA_TBIS(v); } /* Index: trap.c =================================================================== RCS file: /home/ncvs/src/sys/alpha/alpha/trap.c,v retrieving revision 1.65 diff -u -r1.65 trap.c --- trap.c 2001/06/25 23:52:25 1.65 +++ trap.c 2001/06/28 19:26:47 @@ -484,18 +484,10 @@ case ALPHA_MMCSR_FOR: case ALPHA_MMCSR_FOE: case ALPHA_MMCSR_FOW: - { - int hadvmlock; - - hadvmlock = mtx_owned(&vm_mtx); - if (hadvmlock == 0) - mtx_lock(&vm_mtx); pmap_emulate_reference(p, a0, user, a1 == ALPHA_MMCSR_FOW); - if (hadvmlock == 0) - mtx_unlock(&vm_mtx); goto out; - } + case ALPHA_MMCSR_INVALTRANS: case ALPHA_MMCSR_ACCESS: { -- 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.0106282033460.1173-100000>