Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Apr 2012 17:58:30 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r234576 - in head/sys: powerpc/aim vm
Message-ID:  <201204221758.q3MHwUXM050602@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Sun Apr 22 17:58:30 2012
New Revision: 234576
URL: http://svn.freebsd.org/changeset/base/234576

Log:
  Avoid a lock order reversal in pmap_extract_and_hold() from relocking
  the page. This PMAP requires an additional lock besides the PMAP lock
  in pmap_extract_and_hold(), which vm_page_pa_tryrelock() did not release.
  
  Suggested by:	kib
  MFC after:	4 days

Modified:
  head/sys/powerpc/aim/mmu_oea64.c
  head/sys/vm/vm_page.c

Modified: head/sys/powerpc/aim/mmu_oea64.c
==============================================================================
--- head/sys/powerpc/aim/mmu_oea64.c	Sun Apr 22 17:14:11 2012	(r234575)
+++ head/sys/powerpc/aim/mmu_oea64.c	Sun Apr 22 17:58:30 2012	(r234576)
@@ -1333,6 +1333,37 @@ moea64_extract(mmu_t mmu, pmap_t pm, vm_
  * pmap and virtual address pair if that mapping permits the given
  * protection.
  */
+
+extern int pa_tryrelock_restart;
+
+static int
+vm_page_pa_tryrelock_moea64(pmap_t pmap, vm_paddr_t pa, vm_paddr_t *locked)
+{
+	/*
+	 * This is a duplicate of vm_page_pa_tryrelock(), but with proper
+	 * handling of the table lock
+	 */
+	vm_paddr_t lockpa;
+
+	lockpa = *locked;
+	*locked = pa;
+	if (lockpa) {
+		PA_LOCK_ASSERT(lockpa, MA_OWNED);
+		if (PA_LOCKPTR(pa) == PA_LOCKPTR(lockpa))
+			return (0);
+		PA_UNLOCK(lockpa);
+	}
+	if (PA_TRYLOCK(pa))
+		return (0);
+	UNLOCK_TABLE_RD();
+	PMAP_UNLOCK(pmap);
+	atomic_add_int(&pa_tryrelock_restart, 1);
+	PA_LOCK(pa);
+	LOCK_TABLE_RD();
+	PMAP_LOCK(pmap);
+	return (EAGAIN);
+}
+
 vm_page_t
 moea64_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_prot_t prot)
 {
@@ -1349,7 +1380,7 @@ retry:
 	if (pvo != NULL && (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) &&
 	    ((pvo->pvo_pte.lpte.pte_lo & LPTE_PP) == LPTE_RW ||
 	     (prot & VM_PROT_WRITE) == 0)) {
-		if (vm_page_pa_tryrelock(pmap,
+		if (vm_page_pa_tryrelock_moea64(pmap,
 			pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN, &pa))
 			goto retry;
 		m = PHYS_TO_VM_PAGE(pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN);

Modified: head/sys/vm/vm_page.c
==============================================================================
--- head/sys/vm/vm_page.c	Sun Apr 22 17:14:11 2012	(r234575)
+++ head/sys/vm/vm_page.c	Sun Apr 22 17:58:30 2012	(r234576)
@@ -131,7 +131,7 @@ TUNABLE_INT("vm.boot_pages", &boot_pages
 SYSCTL_INT(_vm, OID_AUTO, boot_pages, CTLFLAG_RD, &boot_pages, 0,
 	"number of pages allocated for bootstrapping the VM system");
 
-static int pa_tryrelock_restart;
+int pa_tryrelock_restart;
 SYSCTL_INT(_vm, OID_AUTO, tryrelock_restart, CTLFLAG_RD,
     &pa_tryrelock_restart, 0, "Number of tryrelock restarts");
 



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