Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 07 Jul 2012 12:39:18 -0500
From:      Alan Cox <alc@rice.edu>
To:        Justin Hibbits <chmeeedalf@gmail.com>
Cc:        alc@freebsd.org, freebsd-ppc@freebsd.org
Subject:   Re: Panic with latest pmap lock changes.
Message-ID:  <4FF87446.2090903@rice.edu>
In-Reply-To: <20120707102004.3e874201@narn.knownspace>
References:  <20120707102004.3e874201@narn.knownspace>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------070807020805030306060404
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

On 07/07/2012 09:20, Justin Hibbits wrote:
> Looks like I spoke too soon about the pmap lock changes working on my
> G4.  After about 24 hours of uptime, it panicked with the following:
>
> _rw_wlock_hard: recursing but non-recursive rw pmap pv global
> @ /home/chmeee/freebsd/src/sys/powerpc/aim/mmu_oea.c:2301
>
> I think the attached patch should fix it (Untested, except for
> compiling).
>

Ugh.  Sorry.

The attached patch eliminates the lock recursion.  While I was doing 
that, I noticed that the pmap_ts_referenced() implementations on powerpc 
have the wrong return type.  Oddly, the comments in mmu_if.h have the 
return type correct, but the code two or three lines later has it wrong.

Alan


--------------070807020805030306060404
Content-Type: text/plain;
 name="powerpc_pmap.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="powerpc_pmap.patch"

Index: powerpc/powerpc/mmu_if.m
===================================================================
--- powerpc/powerpc/mmu_if.m	(revision 237346)
+++ powerpc/powerpc/mmu_if.m	(working copy)
@@ -387,7 +387,7 @@ METHOD boolean_t is_referenced {
  *
  * @retval int		count of referenced bits
  */
-METHOD boolean_t ts_referenced {
+METHOD int ts_referenced {
 	mmu_t		_mmu;
 	vm_page_t	_pg;
 };
Index: powerpc/booke/pmap.c
===================================================================
--- powerpc/booke/pmap.c	(revision 237346)
+++ powerpc/booke/pmap.c	(working copy)
@@ -286,7 +286,7 @@ static void		mmu_booke_init(mmu_t);
 static boolean_t	mmu_booke_is_modified(mmu_t, vm_page_t);
 static boolean_t	mmu_booke_is_prefaultable(mmu_t, pmap_t, vm_offset_t);
 static boolean_t	mmu_booke_is_referenced(mmu_t, vm_page_t);
-static boolean_t	mmu_booke_ts_referenced(mmu_t, vm_page_t);
+static int		mmu_booke_ts_referenced(mmu_t, vm_page_t);
 static vm_offset_t	mmu_booke_map(mmu_t, vm_offset_t *, vm_paddr_t, vm_paddr_t,
     int);
 static int		mmu_booke_mincore(mmu_t, pmap_t, vm_offset_t,
Index: powerpc/aim/mmu_oea.c
===================================================================
--- powerpc/aim/mmu_oea.c	(revision 238159)
+++ powerpc/aim/mmu_oea.c	(working copy)
@@ -300,7 +300,7 @@ void moea_init(mmu_t);
 boolean_t moea_is_modified(mmu_t, vm_page_t);
 boolean_t moea_is_prefaultable(mmu_t, pmap_t, vm_offset_t);
 boolean_t moea_is_referenced(mmu_t, vm_page_t);
-boolean_t moea_ts_referenced(mmu_t, vm_page_t);
+int moea_ts_referenced(mmu_t, vm_page_t);
 vm_offset_t moea_map(mmu_t, vm_offset_t *, vm_paddr_t, vm_paddr_t, int);
 boolean_t moea_page_exists_quick(mmu_t, pmap_t, vm_page_t);
 int moea_page_wired_mappings(mmu_t, vm_page_t);
@@ -1269,15 +1269,20 @@ moea_init(mmu_t mmu)
 boolean_t
 moea_is_referenced(mmu_t mmu, vm_page_t m)
 {
+	boolean_t rv;
 
 	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
 	    ("moea_is_referenced: page %p is not managed", m));
-	return (moea_query_bit(m, PTE_REF));
+	rw_wlock(&pvh_global_lock);
+	rv = moea_query_bit(m, PTE_REF);
+	rw_wunlock(&pvh_global_lock);
+	return (rv);
 }
 
 boolean_t
 moea_is_modified(mmu_t mmu, vm_page_t m)
 {
+	boolean_t rv;
 
 	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
 	    ("moea_is_modified: page %p is not managed", m));
@@ -1291,7 +1296,10 @@ moea_is_modified(mmu_t mmu, vm_page_t m)
 	if ((m->oflags & VPO_BUSY) == 0 &&
 	    (m->aflags & PGA_WRITEABLE) == 0)
 		return (FALSE);
-	return (moea_query_bit(m, PTE_CHG));
+	rw_wlock(&pvh_global_lock);
+	rv = moea_query_bit(m, PTE_CHG);
+	rw_wunlock(&pvh_global_lock);
+	return (rv);
 }
 
 boolean_t
@@ -1313,7 +1321,9 @@ moea_clear_reference(mmu_t mmu, vm_page_t m)
 
 	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
 	    ("moea_clear_reference: page %p is not managed", m));
+	rw_wlock(&pvh_global_lock);
 	moea_clear_bit(m, PTE_REF);
+	rw_wunlock(&pvh_global_lock);
 }
 
 void
@@ -1333,7 +1343,9 @@ moea_clear_modify(mmu_t mmu, vm_page_t m)
 	 */
 	if ((m->aflags & PGA_WRITEABLE) == 0)
 		return;
+	rw_wlock(&pvh_global_lock);
 	moea_clear_bit(m, PTE_CHG);
+	rw_wunlock(&pvh_global_lock);
 }
 
 /*
@@ -1400,13 +1412,17 @@ moea_remove_write(mmu_t mmu, vm_page_t m)
  *	should be tested and standardized at some point in the future for
  *	optimal aging of shared pages.
  */
-boolean_t
+int
 moea_ts_referenced(mmu_t mmu, vm_page_t m)
 {
+	int count;
 
 	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
 	    ("moea_ts_referenced: page %p is not managed", m));
-	return (moea_clear_bit(m, PTE_REF));
+	rw_wlock(&pvh_global_lock);
+	count = moea_clear_bit(m, PTE_REF);
+	rw_wunlock(&pvh_global_lock);
+	return (count);
 }
 
 /*
@@ -1816,7 +1832,7 @@ moea_remove_all(mmu_t mmu, vm_page_t m)
 		moea_pvo_remove(pvo, -1);
 		PMAP_UNLOCK(pmap);
 	}
-	if ((m->aflags & PGA_WRITEABLE) && moea_is_modified(mmu, m)) {
+	if ((m->aflags & PGA_WRITEABLE) && moea_query_bit(m, PTE_CHG)) {
 		moea_attr_clear(m, PTE_CHG);
 		vm_page_dirty(m);
 	}
@@ -2293,10 +2309,10 @@ moea_query_bit(vm_page_t m, int ptebit)
 	struct	pvo_entry *pvo;
 	struct	pte *pt;
 
+	rw_assert(&pvh_global_lock, RA_WLOCKED);
 	if (moea_attr_fetch(m) & ptebit)
 		return (TRUE);
 
-	rw_wlock(&pvh_global_lock);
 	LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
 
 		/*
@@ -2305,7 +2321,6 @@ moea_query_bit(vm_page_t m, int ptebit)
 		 */
 		if (pvo->pvo_pte.pte.pte_lo & ptebit) {
 			moea_attr_save(m, ptebit);
-			rw_wunlock(&pvh_global_lock);
 			return (TRUE);
 		}
 	}
@@ -2329,13 +2344,11 @@ moea_query_bit(vm_page_t m, int ptebit)
 			mtx_unlock(&moea_table_mutex);
 			if (pvo->pvo_pte.pte.pte_lo & ptebit) {
 				moea_attr_save(m, ptebit);
-				rw_wunlock(&pvh_global_lock);
 				return (TRUE);
 			}
 		}
 	}
 
-	rw_wunlock(&pvh_global_lock);
 	return (FALSE);
 }
 
@@ -2346,7 +2359,7 @@ moea_clear_bit(vm_page_t m, int ptebit)
 	struct	pvo_entry *pvo;
 	struct	pte *pt;
 
-	rw_wlock(&pvh_global_lock);
+	rw_assert(&pvh_global_lock, RA_WLOCKED);
 
 	/*
 	 * Clear the cached value.
@@ -2380,7 +2393,6 @@ moea_clear_bit(vm_page_t m, int ptebit)
 		pvo->pvo_pte.pte.pte_lo &= ~ptebit;
 	}
 
-	rw_wunlock(&pvh_global_lock);
 	return (count);
 }
 
Index: powerpc/aim/mmu_oea64.c
===================================================================
--- powerpc/aim/mmu_oea64.c	(revision 237346)
+++ powerpc/aim/mmu_oea64.c	(working copy)
@@ -305,7 +305,7 @@ void moea64_init(mmu_t);
 boolean_t moea64_is_modified(mmu_t, vm_page_t);
 boolean_t moea64_is_prefaultable(mmu_t, pmap_t, vm_offset_t);
 boolean_t moea64_is_referenced(mmu_t, vm_page_t);
-boolean_t moea64_ts_referenced(mmu_t, vm_page_t);
+int moea64_ts_referenced(mmu_t, vm_page_t);
 vm_offset_t moea64_map(mmu_t, vm_offset_t *, vm_paddr_t, vm_paddr_t, int);
 boolean_t moea64_page_exists_quick(mmu_t, pmap_t, vm_page_t);
 int moea64_page_wired_mappings(mmu_t, vm_page_t);
@@ -1570,7 +1570,7 @@ moea64_remove_write(mmu_t mmu, vm_page_t m)
  *	should be tested and standardized at some point in the future for
  *	optimal aging of shared pages.
  */
-boolean_t
+int
 moea64_ts_referenced(mmu_t mmu, vm_page_t m)
 {
 

--------------070807020805030306060404--



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