From owner-dev-commits-src-all@freebsd.org Sun Oct 3 18:36:47 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 54DC066C8A1; Sun, 3 Oct 2021 18:36:47 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4HMsy71xf8z3rwn; Sun, 3 Oct 2021 18:36:47 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 22C3B2E9E; Sun, 3 Oct 2021 18:36:47 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 193IalnV074862; Sun, 3 Oct 2021 18:36:47 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 193IalKi074861; Sun, 3 Oct 2021 18:36:47 GMT (envelope-from git) Date: Sun, 3 Oct 2021 18:36:47 GMT Message-Id: <202110031836.193IalKi074861@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Jessica Clarke Subject: git: 1be2e16df1d2 - main - riscv: Add a stub pmap_change_attr implementation MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jrtc27 X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 1be2e16df1d29148aee83964330a71ae403c6078 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Oct 2021 18:36:47 -0000 The branch main has been updated by jrtc27: URL: https://cgit.FreeBSD.org/src/commit/?id=1be2e16df1d29148aee83964330a71ae403c6078 commit 1be2e16df1d29148aee83964330a71ae403c6078 Author: Jessica Clarke AuthorDate: 2021-10-03 18:33:47 +0000 Commit: Jessica Clarke CommitDate: 2021-10-03 18:33:47 +0000 riscv: Add a stub pmap_change_attr implementation pmap_change_attr is required by drm-kmod so we need the function to exist. Since the Svpbmt extension is on the horizon we will likely end up with a real implementation of it, so this stub implementation does all the necessary page table walking to validate the input, ensuring that no new errors are returned once it's implemented fully (other than due to out of memory conditions when demoting L2 entries) and providing a skeleton for that future implementation. Reviewed by: markj MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D31996 --- sys/riscv/include/pmap.h | 1 + sys/riscv/riscv/pmap.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/sys/riscv/include/pmap.h b/sys/riscv/include/pmap.h index 599adfa4ce19..024bc3743f67 100644 --- a/sys/riscv/include/pmap.h +++ b/sys/riscv/include/pmap.h @@ -144,6 +144,7 @@ struct thread; void pmap_activate_boot(pmap_t); void pmap_activate_sw(struct thread *); void pmap_bootstrap(vm_offset_t, vm_paddr_t, vm_size_t); +int pmap_change_attr(vm_offset_t va, vm_size_t size, int mode); void pmap_kenter_device(vm_offset_t, vm_size_t, vm_paddr_t); vm_paddr_t pmap_kextract(vm_offset_t va); void pmap_kremove(vm_offset_t); diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c index 8f76881478b9..df80f07df0ca 100644 --- a/sys/riscv/riscv/pmap.c +++ b/sys/riscv/riscv/pmap.c @@ -310,6 +310,8 @@ static void _pmap_unwire_ptp(pmap_t pmap, vm_offset_t va, vm_page_t m, struct spglist *free); static int pmap_unuse_pt(pmap_t, vm_offset_t, pd_entry_t, struct spglist *); +static int pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode); + #define pmap_clear(pte) pmap_store(pte, 0) #define pmap_clear_bits(pte, bits) atomic_clear_64(pte, bits) #define pmap_load_store(pte, entry) atomic_swap_64(pte, entry) @@ -4252,6 +4254,98 @@ pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) { m->md.pv_memattr = ma; + + /* + * If "m" is a normal page, update its direct mapping. This update + * can be relied upon to perform any cache operations that are + * required for data coherence. + */ + if ((m->flags & PG_FICTITIOUS) == 0 && + pmap_change_attr(PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)), PAGE_SIZE, + m->md.pv_memattr) != 0) + panic("memory attribute change on the direct map failed"); +} + +/* + * Changes the specified virtual address range's memory type to that given by + * the parameter "mode". The specified virtual address range must be + * completely contained within either the direct map or the kernel map. + * + * Returns zero if the change completed successfully, and either EINVAL or + * ENOMEM if the change failed. Specifically, EINVAL is returned if some part + * of the virtual address range was not mapped, and ENOMEM is returned if + * there was insufficient memory available to complete the change. In the + * latter case, the memory type may have been changed on some part of the + * virtual address range. + */ +int +pmap_change_attr(vm_offset_t va, vm_size_t size, int mode) +{ + int error; + + PMAP_LOCK(kernel_pmap); + error = pmap_change_attr_locked(va, size, mode); + PMAP_UNLOCK(kernel_pmap); + return (error); +} + +static int +pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode) +{ + vm_offset_t base, offset, tmpva; + pd_entry_t *l1, l1e; + pd_entry_t *l2, l2e; + pt_entry_t *l3, l3e; + + PMAP_LOCK_ASSERT(kernel_pmap, MA_OWNED); + base = trunc_page(va); + offset = va & PAGE_MASK; + size = round_page(offset + size); + + if (!VIRT_IN_DMAP(base) && + !(base >= VM_MIN_KERNEL_ADDRESS && base < VM_MAX_KERNEL_ADDRESS)) + return (EINVAL); + + for (tmpva = base; tmpva < base + size; ) { + l1 = pmap_l1(kernel_pmap, tmpva); + if (l1 == NULL || ((l1e = pmap_load(l1)) & PTE_V) == 0) + return (EINVAL); + if ((l1e & PTE_RWX) != 0) { + /* + * TODO: Demote if attributes don't match and there + * isn't an L1 page left in the range, and update the + * L1 entry if the attributes don't match but there is + * an L1 page left in the range, once we support the + * upcoming Svpbmt extension. + */ + tmpva = (tmpva & ~L1_OFFSET) + L1_SIZE; + continue; + } + l2 = pmap_l1_to_l2(l1, tmpva); + if (l2 == NULL || ((l2e = pmap_load(l2)) & PTE_V) == 0) + return (EINVAL); + if ((l2e & PTE_RWX) != 0) { + /* + * TODO: Demote if attributes don't match and there + * isn't an L2 page left in the range, and update the + * L2 entry if the attributes don't match but there is + * an L2 page left in the range, once we support the + * upcoming Svpbmt extension. + */ + tmpva = (tmpva & ~L2_OFFSET) + L2_SIZE; + continue; + } + l3 = pmap_l2_to_l3(l2, tmpva); + if (l3 == NULL || ((l3e = pmap_load(l3)) & PTE_V) == 0) + return (EINVAL); + /* + * TODO: Update the L3 entry if the attributes don't match once + * we support the upcoming Svpbmt extension. + */ + tmpva += PAGE_SIZE; + } + + return (0); } /*