Module Name:    src
Committed By:   ad
Date:           Sun Mar 15 15:58:24 UTC 2020

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

Log Message:
- pmap_enter(): Remove cosmetic differences between the EPT & native cases.
  Remove old code to free PVEs that should not be there that caused panics
  (merge error moving between source trees on my part).

- pmap_destroy(): pmap_remove_all() doesn't work for EPT yet, so need to catch
  up on deferred PTP frees manually in the EPT case.

- pp_embedded: Remove it.  It's one more variable to go wrong and another
  store to be made.  Just check for non-zero PTP pointer & non-zero VA
  instead.


To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/x86/include/pmap_pv.h
cvs rdiff -u -r1.368 -r1.369 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_pv.h
diff -u src/sys/arch/x86/include/pmap_pv.h:1.14 src/sys/arch/x86/include/pmap_pv.h:1.15
--- src/sys/arch/x86/include/pmap_pv.h:1.14	Sat Mar 14 18:24:10 2020
+++ src/sys/arch/x86/include/pmap_pv.h	Sun Mar 15 15:58:24 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap_pv.h,v 1.14 2020/03/14 18:24:10 ad Exp $	*/
+/*	$NetBSD: pmap_pv.h,v 1.15 2020/03/15 15:58:24 ad Exp $	*/
 
 /*-
  * Copyright (c)2008 YAMAMOTO Takashi,
@@ -79,7 +79,6 @@ struct pmap_page {
 		struct {
 			struct pv_pte pte;
 			LIST_HEAD(, pv_entry) pvlist;
-			uint8_t embedded;
 			uint8_t attrs;
 		} s;
 	} pp_u;
@@ -88,7 +87,6 @@ struct pmap_page {
 #define	pp_link		pp_u.link
 #define	pp_pte		pp_u.s.pte
 #define pp_pvlist	pp_u.s.pvlist
-#define	pp_embedded	pp_u.s.embedded
 #define	pp_attrs	pp_u.s.attrs
 };
 

Index: src/sys/arch/x86/x86/pmap.c
diff -u src/sys/arch/x86/x86/pmap.c:1.368 src/sys/arch/x86/x86/pmap.c:1.369
--- src/sys/arch/x86/x86/pmap.c:1.368	Sun Mar 15 15:14:22 2020
+++ src/sys/arch/x86/x86/pmap.c	Sun Mar 15 15:58:24 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.368 2020/03/15 15:14:22 ad Exp $	*/
+/*	$NetBSD: pmap.c,v 1.369 2020/03/15 15:58:24 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.368 2020/03/15 15:14:22 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.369 2020/03/15 15:58:24 ad Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -539,6 +539,17 @@ pvpte_to_pve(struct pv_pte *pvpte)
 }
 
 /*
+ * Return true if the pmap page has an embedded PV entry.
+ */
+static inline bool
+pv_pte_embedded(struct pmap_page *pp)
+{
+
+	KASSERT(mutex_owned(&pp->pp_lock));
+	return (bool)((vaddr_t)pp->pp_pte.pte_ptp | pp->pp_pte.pte_va);
+}
+
+/*
  * pv_pte_first, pv_pte_next: PV list iterator.
  */
 static struct pv_pte *
@@ -546,7 +557,7 @@ pv_pte_first(struct pmap_page *pp)
 {
 
 	KASSERT(mutex_owned(&pp->pp_lock));
-	if (pp->pp_embedded) {
+	if (pv_pte_embedded(pp)) {
 		return &pp->pp_pte;
 	}
 	return pve_to_pvpte(LIST_FIRST(&pp->pp_pvlist));
@@ -2025,8 +2036,7 @@ pmap_lookup_pv(const struct pmap *pmap, 
 	 * set together for this pmap.
 	 *
 	 */
-	if (atomic_load_relaxed(&old_pp->pp_embedded) &&
-	    atomic_load_relaxed(&old_pp->pp_pte.pte_ptp) == ptp &&
+	if (atomic_load_relaxed(&old_pp->pp_pte.pte_ptp) == ptp &&
 	    atomic_load_relaxed(&old_pp->pp_pte.pte_va) == va) {
 		return NULL;
 	}
@@ -2080,8 +2090,7 @@ pmap_enter_pv(struct pmap *pmap, struct 
 	 * to check for this very specific set of values without a lock
 	 * because all 3 will only ever be set together for this pmap.
 	 */
-	if (atomic_load_relaxed(&pp->pp_embedded) &&
-	    atomic_load_relaxed(&pp->pp_pte.pte_ptp) == ptp &&
+	if (atomic_load_relaxed(&pp->pp_pte.pte_ptp) == ptp &&
 	    atomic_load_relaxed(&pp->pp_pte.pte_va) == va) {
 		*samepage = true;
 		return 0;
@@ -2108,13 +2117,12 @@ pmap_enter_pv(struct pmap *pmap, struct 
 
 	error = 0;
 	mutex_spin_enter(&pp->pp_lock);
-	if (!pp->pp_embedded) {
+	if (!pv_pte_embedded(pp)) {
 		/*
 		 * Embedded PV tracking available - easy.
 		 */
 		pp->pp_pte.pte_ptp = ptp;
 		pp->pp_pte.pte_va = va;
-		pp->pp_embedded = true;
 		*new_embedded = true;
 	} else if (__predict_false(pmap->pm_pve == NULL)) {
 		/*
@@ -2160,14 +2168,10 @@ pmap_remove_pv(struct pmap *pmap, struct
 	mutex_spin_enter(&pp->pp_lock);
 	pp->pp_attrs |= oattrs;
 	if (pve == NULL) {
-		KASSERT(pp->pp_embedded);
 		KASSERT(pp->pp_pte.pte_ptp == ptp);
 		KASSERT(pp->pp_pte.pte_va == va);
-		pp->pp_embedded = false;
-#ifdef DIAGNOSTIC
 		pp->pp_pte.pte_ptp = NULL;
 		pp->pp_pte.pte_va = 0;
-#endif
 		mutex_spin_exit(&pp->pp_lock);
 	} else {
 		KASSERT(pve == pmap_lookup_pv(pmap, ptp, pp, va));
@@ -2786,16 +2790,24 @@ pmap_destroy(struct pmap *pmap)
 	int i;
 
 	/*
-	 * drop reference count
+	 * drop reference count and verify not in use.
 	 */
 
 	if (atomic_dec_uint_nv(&pmap->pm_obj[0].uo_refs) > 0) {
 		return;
 	}
-
 	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.
+	 */
+	if (__predict_false(!LIST_EMPTY(&pmap->pm_gc_ptp))) {
+		pmap_update(pmap);
+	}
+
+	/*
 	 * Reference count is zero, free pmap resources and then free pmap.
 	 */
 
@@ -4105,9 +4117,12 @@ pmap_pp_remove(struct pmap_page *pp, pad
 	/*
 	 * Do an unlocked check to see if the page has no mappings, eg when
 	 * pmap_remove_all() was called before amap_wipeout() for a process
-	 * private amap - common.
+	 * private amap - common.  The page being removed must be on the way
+	 * out, so we don't have to worry about concurrent attempts to enter
+	 * it (otherwise the caller either doesn't care or has screwed up).
 	 */
-	if (atomic_load_relaxed(&pp->pp_embedded) == 0 &&
+	if (atomic_load_relaxed(&pp->pp_pte.pte_va) == 0 &&
+	    atomic_load_relaxed(&pp->pp_pte.pte_ptp) == NULL &&
 	    atomic_load_relaxed(&pp->pp_pvlist.lh_first) == NULL) {
 	    	return;
 	}
@@ -4554,10 +4569,10 @@ pmap_enter_ma(struct pmap *pmap, vaddr_t
 	struct vm_page *new_pg, *old_pg;
 	struct pmap_page *new_pp, *old_pp;
 	struct pv_entry *old_pve, *new_pve;
-	int error;
 	bool wired = (flags & PMAP_WIRED) != 0;
 	struct pmap *pmap2;
 	struct pmap_ptparray pt;
+	int error;
 	bool getptp, samepage, new_embedded;
 	rb_tree_t *tree;
 
@@ -4631,6 +4646,8 @@ pmap_enter_ma(struct pmap *pmap, vaddr_t
 		pmap_ptp_range_set(ptp, va);
 		tree = &VM_PAGE_TO_PP(ptp)->pp_rb;
 	} else {
+		/* Embedded PV entries rely on this. */
+		KASSERT(va != 0);
 		tree = &pmap_kernel_rb;
 	}
 
@@ -4716,7 +4733,8 @@ pmap_enter_ma(struct pmap *pmap, vaddr_t
 						KASSERT(pmap->pm_pve == NULL);
 						pmap->pm_pve = new_pve;
 					} else if (new_embedded) {
-						new_pp->pp_embedded = false;
+						new_pp->pp_pte.pte_ptp = NULL;
+						new_pp->pp_pte.pte_va = 0;
 					}
 					mutex_spin_exit(&new_pp->pp_lock);
 					pmap_unmap_ptes(pmap, pmap2);
@@ -5139,7 +5157,8 @@ pmap_update(struct pmap *pmap)
 			pp = VM_PAGE_TO_PP(ptp);
 			LIST_INIT(&pp->pp_pvlist);
 			pp->pp_attrs = 0;
-			pp->pp_embedded = false;
+			pp->pp_pte.pte_ptp = NULL;
+			pp->pp_pte.pte_va = 0;
 
 			/*
 			 * XXX Hack to avoid extra locking, and lock
@@ -5548,6 +5567,8 @@ pmap_ept_enter(struct pmap *pmap, vaddr_
 		pmap_ptp_range_set(ptp, va);
 		tree = &VM_PAGE_TO_PP(ptp)->pp_rb;
 	} else {
+		/* Embedded PV entries rely on this. */
+		KASSERT(va != 0);
 		tree = &pmap_kernel_rb;
 	}
 
@@ -5595,12 +5616,7 @@ pmap_ept_enter(struct pmap *pmap, vaddr_
 		pmap_ept_install_ptp(pmap, &pt, va);
 	}
 
-	/*
-	 * Check if there is an existing mapping.  If we are now sure that
-	 * we need pves and we failed to allocate them earlier, handle that.
-	 * Caching the value of oldpa here is safe because only the mod/ref
-	 * bits can change while the pmap is locked.
-	 */
+	/* Check if there is an existing mapping. */
 	ptes = (pt_entry_t *)PMAP_DIRECT_MAP(VM_PAGE_TO_PHYS(ptp));
 	ptep = &ptes[pl1_pi(va)];
 	opte = *ptep;
@@ -5622,6 +5638,11 @@ pmap_ept_enter(struct pmap *pmap, vaddr_
 	} while (pmap_pte_cas(ptep, opte, npte) != opte);
 
 	/*
+	 * Done with the PTEs: they can now be unmapped.
+	 */
+	kpreempt_enable();
+
+	/*
 	 * Update statistics and PTP's reference count.
 	 */
 	pmap_ept_stats_update_bypte(pmap, npte, opte);
@@ -5673,6 +5694,10 @@ pmap_ept_enter(struct pmap *pmap, vaddr_
 	}
 
 same_pa:
+	/*
+	 * shootdown tlb if necessary.
+	 */
+
 	if (pmap_ept_has_ad) {
 		accessed = (~opte & (EPT_R | EPT_A)) == 0;
 	} else {
@@ -5681,18 +5706,8 @@ same_pa:
 	if (accessed && ((opte ^ npte) & (PTE_FRAME | EPT_W)) != 0) {
 		pmap_tlb_shootdown(pmap, va, 0, TLBSHOOT_ENTER);
 	}
-
-	error = 0;
-	kpreempt_enable();
-	if (old_pve != NULL) {
-		pool_cache_put(&pmap_pv_cache, old_pve);
-	}
-	if (new_pve != NULL) {
-		pool_cache_put(&pmap_pv_cache, new_pve);
-	}
 	mutex_exit(&pmap->pm_lock);
-
-	return error;
+	return 0;
 }
 
 /* Pay close attention, this returns L2. */

Reply via email to