Module Name:    src
Committed By:   rmind
Date:           Tue Mar  8 20:07:31 UTC 2011

Modified Files:
        src/sys/arch/x86/x86 [rmind-uvmplock]: pmap.c

Log Message:
- pmap_remove_ptes: simplify by removing the duplicate code and re-using
  equivalent functionality in pmap_remove_pte().
- pmap_remove_pte: fix assert to allow page owner lock to be unacquired
  if pmap is pmap_kernel(); relevant for UVM_KMF_PAGEABLE memory case.


To generate a diff of this commit:
cvs rdiff -u -r1.105.2.10 -r1.105.2.11 src/sys/arch/x86/x86/pmap.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x86/x86/pmap.c
diff -u src/sys/arch/x86/x86/pmap.c:1.105.2.10 src/sys/arch/x86/x86/pmap.c:1.105.2.11
--- src/sys/arch/x86/x86/pmap.c:1.105.2.10	Sat Mar  5 20:52:31 2011
+++ src/sys/arch/x86/x86/pmap.c	Tue Mar  8 20:07:30 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.105.2.10 2011/03/05 20:52:31 rmind Exp $	*/
+/*	$NetBSD: pmap.c,v 1.105.2.11 2011/03/08 20:07:30 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2010 The NetBSD Foundation, Inc.
@@ -171,7 +171,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.105.2.10 2011/03/05 20:52:31 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.105.2.11 2011/03/08 20:07:30 rmind Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -3121,9 +3121,7 @@
 pmap_remove_ptes(struct pmap *pmap, struct vm_page *ptp, vaddr_t ptpva,
 		 vaddr_t startva, vaddr_t endva, struct pv_entry **pv_tofree)
 {
-	struct pv_entry *pve;
-	pt_entry_t *pte = (pt_entry_t *) ptpva;
-	pt_entry_t opte;
+	pt_entry_t *pte = (pt_entry_t *)ptpva;
 
 	KASSERT(pmap == pmap_kernel() || mutex_owned(pmap->pm_lock));
 	KASSERT(kpreempt_disabled());
@@ -3136,74 +3134,16 @@
 	 * and the wire_count is greater than 1 (because we use the wire_count
 	 * to keep track of the number of real PTEs in the PTP).
 	 */
-
-	for (/*null*/; startva < endva && (ptp == NULL || ptp->wire_count > 1)
-			     ; pte++, startva += PAGE_SIZE) {
-		struct vm_page *pg;
-		struct pmap_page *pp;
-
-		if (!pmap_valid_entry(*pte))
-			continue;			/* VA not mapped */
-
-		/* atomically save the old PTE and zap! it */
-		opte = pmap_pte_testset(pte, 0);
-		if (!pmap_valid_entry(opte)) {
-			continue;
-		}
-
-		pmap_exec_account(pmap, startva, opte, 0);
-		pmap_stats_update_bypte(pmap, 0, opte);
-
-		if (ptp) {
-			ptp->wire_count--;		/* dropping a PTE */
-			/* Make sure that the PDE is flushed */
-			if (ptp->wire_count <= 1)
-				opte |= PG_U;
-		}
-
-		if ((opte & PG_U) != 0) {
-			pmap_tlb_shootdown(pmap, startva, opte,
-			    TLBSHOOT_REMOVE_PTES);
-		}
-
-		/*
-		 * if we are not on a pv_head list we are done.
-		 */
-
-		if ((opte & PG_PVLIST) == 0) {
-#if defined(DIAGNOSTIC) && !defined(DOM0OPS)
-			if (PHYS_TO_VM_PAGE(pmap_pte2pa(opte)) != NULL)
-				panic("pmap_remove_ptes: managed page without "
-				      "PG_PVLIST for %#" PRIxVADDR, startva);
-#endif
-			continue;
-		}
-
-		pg = PHYS_TO_VM_PAGE(pmap_pte2pa(opte));
-
-		KASSERTMSG(pg != NULL, ("pmap_remove_ptes: unmanaged page "
-		    "marked PG_PVLIST, va = %#" PRIxVADDR ", pa = %#" PRIxPADDR,
-		    startva, (paddr_t)pmap_pte2pa(opte)));
-
-		KASSERT(uvm_page_locked_p(pg));
-
-		/* sync R/M bits */
-		pp = VM_PAGE_TO_PP(pg);
-		pp->pp_attrs |= opte;
-		pve = pmap_remove_pv(pp, ptp, startva);
-
-		if (pve != NULL) {
-			pve->pve_next = *pv_tofree;
-			*pv_tofree = pve;
-		}
-
-		/* end of "for" loop: time for next pte */
+	while (startva < endva && (ptp == NULL || ptp->wire_count > 1)) {
+		(void)pmap_remove_pte(pmap, ptp, pte, startva, pv_tofree);
+		startva += PAGE_SIZE;
+		pte++;
 	}
 }
 
 
 /*
- * pmap_remove_pte: remove a single PTE from a PTP
+ * pmap_remove_pte: remove a single PTE from a PTP.
  *
  * => caller must hold pmap's lock
  * => PTP must be mapped into KVA
@@ -3211,23 +3151,24 @@
  * => returns true if we removed a mapping
  * => must be called with kernel preemption disabled
  */
-
 static bool
 pmap_remove_pte(struct pmap *pmap, struct vm_page *ptp, pt_entry_t *pte,
 		vaddr_t va, struct pv_entry **pv_tofree)
 {
-	pt_entry_t opte;
 	struct pv_entry *pve;
 	struct vm_page *pg;
 	struct pmap_page *pp;
+	pt_entry_t opte;
 
 	KASSERT(pmap == pmap_kernel() || mutex_owned(pmap->pm_lock));
-	KASSERT(pmap == pmap_kernel() || kpreempt_disabled());
+	KASSERT(kpreempt_disabled());
 
-	if (!pmap_valid_entry(*pte))
-		return(false);		/* VA not mapped */
+	if (!pmap_valid_entry(*pte)) {
+		/* VA not mapped. */
+		return false;
+	}
 
-	/* atomically save the old PTE and zap! it */
+	/* Atomically save the old PTE and zap it. */
 	opte = pmap_pte_testset(pte, 0);
 	if (!pmap_valid_entry(opte)) {
 		return false;
@@ -3237,10 +3178,13 @@
 	pmap_stats_update_bypte(pmap, 0, opte);
 
 	if (ptp) {
-		ptp->wire_count--;		/* dropping a PTE */
-		/* Make sure that the PDE is flushed */
-		if (ptp->wire_count <= 1)
+		/*
+		 * Dropping a PTE.  Make sure that the PDE is flushed.
+		 */
+		ptp->wire_count--;
+		if (ptp->wire_count <= 1) {
 			opte |= PG_U;
+		}
 	}
 
 	if ((opte & PG_U) != 0) {
@@ -3248,16 +3192,15 @@
 	}
 
 	/*
-	 * if we are not on a pv_head list we are done.
+	 * If we are not on a pv_head list - we are done.
 	 */
-
 	if ((opte & PG_PVLIST) == 0) {
 #if defined(DIAGNOSTIC) && !defined(DOM0OPS)
 		if (PHYS_TO_VM_PAGE(pmap_pte2pa(opte)) != NULL)
 			panic("pmap_remove_pte: managed page without "
 			      "PG_PVLIST for %#" PRIxVADDR, va);
 #endif
-		return(true);
+		return true;
 	}
 
 	pg = PHYS_TO_VM_PAGE(pmap_pte2pa(opte));
@@ -3266,9 +3209,9 @@
 	    "PG_PVLIST, va = %#" PRIxVADDR ", pa = %#" PRIxPADDR,
 	    va, (paddr_t)pmap_pte2pa(opte)));
 
-	KASSERT(uvm_page_locked_p(pg));
+	KASSERT(pmap == pmap_kernel() || uvm_page_locked_p(pg));
 
-	/* sync R/M bits */
+	/* Sync R/M bits. */
 	pp = VM_PAGE_TO_PP(pg);
 	pp->pp_attrs |= opte;
 	pve = pmap_remove_pv(pp, ptp, va);
@@ -3277,8 +3220,7 @@
 		pve->pve_next = *pv_tofree;
 		*pv_tofree = pve;
 	}
-
-	return(true);
+	return true;
 }
 
 /*
@@ -3314,20 +3256,17 @@
 			/* PA of the PTP */
 			ptppa = pmap_pte2pa(pde);
 
-			/* get PTP if non-kernel mapping */
-			if (pmap == pmap_kernel()) {
-				/* we never free kernel PTPs */
-				ptp = NULL;
-			} else {
+			/* Get PTP if non-kernel mapping. */
+			if (pmap != pmap_kernel()) {
 				ptp = pmap_find_ptp(pmap, va, ptppa, 1);
-#ifdef DIAGNOSTIC
-				if (ptp == NULL)
-					panic("pmap_remove: unmanaged "
-					      "PTP detected");
-#endif
+				KASSERTMSG(ptp != NULL,
+				    ("pmap_remove: unmanaged PTP detected")
+				);
+			} else {
+				/* Never free kernel PTPs. */
+				ptp = NULL;
 			}
 
-			/* do it! */
 			result = pmap_remove_pte(pmap, ptp,
 			    &ptes[pl1_i(va)], va, &pv_tofree);
 
@@ -3379,18 +3318,17 @@
 		/* PA of the PTP */
 		ptppa = pmap_pte2pa(pde);
 
-		/* get PTP if non-kernel mapping */
-		if (pmap == pmap_kernel()) {
-			/* we never free kernel PTPs */
-			ptp = NULL;
-		} else {
+		/* Get PTP if non-kernel mapping. */
+		if (pmap != pmap_kernel()) {
 			ptp = pmap_find_ptp(pmap, va, ptppa, 1);
-#ifdef DIAGNOSTIC
-			if (ptp == NULL)
-				panic("pmap_remove: unmanaged PTP "
-				      "detected");
-#endif
+			KASSERTMSG(ptp != NULL,
+			    ("pmap_remove: unmanaged PTP detected")
+			);
+		} else {
+			/* Never free kernel PTPs. */
+			ptp = NULL;
 		}
+
 		pmap_remove_ptes(pmap, ptp, (vaddr_t)&ptes[pl1_i(va)], va,
 		    blkendva, &pv_tofree);
 

Reply via email to