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>
index | next in thread | previous in thread | raw e-mail
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
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.33.0106282033460.1173-100000>
