Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Oct 2012 16:57:05 +0000 (UTC)
From:      Alan Cox <alc@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r241353 - in head/sys/i386: i386 xen
Message-ID:  <201210081657.q98Gv5fH037726@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: alc
Date: Mon Oct  8 16:57:05 2012
New Revision: 241353
URL: http://svn.freebsd.org/changeset/base/241353

Log:
  In a few places, like the implementation of ptrace(), a thread may call
  upon pmap_enter() to create a mapping within a different address space,
  i.e., not the thread's own address space.  On i386, this entails the
  creation of a temporary mapping to the affected page table page (PTP).  In
  general, pmap_enter() will read from this PTP, allocate a PV entry, and
  write to this PTP.  The trouble comes when the system is short of memory.
  In order to allocate a new PV entry, an older PV entry has to be
  reclaimed.  Reclaiming a PV entry involves destroying a mapping, which
  requires access to the affected PTP.  Thus, the PTP mapped at the
  beginning of pmap_enter() is no longer mapped at the end of pmap_enter(),
  which leads to pmap_enter() modifying the wrong PTP.  To address this
  problem, pmap_pv_reclaim() is changed to use an alternate method of
  mapping PTPs.
  
  Update a related comment.
  
  Reported by:	pho
  Diagnosed by:	kib
  MFC after:	5 days

Modified:
  head/sys/i386/i386/pmap.c
  head/sys/i386/xen/pmap.c

Modified: head/sys/i386/i386/pmap.c
==============================================================================
--- head/sys/i386/i386/pmap.c	Mon Oct  8 16:00:33 2012	(r241352)
+++ head/sys/i386/i386/pmap.c	Mon Oct  8 16:57:05 2012	(r241353)
@@ -475,7 +475,8 @@ pmap_bootstrap(vm_paddr_t firstaddr)
 	KPTmap -= i386_btop(KPTDI << PDRSHIFT);
 
 	/*
-	 * ptemap is used for pmap_pte_quick
+	 * PADDR1 and PADDR2 are used by pmap_pte_quick() and pmap_pte(),
+	 * respectively.
 	 */
 	SYSMAP(pt_entry_t *, PMAP1, PADDR1, 1)
 	SYSMAP(pt_entry_t *, PMAP2, PADDR2, 1)
@@ -2228,7 +2229,6 @@ pmap_pv_reclaim(pmap_t locked_pmap)
 	pmap = NULL;
 	free = m_pc = NULL;
 	TAILQ_INIT(&newtail);
-	sched_pin();
 	while ((pc = TAILQ_FIRST(&pv_chunks)) != NULL && (pv_vafree == 0 ||
 	    free == NULL)) {
 		TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
@@ -2262,10 +2262,13 @@ pmap_pv_reclaim(pmap_t locked_pmap)
 				pde = pmap_pde(pmap, va);
 				if ((*pde & PG_PS) != 0)
 					continue;
-				pte = pmap_pte_quick(pmap, va);
-				if ((*pte & PG_W) != 0)
+				pte = pmap_pte(pmap, va);
+				tpte = *pte;
+				if ((tpte & PG_W) == 0)
+					tpte = pte_load_clear(pte);
+				pmap_pte_release(pte);
+				if ((tpte & PG_W) != 0)
 					continue;
-				tpte = pte_load_clear(pte);
 				if ((tpte & PG_G) != 0)
 					pmap_invalidate_page(pmap, va);
 				m = PHYS_TO_VM_PAGE(tpte & PG_FRAME);
@@ -2323,7 +2326,6 @@ pmap_pv_reclaim(pmap_t locked_pmap)
 		}
 	}
 out:
-	sched_unpin();
 	TAILQ_CONCAT(&pv_chunks, &newtail, pc_lru);
 	if (pmap != NULL) {
 		pmap_invalidate_all(pmap);

Modified: head/sys/i386/xen/pmap.c
==============================================================================
--- head/sys/i386/xen/pmap.c	Mon Oct  8 16:00:33 2012	(r241352)
+++ head/sys/i386/xen/pmap.c	Mon Oct  8 16:57:05 2012	(r241353)
@@ -429,7 +429,8 @@ pmap_bootstrap(vm_paddr_t firstaddr)
 	SYSMAP(struct msgbuf *, unused, msgbufp, atop(round_page(msgbufsize)))
 
 	/*
-	 * ptemap is used for pmap_pte_quick
+	 * PADDR1 and PADDR2 are used by pmap_pte_quick() and pmap_pte(),
+	 * respectively.
 	 */
 	SYSMAP(pt_entry_t *, PMAP1, PADDR1, 1)
 	SYSMAP(pt_entry_t *, PMAP2, PADDR2, 1)
@@ -1976,7 +1977,6 @@ pmap_pv_reclaim(pmap_t locked_pmap)
 	pmap = NULL;
 	free = m_pc = NULL;
 	TAILQ_INIT(&newtail);
-	sched_pin();
 	while ((pc = TAILQ_FIRST(&pv_chunks)) != NULL && (pv_vafree == 0 ||
 	    free == NULL)) {
 		TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
@@ -2007,10 +2007,13 @@ pmap_pv_reclaim(pmap_t locked_pmap)
 				bit = bsfl(inuse);
 				pv = &pc->pc_pventry[field * 32 + bit];
 				va = pv->pv_va;
-				pte = pmap_pte_quick(pmap, va);
-				if ((*pte & PG_W) != 0)
+				pte = pmap_pte(pmap, va);
+				tpte = *pte;
+				if ((tpte & PG_W) == 0)
+					tpte = pte_load_clear(pte);
+				pmap_pte_release(pte);
+				if ((tpte & PG_W) != 0)
 					continue;
-				tpte = pte_load_clear(pte);
 				if ((tpte & PG_G) != 0)
 					pmap_invalidate_page(pmap, va);
 				m = PHYS_TO_VM_PAGE(tpte & PG_FRAME);
@@ -2062,7 +2065,6 @@ pmap_pv_reclaim(pmap_t locked_pmap)
 		}
 	}
 out:
-	sched_unpin();
 	TAILQ_CONCAT(&pv_chunks, &newtail, pc_lru);
 	if (pmap != NULL) {
 		pmap_invalidate_all(pmap);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201210081657.q98Gv5fH037726>