Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 27 Sep 2012 05:39:42 +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: r240983 - in head/sys/arm: arm include
Message-ID:  <201209270539.q8R5dg6S060164@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: alc
Date: Thu Sep 27 05:39:42 2012
New Revision: 240983
URL: http://svn.freebsd.org/changeset/base/240983

Log:
  Implementing pmap_kextract(va) as pmap_extract(kernel_pmap, va) is
  problematic because some callers to pmap_kextract() expect its
  implementation to be lock-less.  In particular, uma_dbg_alloc() implicitly
  requires this.  Otherwise, lock-order reversals occur between pmap locks and
  UMA zone locks.  So, this change introduces a lock-less implementation of
  pmap_kextract().
  
  Disable recursion on the pvh global lock in the new armv6 pmap.  While
  recursion on this locks occurs in the old arm pmap, it thankfully doesn't
  occur in the armv6 pmap.
  
  Tested by:	jmg

Modified:
  head/sys/arm/arm/pmap-v6.c
  head/sys/arm/arm/pmap.c
  head/sys/arm/include/pmap.h

Modified: head/sys/arm/arm/pmap-v6.c
==============================================================================
--- head/sys/arm/arm/pmap-v6.c	Thu Sep 27 05:26:29 2012	(r240982)
+++ head/sys/arm/arm/pmap-v6.c	Thu Sep 27 05:39:42 2012	(r240983)
@@ -148,9 +148,11 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/ktr.h>
+#include <sys/lock.h>
 #include <sys/proc.h>
 #include <sys/malloc.h>
 #include <sys/msgbuf.h>
+#include <sys/mutex.h>
 #include <sys/vmmeter.h>
 #include <sys/mman.h>
 #include <sys/rwlock.h>
@@ -167,8 +169,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_page.h>
 #include <vm/vm_pageout.h>
 #include <vm/vm_extern.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
+
 #include <machine/md_var.h>
 #include <machine/cpu.h>
 #include <machine/cpufunc.h>
@@ -202,6 +203,7 @@ static pv_entry_t pmap_get_pv_entry(void
 
 static void		pmap_enter_locked(pmap_t, vm_offset_t, vm_page_t,
     vm_prot_t, boolean_t, int);
+static vm_paddr_t	pmap_extract_locked(pmap_t pmap, vm_offset_t va);
 static void		pmap_alloc_l1(pmap_t);
 static void		pmap_free_l1(pmap_t);
 
@@ -1659,7 +1661,7 @@ pmap_bootstrap(vm_offset_t firstaddr, vm
 	/*
 	 * Initialize the global pv list lock.
 	 */
-	rw_init_flags(&pvh_global_lock, "pmap pv global", RW_RECURSE);
+	rw_init(&pvh_global_lock, "pmap pv global");
 
 	/*
 	 * Reserve some special page table entries/VA space for temporary
@@ -2100,6 +2102,13 @@ pmap_kenter_user(vm_offset_t va, vm_padd
 	pmap_fault_fixup(pmap_kernel(), va, VM_PROT_READ|VM_PROT_WRITE, 1);
 }
 
+vm_paddr_t
+pmap_kextract(vm_offset_t va)
+{
+
+	return (pmap_extract_locked(kernel_pmap, va));
+}
+
 /*
  * remove a page from the kernel pagetables
  */
@@ -2850,22 +2859,34 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pm
  *		with the given map/virtual_address pair.
  */
 vm_paddr_t
-pmap_extract(pmap_t pm, vm_offset_t va)
+pmap_extract(pmap_t pmap, vm_offset_t va)
+{
+	vm_paddr_t pa;
+
+	PMAP_LOCK(pmap);
+	pa = pmap_extract_locked(pmap, va);
+	PMAP_UNLOCK(pmap);
+	return (pa);
+}
+
+static vm_paddr_t
+pmap_extract_locked(pmap_t pmap, vm_offset_t va)
 {
 	struct l2_dtable *l2;
 	pd_entry_t l1pd;
 	pt_entry_t *ptep, pte;
 	vm_paddr_t pa;
 	u_int l1idx;
-	l1idx = L1_IDX(va);
 
-	PMAP_LOCK(pm);
-	l1pd = pm->pm_l1->l1_kva[l1idx];
+	if (pmap != kernel_pmap)
+		PMAP_ASSERT_LOCKED(pmap);
+	l1idx = L1_IDX(va);
+	l1pd = pmap->pm_l1->l1_kva[l1idx];
 	if (l1pte_section_p(l1pd)) {
 		/*
-		 * These should only happen for pmap_kernel()
+		 * These should only happen for the kernel pmap.
 		 */
-		KASSERT(pm == pmap_kernel(), ("huh"));
+		KASSERT(pmap == kernel_pmap, ("unexpected section"));
 		/* XXX: what to do about the bits > 32 ? */
 		if (l1pd & L1_S_SUPERSEC)
 			pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET);
@@ -2877,34 +2898,22 @@ pmap_extract(pmap_t pm, vm_offset_t va)
 		 * descriptor as an indication that a mapping exists.
 		 * We have to look it up in the L2 dtable.
 		 */
-		l2 = pm->pm_l2[L2_IDX(l1idx)];
-
+		l2 = pmap->pm_l2[L2_IDX(l1idx)];
 		if (l2 == NULL ||
-		    (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) {
-			PMAP_UNLOCK(pm);
+		    (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL)
 			return (0);
-		}
-
-		ptep = &ptep[l2pte_index(va)];
-		pte = *ptep;
-
-		if (pte == 0) {
-			PMAP_UNLOCK(pm);
+		pte = ptep[l2pte_index(va)];
+		if (pte == 0)
 			return (0);
-		}
-
 		switch (pte & L2_TYPE_MASK) {
 		case L2_TYPE_L:
 			pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET);
 			break;
-
 		default:
 			pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET);
 			break;
 		}
 	}
-
-	PMAP_UNLOCK(pm);
 	return (pa);
 }
 

Modified: head/sys/arm/arm/pmap.c
==============================================================================
--- head/sys/arm/arm/pmap.c	Thu Sep 27 05:26:29 2012	(r240982)
+++ head/sys/arm/arm/pmap.c	Thu Sep 27 05:39:42 2012	(r240983)
@@ -145,9 +145,11 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/ktr.h>
+#include <sys/lock.h>
 #include <sys/proc.h>
 #include <sys/malloc.h>
 #include <sys/msgbuf.h>
+#include <sys/mutex.h>
 #include <sys/vmmeter.h>
 #include <sys/mman.h>
 #include <sys/rwlock.h>
@@ -164,8 +166,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_page.h>
 #include <vm/vm_pageout.h>
 #include <vm/vm_extern.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
+
 #include <machine/md_var.h>
 #include <machine/cpu.h>
 #include <machine/cpufunc.h>
@@ -197,6 +198,7 @@ static pv_entry_t pmap_get_pv_entry(void
 
 static void		pmap_enter_locked(pmap_t, vm_offset_t, vm_page_t,
     vm_prot_t, boolean_t, int);
+static vm_paddr_t	pmap_extract_locked(pmap_t pmap, vm_offset_t va);
 static void		pmap_fix_cache(struct vm_page *, pmap_t, vm_offset_t);
 static void		pmap_alloc_l1(pmap_t);
 static void		pmap_free_l1(pmap_t);
@@ -2840,6 +2842,13 @@ pmap_kenter_user(vm_offset_t va, vm_padd
 	pmap_fault_fixup(pmap_kernel(), va, VM_PROT_READ|VM_PROT_WRITE, 1);
 }
 
+vm_paddr_t
+pmap_kextract(vm_offset_t va)
+{
+
+	return (pmap_extract_locked(kernel_pmap, va));
+}
+
 /*
  * remove a page from the kernel pagetables
  */
@@ -3644,22 +3653,34 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pm
  *		with the given map/virtual_address pair.
  */
 vm_paddr_t
-pmap_extract(pmap_t pm, vm_offset_t va)
+pmap_extract(pmap_t pmap, vm_offset_t va)
+{
+	vm_paddr_t pa;
+
+	PMAP_LOCK(pmap);
+	pa = pmap_extract_locked(pmap, va);
+	PMAP_UNLOCK(pmap);
+	return (pa);
+}
+
+static vm_paddr_t
+pmap_extract_locked(pmap_t pmap, vm_offset_t va)
 {
 	struct l2_dtable *l2;
 	pd_entry_t l1pd;
 	pt_entry_t *ptep, pte;
 	vm_paddr_t pa;
 	u_int l1idx;
-	l1idx = L1_IDX(va);
 
-	PMAP_LOCK(pm);
-	l1pd = pm->pm_l1->l1_kva[l1idx];
+	if (pmap != kernel_pmap)
+		PMAP_ASSERT_LOCKED(pmap);
+	l1idx = L1_IDX(va);
+	l1pd = pmap->pm_l1->l1_kva[l1idx];
 	if (l1pte_section_p(l1pd)) {
 		/*
-		 * These should only happen for pmap_kernel()
+		 * These should only happen for the kernel pmap.
 		 */
-		KASSERT(pm == pmap_kernel(), ("huh"));
+		KASSERT(pmap == kernel_pmap, ("unexpected section"));
 		/* XXX: what to do about the bits > 32 ? */
 		if (l1pd & L1_S_SUPERSEC)
 			pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET);
@@ -3671,34 +3692,22 @@ pmap_extract(pmap_t pm, vm_offset_t va)
 		 * descriptor as an indication that a mapping exists.
 		 * We have to look it up in the L2 dtable.
 		 */
-		l2 = pm->pm_l2[L2_IDX(l1idx)];
-
+		l2 = pmap->pm_l2[L2_IDX(l1idx)];
 		if (l2 == NULL ||
-		    (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) {
-			PMAP_UNLOCK(pm);
+		    (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL)
 			return (0);
-		}
-
-		ptep = &ptep[l2pte_index(va)];
-		pte = *ptep;
-
-		if (pte == 0) {
-			PMAP_UNLOCK(pm);
+		pte = ptep[l2pte_index(va)];
+		if (pte == 0)
 			return (0);
-		}
-
 		switch (pte & L2_TYPE_MASK) {
 		case L2_TYPE_L:
 			pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET);
 			break;
-
 		default:
 			pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET);
 			break;
 		}
 	}
-
-	PMAP_UNLOCK(pm);
 	return (pa);
 }
 

Modified: head/sys/arm/include/pmap.h
==============================================================================
--- head/sys/arm/include/pmap.h	Thu Sep 27 05:26:29 2012	(r240982)
+++ head/sys/arm/include/pmap.h	Thu Sep 27 05:39:42 2012	(r240983)
@@ -92,8 +92,7 @@ enum mem_type {
 
 #ifdef _KERNEL
 
-#define vtophys(va)	pmap_extract(pmap_kernel(), (vm_offset_t)(va))
-#define pmap_kextract(va)	pmap_extract(pmap_kernel(), (vm_offset_t)(va))
+#define vtophys(va)	pmap_kextract((vm_offset_t)(va))
 
 #endif
 
@@ -228,6 +227,7 @@ void	pmap_kenter(vm_offset_t va, vm_padd
 void	pmap_kenter_nocache(vm_offset_t va, vm_paddr_t pa);
 void	*pmap_kenter_temp(vm_paddr_t pa, int i);
 void 	pmap_kenter_user(vm_offset_t va, vm_paddr_t pa);
+vm_paddr_t pmap_kextract(vm_offset_t va);
 void	pmap_kremove(vm_offset_t);
 void	*pmap_mapdev(vm_offset_t, vm_size_t);
 void	pmap_unmapdev(vm_offset_t, vm_size_t);



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