Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Jun 2001 00:22:33 +0100 (BST)
From:      Doug Rabson <dfr@nlsystems.com>
To:        <alpha@freebsd.org>
Subject:   Re: pmap_emulate_reference()
Message-ID:  <Pine.BSF.4.33.0106280021530.97752-100000@herring.nlsystems.com>
In-Reply-To: <Pine.BSF.4.33.0106280012290.97752-100000@herring.nlsystems.com>

next in thread | previous in thread | raw e-mail | index | archive | help
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...

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:18:13
@@ -2745,16 +2745,31 @@
 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 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 +2781,24 @@
 boolean_t
 pmap_is_modified(vm_page_t m)
 {
+	pv_entry_t pv;

 	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 +2807,23 @@
 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 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_FOR | PG_FOE | PG_FOW;
+			pmap_invalidate_page(pv->pv_pmap, pv->pv_va);
+		}
 	}
 }

@@ -2883,35 +2922,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 && 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;
+	} else {
+		faultoff = PG_FOR | PG_FOE;
 	}
+
+	*pte = (*pte & ~faultoff);
+	ALPHA_TBIS(v);
 }

 /*


-- 
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.0106280021530.97752-100000>