Module Name:    src
Committed By:   ad
Date:           Sun Apr  5 00:21:12 UTC 2020

Modified Files:
        src/sys/arch/x86/include: pmap.h
        src/sys/arch/x86/x86: pmap.c

Log Message:
Allocate PV entries in PAGE_SIZE chunks, and cache partially allocated PV
pages with the pmap.  Worth about 2-3% sys time on build.sh for me.


To generate a diff of this commit:
cvs rdiff -u -r1.116 -r1.117 src/sys/arch/x86/include/pmap.h
cvs rdiff -u -r1.380 -r1.381 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/include/pmap.h
diff -u src/sys/arch/x86/include/pmap.h:1.116 src/sys/arch/x86/include/pmap.h:1.117
--- src/sys/arch/x86/include/pmap.h:1.116	Sun Mar 22 00:16:16 2020
+++ src/sys/arch/x86/include/pmap.h	Sun Apr  5 00:21:11 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.h,v 1.116 2020/03/22 00:16:16 ad Exp $	*/
+/*	$NetBSD: pmap.h,v 1.117 2020/04/05 00:21:11 ad Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -259,6 +259,9 @@ struct pmap {
 					/* pointer to a PTP in our pmap */
 	struct pmap_statistics pm_stats;  /* pmap stats */
 	struct pv_entry *pm_pve;	/* spare pv_entry */
+	LIST_HEAD(, pv_page) pm_pvp_part;
+	LIST_HEAD(, pv_page) pm_pvp_empty;
+	LIST_HEAD(, pv_page) pm_pvp_full;
 
 #if !defined(__x86_64__)
 	vaddr_t pm_hiexec;		/* highest executable mapping */

Index: src/sys/arch/x86/x86/pmap.c
diff -u src/sys/arch/x86/x86/pmap.c:1.380 src/sys/arch/x86/x86/pmap.c:1.381
--- src/sys/arch/x86/x86/pmap.c:1.380	Sun Mar 22 00:16:16 2020
+++ src/sys/arch/x86/x86/pmap.c	Sun Apr  5 00:21:11 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.380 2020/03/22 00:16:16 ad Exp $	*/
+/*	$NetBSD: pmap.c,v 1.381 2020/04/05 00:21:11 ad Exp $	*/
 
 /*
  * Copyright (c) 2008, 2010, 2016, 2017, 2019, 2020 The NetBSD Foundation, Inc.
@@ -130,7 +130,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.380 2020/03/22 00:16:16 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.381 2020/04/05 00:21:11 ad Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -371,9 +371,9 @@ static int  pmap_ctor(void *, void *, in
 static void pmap_dtor(void *, void *);
 
 /*
- * pv_entry cache
+ * pv_page cache
  */
-static struct pool_cache pmap_pv_cache;
+static struct pool_cache pmap_pvp_cache;
 
 #ifdef __HAVE_DIRECT_MAP
 vaddr_t pmap_direct_base __read_mostly;
@@ -430,6 +430,20 @@ struct pmap_ptparray {
 };
 
 /*
+ * PV entries are allocated in page-sized chunks and cached per-pmap to
+ * avoid intense pressure on memory allocators.
+ */
+
+struct pv_page {
+	LIST_HEAD(, pv_entry)	pvp_pves;
+	LIST_ENTRY(pv_page)	pvp_list;
+	long			pvp_nfree;
+	struct pmap		*pvp_pmap;
+};
+
+#define	PVE_PER_PVP	((PAGE_SIZE / sizeof(struct pv_entry)) - 1)
+
+/*
  * PV tree prototypes
  */
 
@@ -472,9 +486,13 @@ static void pmap_freepage(struct pmap *,
 static void pmap_free_ptp(struct pmap *, struct vm_page *, vaddr_t,
     pt_entry_t *, pd_entry_t * const *);
 static bool pmap_remove_pte(struct pmap *, struct vm_page *, pt_entry_t *,
-    vaddr_t, struct pv_entry **);
+    vaddr_t);
 static void pmap_remove_ptes(struct pmap *, struct vm_page *, vaddr_t, vaddr_t,
-    vaddr_t, struct pv_entry **);
+    vaddr_t);
+static int pmap_pvp_ctor(void *, void *, int);
+static void pmap_pvp_dtor(void *, void *);
+static struct pv_entry *pmap_alloc_pv(struct pmap *);
+static void pmap_free_pv(struct pmap *, struct pv_entry *);
 
 static void pmap_alloc_level(struct pmap *, vaddr_t, long *);
 
@@ -1837,14 +1855,9 @@ pmap_init(void)
 	pool_init(&pmap_pdp_pool, PAGE_SIZE, 0, 0, flags,
 	    "pdppl", NULL, IPL_NONE);
 #endif
-	pool_cache_bootstrap(&pmap_pv_cache, sizeof(struct pv_entry),
-#ifdef _LP64
-	    coherency_unit,
-#else
-	    coherency_unit / 2,
-#endif
-	     0, PR_LARGECACHE, "pvpl", &pool_allocator_kmem,
-	    IPL_NONE, NULL, NULL, NULL);
+	pool_cache_bootstrap(&pmap_pvp_cache, PAGE_SIZE, PAGE_SIZE,
+	     0, 0, "pvpage", &pool_allocator_kmem,
+	    IPL_NONE, pmap_pvp_ctor, pmap_pvp_dtor, NULL);
 
 	pmap_tlb_init();
 
@@ -1947,23 +1960,109 @@ pmap_vpage_cpu_init(struct cpu_info *ci)
  */
 
 /*
- * pmap_free_pvs: free a linked list of pv entries.  the pv entries have
- * been removed from their respective pages, but are still entered into the
- * map and we must undo that.
- *
- * => must be called with pmap locked.
+ * pmap_pvp_dtor: pool_cache constructor for PV pages.
+ */
+static int
+pmap_pvp_ctor(void *arg, void *obj, int flags)
+{
+	struct pv_page *pvp = (struct pv_page *)obj;
+	struct pv_entry *pve = (struct pv_entry *)obj + 1;
+	struct pv_entry *maxpve = pve + PVE_PER_PVP;
+
+	KASSERT(sizeof(struct pv_page) <= sizeof(struct pv_entry));
+	KASSERT(trunc_page((vaddr_t)obj) == (vaddr_t)obj);
+
+	LIST_INIT(&pvp->pvp_pves);
+	pvp->pvp_nfree = PVE_PER_PVP;
+	pvp->pvp_pmap = NULL;
+
+	for (; pve < maxpve; pve++) {
+		LIST_INSERT_HEAD(&pvp->pvp_pves, pve, pve_list);
+	}
+
+	return 0;
+}
+
+/*
+ * pmap_pvp_dtor: pool_cache destructor for PV pages.
  */
 static void
-pmap_free_pvs(struct pmap *pmap, struct pv_entry *pve)
+pmap_pvp_dtor(void *arg, void *obj)
+{
+	struct pv_page *pvp __diagused = obj;
+
+	KASSERT(pvp->pvp_pmap == NULL);
+	KASSERT(pvp->pvp_nfree == PVE_PER_PVP);
+}
+
+/*
+ * pmap_alloc_pv: allocate a PV entry (likely cached with pmap).
+ */
+static struct pv_entry *
+pmap_alloc_pv(struct pmap *pmap)
 {
-	struct pv_entry *next;
+	struct pv_entry *pve;
+	struct pv_page *pvp;
 
 	KASSERT(mutex_owned(&pmap->pm_lock));
 
-	for ( /* null */ ; pve != NULL ; pve = next) {
-		next = pve->pve_next;
-		pool_cache_put(&pmap_pv_cache, pve);
+	if (__predict_false((pvp = LIST_FIRST(&pmap->pm_pvp_part)) == NULL)) {
+		if ((pvp = LIST_FIRST(&pmap->pm_pvp_full)) != NULL) {
+			LIST_REMOVE(pvp, pvp_list);
+		} else {
+			pvp = pool_cache_get(&pmap_pvp_cache, PR_NOWAIT);
+		}
+		if (__predict_false(pvp == NULL)) {
+			return NULL;
+		}
+		/* full -> part */
+		LIST_INSERT_HEAD(&pmap->pm_pvp_part, pvp, pvp_list);
+		pvp->pvp_pmap = pmap;
+	}
+
+	KASSERT(pvp->pvp_pmap == pmap);
+	KASSERT(pvp->pvp_nfree > 0);
+
+	pve = LIST_FIRST(&pvp->pvp_pves);
+	LIST_REMOVE(pve, pve_list);
+	pvp->pvp_nfree--;
+
+	if (__predict_false(pvp->pvp_nfree == 0)) {
+		/* part -> empty */
+		KASSERT(LIST_EMPTY(&pvp->pvp_pves));
+		LIST_REMOVE(pvp, pvp_list);
+		LIST_INSERT_HEAD(&pmap->pm_pvp_empty, pvp, pvp_list);
+	} else {
+		KASSERT(!LIST_EMPTY(&pvp->pvp_pves));
 	}
+
+	return pve;
+}
+
+/*
+ * pmap_free_pv: delayed free of a PV entry.
+ */
+static void
+pmap_free_pv(struct pmap *pmap, struct pv_entry *pve)
+{
+	struct pv_page *pvp = (struct pv_page *)trunc_page((vaddr_t)pve);
+
+	KASSERT(mutex_owned(&pmap->pm_lock));
+	KASSERT(pvp->pvp_pmap == pmap);
+	KASSERT(pvp->pvp_nfree >= 0);
+
+	LIST_INSERT_HEAD(&pvp->pvp_pves, pve, pve_list);
+	pvp->pvp_nfree++;
+
+	if (__predict_false(pvp->pvp_nfree == 1)) {
+		/* empty -> part */
+		LIST_REMOVE(pvp, pvp_list);
+		LIST_INSERT_HEAD(&pmap->pm_pvp_part, pvp, pvp_list);
+	} else if (__predict_false(pvp->pvp_nfree == PVE_PER_PVP)) {
+		/* part -> full */
+		LIST_REMOVE(pvp, pvp_list);
+		LIST_INSERT_HEAD(&pmap->pm_pvp_full, pvp, pvp_list);
+	} 
 }
 
 /*
@@ -2129,7 +2228,7 @@ pmap_enter_pv(struct pmap *pmap, struct 
 	 * case it's needed; won't know for sure until the lock is taken.
 	 */
 	if (pmap->pm_pve == NULL) {
-		pmap->pm_pve = pool_cache_get(&pmap_pv_cache, PR_NOWAIT);
+		pmap->pm_pve = pmap_alloc_pv(pmap);
 	}
 
 	error = 0;
@@ -2171,7 +2270,7 @@ pmap_enter_pv(struct pmap *pmap, struct 
  * pmap_remove_pv: try to remove a mapping from a pv_list
  *
  * => pmap must be locked
- * => removes dynamic entries from tree
+ * => removes dynamic entries from tree and frees them
  * => caller should adjust ptp's wire_count and free PTP if needed
  */
 static void
@@ -2213,6 +2312,7 @@ pmap_remove_pv(struct pmap *pmap, struct
 #ifdef DIAGNOSTIC
 		memset(pve, 0, sizeof(*pve));
 #endif
+		pmap_free_pv(pmap, pve);
 	}
 
 	KASSERT(pmap_treelookup_pv(pmap, ptp, tree, va) == NULL);
@@ -2670,6 +2770,9 @@ pmap_ctor(void *arg, void *obj, int flag
 #endif
 	LIST_INIT(&pmap->pm_gc_ptp);
 	pmap->pm_pve = NULL;
+	LIST_INIT(&pmap->pm_pvp_full);
+	LIST_INIT(&pmap->pm_pvp_part);
+	LIST_INIT(&pmap->pm_pvp_empty);
 
 	/* allocate and init PDP */
 	pmap->pm_pdir = pool_get(&pmap_pdp_pool, PR_WAITOK);
@@ -2702,10 +2805,6 @@ pmap_dtor(void *arg, void *obj)
 {
 	struct pmap *pmap = obj;
 
-	if (pmap->pm_pve != NULL) {
-		pool_cache_put(&pmap_pv_cache, pmap->pm_pve);
-	}
-
 	mutex_enter(&pmaps_lock);
 	LIST_REMOVE(pmap, pm_list);
 	mutex_exit(&pmaps_lock);
@@ -2832,13 +2931,16 @@ pmap_destroy(struct pmap *pmap)
 	pmap_check_inuse(pmap);
 
 	/*
-	 * XXX handle deferred PTP page free for EPT.  ordinarily this is
-	 * taken care of by pmap_remove_all().  once shared with EPT this
-	 * can go away.
+	 * handle any deferred frees.
 	 */
-	if (__predict_false(!LIST_EMPTY(&pmap->pm_gc_ptp))) {
-		pmap_update(pmap);
+
+	if (pmap->pm_pve != NULL) {
+		mutex_enter(&pmap->pm_lock);
+		pmap_free_pv(pmap, pmap->pm_pve);
+		mutex_exit(&pmap->pm_lock);
+		pmap->pm_pve = NULL;
 	}
+	pmap_update(pmap);
 
 	/*
 	 * Reference count is zero, free pmap resources and then free pmap.
@@ -2874,6 +2976,10 @@ pmap_destroy(struct pmap *pmap)
 	kcpuset_zero(pmap->pm_xen_ptp_cpus);
 #endif
 
+	KASSERT(LIST_EMPTY(&pmap->pm_pvp_full));
+	KASSERT(LIST_EMPTY(&pmap->pm_pvp_part));
+	KASSERT(LIST_EMPTY(&pmap->pm_pvp_empty));
+
 	pmap_check_ptps(pmap);
 	if (__predict_false(pmap->pm_enter != NULL)) {
 		/* XXX make this a different cache */
@@ -2893,7 +2999,7 @@ pmap_destroy(struct pmap *pmap)
  */
 static void
 pmap_zap_ptp(struct pmap *pmap, struct vm_page *ptp, pt_entry_t *pte,
-    vaddr_t startva, vaddr_t blkendva, struct pv_entry **pv_tofree)
+    vaddr_t startva, vaddr_t blkendva)
 {
 #ifndef XEN
 	struct pv_entry *pve;
@@ -2968,8 +3074,12 @@ pmap_zap_ptp(struct pmap *pmap, struct v
 			pp->pp_attrs |= oattrs;
 			LIST_REMOVE(pve, pve_list);
 			mutex_spin_exit(&pp->pp_lock);
-			pve->pve_next = *pv_tofree;
-			*pv_tofree = pve;
+
+			/*
+			 * pve won't be touched again until pmap_update(),
+			 * so it's still safe to traverse the tree.
+			 */
+			pmap_free_pv(pmap, pve);
 			pve = RB_TREE_NEXT(tree, pve);
 			continue;
 		}
@@ -3006,8 +3116,7 @@ pmap_zap_ptp(struct pmap *pmap, struct v
 	 * XXXAD For XEN, it's not clear to me that we can do this, because
 	 * I guess the hypervisor keeps track of PTEs too.
 	 */
-	pmap_remove_ptes(pmap, ptp, (vaddr_t)pte, startva, blkendva,
-	    pv_tofree);
+	pmap_remove_ptes(pmap, ptp, (vaddr_t)pte, startva, blkendva);
 #endif	/* !XEN */
 }
 
@@ -3029,7 +3138,6 @@ pmap_remove_all(struct pmap *pmap)
 	pt_entry_t *ptes;
 	pd_entry_t pde __diagused;
 	pd_entry_t * const *pdes;
-	struct pv_entry *pv_tofree;
 	int lvl __diagused, i, n;
 
 	/* XXX Can't handle EPT just yet. */
@@ -3049,7 +3157,6 @@ pmap_remove_all(struct pmap *pmap)
 
 		/* Remove all mappings in the set of PTPs. */
 		pmap_map_ptes(pmap, &pmap2, &ptes, &pdes);
-		pv_tofree = NULL;
 		for (i = 0; i < n; i++) {
 			if (ptps[i]->wire_count == 0) {
 				/* It's dead: pmap_update() will expunge. */
@@ -3067,14 +3174,13 @@ pmap_remove_all(struct pmap *pmap)
 
 			/* Zap! */
 			pmap_zap_ptp(pmap, ptps[i], &ptes[pl1_i(va)], va,
-			    blkendva, &pv_tofree);
+			    blkendva);
 
 			/* PTP should now be unused - free it. */
 			KASSERT(ptps[i]->wire_count == 1);
 			pmap_free_ptp(pmap, ptps[i], va, ptes, pdes);
 		}
 		pmap_unmap_ptes(pmap, pmap2);
-		pmap_free_pvs(pmap, pv_tofree);
 		pmap_tlb_shootdown(pmap, -1L, 0, TLBSHOOT_REMOVE_ALL);
 		mutex_exit(&pmap->pm_lock);
 
@@ -3893,7 +3999,7 @@ pmap_unmap_pte(void)
  */
 static void
 pmap_remove_ptes(struct pmap *pmap, struct vm_page *ptp, vaddr_t ptpva,
-    vaddr_t startva, vaddr_t endva, struct pv_entry **pv_tofree)
+    vaddr_t startva, vaddr_t endva)
 {
 	pt_entry_t *pte = (pt_entry_t *)ptpva;
 
@@ -3915,7 +4021,7 @@ pmap_remove_ptes(struct pmap *pmap, stru
 	 * to keep track of the number of real PTEs in the PTP).
 	 */
 	while (startva < endva && (ptp == NULL || ptp->wire_count > 1)) {
-		(void)pmap_remove_pte(pmap, ptp, pte, startva, pv_tofree);
+		(void)pmap_remove_pte(pmap, ptp, pte, startva);
 		startva += PAGE_SIZE;
 		pte++;
 	}
@@ -3932,7 +4038,7 @@ pmap_remove_ptes(struct pmap *pmap, stru
  */
 static bool
 pmap_remove_pte(struct pmap *pmap, struct vm_page *ptp, pt_entry_t *pte,
-    vaddr_t va, struct pv_entry **pv_tofree)
+    vaddr_t va)
 {
 	struct pv_entry *pve;
 	struct vm_page *pg;
@@ -3997,11 +4103,6 @@ pmap_remove_pte(struct pmap *pmap, struc
 	/* Sync R/M bits. */
 	pve = pmap_lookup_pv(pmap, ptp, pp, va);
 	pmap_remove_pv(pmap, pp, ptp, va, pve, pmap_pte_to_pp_attrs(opte));
-
-	if (pve) {
-		pve->pve_next = *pv_tofree;
-		*pv_tofree = pve;
-	}
 	return true;
 }
 
@@ -4016,7 +4117,6 @@ pmap_remove(struct pmap *pmap, vaddr_t s
 	pt_entry_t *ptes;
 	pd_entry_t pde;
 	pd_entry_t * const *pdes;
-	struct pv_entry *pv_tofree = NULL;
 	bool result;
 	vaddr_t blkendva, va = sva;
 	struct vm_page *ptp;
@@ -4050,7 +4150,7 @@ pmap_remove(struct pmap *pmap, vaddr_t s
 			}
 
 			result = pmap_remove_pte(pmap, ptp,
-			    &ptes[pl1_i(va)], va, &pv_tofree);
+			    &ptes[pl1_i(va)], va);
 
 			/*
 			 * if mapping removed and the PTP is no longer
@@ -4084,7 +4184,7 @@ pmap_remove(struct pmap *pmap, vaddr_t s
 		}
 
 		pmap_remove_ptes(pmap, ptp, (vaddr_t)&ptes[pl1_i(va)], va,
-		    blkendva, &pv_tofree);
+		    blkendva);
 
 		/* If PTP is no longer being used, free it. */
 		if (ptp && ptp->wire_count <= 1) {
@@ -4092,13 +4192,6 @@ pmap_remove(struct pmap *pmap, vaddr_t s
 		}
 	}
 	pmap_unmap_ptes(pmap, pmap2);
-	/*
-	 * Now safe to free, as we no longer have the PTEs mapped and can
-	 * block again.
-	 */
-	if (pv_tofree != NULL) {
-		pmap_free_pvs(pmap, pv_tofree);
-	}
 	mutex_exit(&pmap->pm_lock);
 }
 
@@ -4326,10 +4419,6 @@ pmap_pp_remove(struct pmap_page *pp, pad
 			KASSERT(pmap == pmap_kernel());
 			pmap_stats_update_bypte(pmap, 0, opte);
 		}
-		if (pve != NULL) {
-			pve->pve_next = NULL;
-			pmap_free_pvs(pmap, pve);
-		}
 		pmap_tlb_shootnow();
 		mutex_exit(&pmap->pm_lock);
 		if (ptp != NULL) {
@@ -4939,13 +5028,6 @@ pmap_enter_ma(struct pmap *pmap, vaddr_t
 
 		pmap_remove_pv(pmap, old_pp, ptp, va, old_pve,
 		    pmap_pte_to_pp_attrs(opte));
-		if (old_pve != NULL) {
-			if (pmap->pm_pve == NULL) {
-				pmap->pm_pve = old_pve;
-			} else {
-				pool_cache_put(&pmap_pv_cache, old_pve);
-			}
-		}
 	} else {
 		KASSERT(old_pve == NULL);
 		KASSERT(pmap_treelookup_pv(pmap, ptp, tree, va) == NULL);
@@ -5286,6 +5368,7 @@ pmap_dump(struct pmap *pmap, vaddr_t sva
 void
 pmap_update(struct pmap *pmap)
 {
+	struct pv_page *pvp;
 	struct pmap_page *pp;
 	struct vm_page *ptp;
 
@@ -5302,7 +5385,8 @@ pmap_update(struct pmap *pmap)
 	 * is an unlocked check, but is safe as we're only interested in
 	 * work done in this LWP - we won't get a false negative.
 	 */
-	if (__predict_false(!LIST_EMPTY(&pmap->pm_gc_ptp))) {
+	if (__predict_false(!LIST_EMPTY(&pmap->pm_gc_ptp) ||
+	    !LIST_EMPTY(&pmap->pm_pvp_full))) {
 		mutex_enter(&pmap->pm_lock);
 		while ((ptp = LIST_FIRST(&pmap->pm_gc_ptp)) != NULL) {
 			KASSERT(ptp->wire_count == 0);
@@ -5330,6 +5414,13 @@ pmap_update(struct pmap *pmap)
 			 */
 			uvm_pagefree(ptp);
 		}
+		while ((pvp = LIST_FIRST(&pmap->pm_pvp_full)) != NULL) {
+			LIST_REMOVE(pvp, pvp_list);
+			KASSERT(pvp->pvp_pmap == pmap);
+			KASSERT(pvp->pvp_nfree == PVE_PER_PVP);
+			pvp->pvp_pmap = NULL;
+			pool_cache_put(&pmap_pvp_cache, pvp);
+		}
 		mutex_exit(&pmap->pm_lock);
 	}
 }
@@ -5839,13 +5930,6 @@ pmap_ept_enter(struct pmap *pmap, vaddr_
 
 		pmap_remove_pv(pmap, old_pp, ptp, va, old_pve,
 		    pmap_ept_to_pp_attrs(opte));
-		if (old_pve != NULL) {
-			if (pmap->pm_pve == NULL) {
-				pmap->pm_pve = old_pve;
-			} else {
-				pool_cache_put(&pmap_pv_cache, old_pve);
-			}
-		}
 	} else {
 		KASSERT(old_pve == NULL);
 		KASSERT(pmap_treelookup_pv(pmap, ptp, tree, va) == NULL);
@@ -5947,7 +6031,7 @@ pmap_ept_extract(struct pmap *pmap, vadd
 
 static bool
 pmap_ept_remove_pte(struct pmap *pmap, struct vm_page *ptp, pt_entry_t *pte,
-    vaddr_t va, struct pv_entry **pv_tofree)
+    vaddr_t va)
 {
 	struct pv_entry *pve;
 	struct vm_page *pg;
@@ -6016,17 +6100,12 @@ pmap_ept_remove_pte(struct pmap *pmap, s
 	/* Sync R/M bits. */
 	pve = pmap_lookup_pv(pmap, ptp, pp, va);
 	pmap_remove_pv(pmap, pp, ptp, va, pve, pmap_ept_to_pp_attrs(opte));
-
-	if (pve) {
-		pve->pve_next = *pv_tofree;
-		*pv_tofree = pve;
-	}
 	return true;
 }
 
 static void
 pmap_ept_remove_ptes(struct pmap *pmap, struct vm_page *ptp, vaddr_t ptpva,
-    vaddr_t startva, vaddr_t endva, struct pv_entry **pv_tofree)
+    vaddr_t startva, vaddr_t endva)
 {
 	pt_entry_t *pte = (pt_entry_t *)ptpva;
 
@@ -6049,7 +6128,7 @@ pmap_ept_remove_ptes(struct pmap *pmap, 
 	 * to keep track of the number of real PTEs in the PTP).
 	 */
 	while (startva < endva && (ptp == NULL || ptp->wire_count > 1)) {
-		(void)pmap_ept_remove_pte(pmap, ptp, pte, startva, pv_tofree);
+		(void)pmap_ept_remove_pte(pmap, ptp, pte, startva);
 		startva += PAGE_SIZE;
 		pte++;
 	}
@@ -6058,7 +6137,6 @@ pmap_ept_remove_ptes(struct pmap *pmap, 
 static void
 pmap_ept_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva)
 {
-	struct pv_entry *pv_tofree = NULL;
 	pt_entry_t *ptes;
 	pd_entry_t pde;
 	paddr_t ptppa;
@@ -6093,7 +6171,7 @@ pmap_ept_remove(struct pmap *pmap, vaddr
 		ptes = (pt_entry_t *)PMAP_DIRECT_MAP(ptppa);
 
 		pmap_ept_remove_ptes(pmap, ptp, (vaddr_t)&ptes[pl1_pi(va)], va,
-		    blkendva, &pv_tofree);
+		    blkendva);
 
 		/* If PTP is no longer being used, free it. */
 		if (ptp && ptp->wire_count <= 1) {
@@ -6102,9 +6180,6 @@ pmap_ept_remove(struct pmap *pmap, vaddr
 	}
 
 	kpreempt_enable();
-	if (pv_tofree != NULL) {
-		pmap_free_pvs(pmap, pv_tofree);
-	}
 	mutex_exit(&pmap->pm_lock);
 }
 

Reply via email to