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>