Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 Aug 2025 23:23:42 GMT
From:      Alan Cox <alc@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: d88f8a306cfe - stable/14 - pmap_demote_{l2,pde}: never invalidate wired mappings
Message-ID:  <202508102323.57ANNgf8054136@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/14 has been updated by alc:

URL: https://cgit.FreeBSD.org/src/commit/?id=d88f8a306cfe7ba0a629108102ed2be0b090a876

commit d88f8a306cfe7ba0a629108102ed2be0b090a876
Author:     Alan Cox <alc@FreeBSD.org>
AuthorDate: 2025-07-19 20:18:04 +0000
Commit:     Alan Cox <alc@FreeBSD.org>
CommitDate: 2025-08-10 21:02:57 +0000

    pmap_demote_{l2,pde}: never invalidate wired mappings
    
    Rather than demoting a superpage mapping that hasn't been accessed, we
    ordinarily invalidate it.  However, if the mapping is wired,
    invalidation is problematic because the page fault to reinstantiate the
    mapping could sleep.  Instead, demote the wired mapping with the
    accessed flag cleared in the PTEs.
    
    (cherry picked from commit 7502c1f270827434bb9661cbb4b9652fdb836521)
---
 sys/amd64/amd64/pmap.c | 21 +++++++++++----------
 sys/arm64/arm64/pmap.c | 24 +++++++++++++-----------
 2 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 8aea7ad6d622..9fd6c4091c95 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -6043,17 +6043,18 @@ pmap_demote_pde_mpte(pmap_t pmap, pd_entry_t *pde, vm_offset_t va,
 	if (mpte == NULL) {
 		/*
 		 * Invalidate the 2MB page mapping and return "failure" if the
-		 * mapping was never accessed.
+		 * mapping was never accessed and not wired.
 		 */
 		if ((oldpde & PG_A) == 0) {
-			KASSERT((oldpde & PG_W) == 0,
-		    ("pmap_demote_pde: a wired mapping is missing PG_A"));
-			pmap_demote_pde_abort(pmap, va, pde, oldpde, lockp);
-			return (FALSE);
-		}
-
-		mpte = pmap_remove_pt_page(pmap, va);
-		if (mpte == NULL) {
+			if ((oldpde & PG_W) == 0) {
+				pmap_demote_pde_abort(pmap, va, pde, oldpde,
+				    lockp);
+				return (false);
+			}
+			mpte = pmap_remove_pt_page(pmap, va);
+			/* Fill the PTP with PTEs that have PG_A cleared. */
+			mpte->valid = 0;
+		} else if ((mpte = pmap_remove_pt_page(pmap, va)) == NULL) {
 			KASSERT((oldpde & PG_W) == 0,
     ("pmap_demote_pde: page table page for a wired mapping is missing"));
 
@@ -6105,7 +6106,7 @@ pmap_demote_pde_mpte(pmap_t pmap, pd_entry_t *pde, vm_offset_t va,
 	/*
 	 * If the PTP is not leftover from an earlier promotion or it does not
 	 * have PG_A set in every PTE, then fill it.  The new PTEs will all
-	 * have PG_A set.
+	 * have PG_A set, unless this is a wired mapping with PG_A clear.
 	 */
 	if (!vm_page_all_valid(mpte))
 		pmap_fill_ptp(firstpte, newpte);
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index 05cb0df4a1ae..a3014fd5cee3 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -7093,18 +7093,20 @@ pmap_demote_l2_locked(pmap_t pmap, pt_entry_t *l2, vm_offset_t va,
 
 	/*
 	 * Invalidate the 2MB page mapping and return "failure" if the
-	 * mapping was never accessed.
+	 * mapping was never accessed and not wired.
 	 */
 	if ((oldl2 & ATTR_AF) == 0) {
-		KASSERT((oldl2 & ATTR_SW_WIRED) == 0,
-		    ("pmap_demote_l2: a wired mapping is missing ATTR_AF"));
-		pmap_demote_l2_abort(pmap, va, l2, lockp);
-		CTR2(KTR_PMAP, "pmap_demote_l2: failure for va %#lx in pmap %p",
-		    va, pmap);
-		goto fail;
-	}
-
-	if ((ml3 = pmap_remove_pt_page(pmap, va)) == NULL) {
+		if ((oldl2 & ATTR_SW_WIRED) == 0) {
+			pmap_demote_l2_abort(pmap, va, l2, lockp);
+			CTR2(KTR_PMAP,
+			    "pmap_demote_l2: failure for va %#lx in pmap %p",
+			    va, pmap);
+			goto fail;
+		}
+		ml3 = pmap_remove_pt_page(pmap, va);
+		/* Fill the PTP with L3Es that have ATTR_AF cleared. */
+		ml3->valid = 0;
+	} else if ((ml3 = pmap_remove_pt_page(pmap, va)) == NULL) {
 		KASSERT((oldl2 & ATTR_SW_WIRED) == 0,
 		    ("pmap_demote_l2: page table page for a wired mapping"
 		    " is missing"));
@@ -7160,7 +7162,7 @@ pmap_demote_l2_locked(pmap_t pmap, pt_entry_t *l2, vm_offset_t va,
 	/*
 	 * If the PTP is not leftover from an earlier promotion or it does not
 	 * have ATTR_AF set in every L3E, then fill it.  The new L3Es will all
-	 * have ATTR_AF set.
+	 * have ATTR_AF set, unless this is a wired mapping with ATTR_AF clear.
 	 *
 	 * When pmap_update_entry() clears the old L2 mapping, it (indirectly)
 	 * performs a dsb().  That dsb() ensures that the stores for filling



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