Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 2 May 2025 15:45:07 GMT
From:      Andrew Turner <andrew@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 9ea78ef1d6f9 - main - arm64: Use the DMAP region in pmap_mapbios
Message-ID:  <202505021545.542Fj7FZ097725@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by andrew:

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

commit 9ea78ef1d6f9785411963a897668cb2eeedd4107
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2025-05-02 15:36:35 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2025-05-02 15:39:04 +0000

    arm64: Use the DMAP region in pmap_mapbios
    
    As pmap_mapbios is used to map a physical address with a default memory
    attribute we can try to use the DMAP region. For now check if all pages
    are mapped, however it is expected this check can be removed later
    after testing on more hardware.
    
    Reviewed by:    alc, markj, jhb (earlier version)
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D42732
---
 sys/arm64/arm64/pmap.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 71 insertions(+), 1 deletion(-)

diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index f4d6b1cfcb56..625caf6ecd7e 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -2110,6 +2110,56 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
 	return (m);
 }
 
+/*
+ * Returns true if the entire kernel virtual address range is mapped
+ */
+static bool
+pmap_kmapped_range(vm_offset_t sva, vm_size_t size)
+{
+	pt_entry_t *pte, tpte;
+	vm_offset_t eva;
+
+	KASSERT(sva >= VM_MIN_KERNEL_ADDRESS,
+	    ("%s: Invalid virtual address: %lx", __func__, sva));
+	MPASS(size != 0);
+	eva = sva + size - 1;
+	KASSERT(eva > sva, ("%s: Size too large: sva %lx, size %lx", __func__,
+	    sva, size));
+
+	while (sva <= eva) {
+		pte = pmap_l1(kernel_pmap, sva);
+		if (pte == NULL)
+			return (false);
+		tpte = pmap_load(pte);
+		if (tpte == 0)
+			return (false);
+		if ((tpte & ATTR_DESCR_TYPE_MASK) == ATTR_DESCR_TYPE_BLOCK) {
+			sva = (sva & ~L1_OFFSET) + L1_SIZE;
+			continue;
+		}
+
+		pte = pmap_l1_to_l2(&tpte, sva);
+		tpte = pmap_load(pte);
+		if (tpte == 0)
+			return (false);
+		if ((tpte & ATTR_DESCR_TYPE_MASK) == ATTR_DESCR_TYPE_BLOCK) {
+			sva = (sva & ~L2_OFFSET) + L2_SIZE;
+			continue;
+		}
+		pte = pmap_l2_to_l3(&tpte, sva);
+		tpte = pmap_load(pte);
+		if (tpte == 0)
+			return (false);
+		MPASS((tpte & ATTR_DESCR_TYPE_MASK) == ATTR_DESCR_TYPE_PAGE);
+		if ((tpte & ATTR_CONTIGUOUS) == ATTR_CONTIGUOUS)
+			sva = (sva & ~L3C_OFFSET) + L3C_SIZE;
+		else
+			sva = (sva & ~L3_OFFSET) + L3_SIZE;
+	}
+
+	return (true);
+}
+
 /*
  * Walks the page tables to translate a kernel virtual address to a
  * physical address. Returns true if the kva is valid and stores the
@@ -7786,6 +7836,11 @@ pmap_mapbios(vm_paddr_t pa, vm_size_t size)
 	pt_entry_t *l2;
 	int i, lvl, l2_blocks, free_l2_count, start_idx;
 
+	/* Use the DMAP region if we can */
+	if (PHYS_IN_DMAP(pa) && PHYS_IN_DMAP(pa + size - 1) &&
+	    pmap_kmapped_range(PHYS_TO_DMAP(pa), size))
+		return ((void *)PHYS_TO_DMAP(pa));
+
 	if (!vm_initialized) {
 		/*
 		 * No L3 ptables so map entire L2 blocks where start VA is:
@@ -7901,10 +7956,25 @@ pmap_unmapbios(void *p, vm_size_t size)
 	vm_offset_t offset, va, va_trunc;
 	pd_entry_t *pde;
 	pt_entry_t *l2;
-	int i, lvl, l2_blocks, block;
+	int error __diagused, i, lvl, l2_blocks, block;
 	bool preinit_map;
 
 	va = (vm_offset_t)p;
+	if (VIRT_IN_DMAP(va)) {
+		KASSERT(VIRT_IN_DMAP(va + size - 1),
+		    ("%s: End address not in DMAP region: %lx", __func__,
+		    va + size - 1));
+		/* Ensure the attributes are as expected for the DMAP region */
+		PMAP_LOCK(kernel_pmap);
+		error = pmap_change_props_locked(va, size,
+		    PROT_READ | PROT_WRITE, VM_MEMATTR_DEFAULT, false);
+		PMAP_UNLOCK(kernel_pmap);
+		KASSERT(error == 0, ("%s: Failed to reset DMAP attributes: %d",
+		    __func__, error));
+
+		return;
+	}
+
 	l2_blocks =
 	   (roundup2(va + size, L2_SIZE) - rounddown2(va, L2_SIZE)) >> L2_SHIFT;
 	KASSERT(l2_blocks > 0, ("pmap_unmapbios: invalid size %lx", size));



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