From owner-svn-src-head@freebsd.org Sun Jul 2 08:52:10 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 0FE51DA0E73; Sun, 2 Jul 2017 08:52:10 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id DF72E284; Sun, 2 Jul 2017 08:52:09 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v628q9bY005957; Sun, 2 Jul 2017 08:52:09 GMT (envelope-from andrew@FreeBSD.org) Received: (from andrew@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v628q9Ci005956; Sun, 2 Jul 2017 08:52:09 GMT (envelope-from andrew@FreeBSD.org) Message-Id: <201707020852.v628q9Ci005956@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: andrew set sender to andrew@FreeBSD.org using -f From: Andrew Turner Date: Sun, 2 Jul 2017 08:52:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r320571 - head/sys/arm64/arm64 X-SVN-Group: head X-SVN-Commit-Author: andrew X-SVN-Commit-Paths: head/sys/arm64/arm64 X-SVN-Commit-Revision: 320571 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Jul 2017 08:52:10 -0000 Author: andrew Date: Sun Jul 2 08:52:08 2017 New Revision: 320571 URL: https://svnweb.freebsd.org/changeset/base/320571 Log: In the arm64 pmap_remove, when removing a full superpage there is no need to demote it to 512 pages, then remove each of these. We can just remove the l2 map directly. This is what the intel pmaps already do. Sponsored by: DARPA, AFRL Modified: head/sys/arm64/arm64/pmap.c Modified: head/sys/arm64/arm64/pmap.c ============================================================================== --- head/sys/arm64/arm64/pmap.c Sun Jul 2 05:40:22 2017 (r320570) +++ head/sys/arm64/arm64/pmap.c Sun Jul 2 08:52:08 2017 (r320571) @@ -270,8 +270,10 @@ static pt_entry_t *pmap_demote_l2_locked(pmap_t pmap, static pt_entry_t *pmap_demote_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t va); static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, vm_page_t mpte, struct rwlock **lockp); +static int pmap_remove_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t sva, + pd_entry_t l1e, struct spglist *free, struct rwlock **lockp); static int pmap_remove_l3(pmap_t pmap, pt_entry_t *l3, vm_offset_t sva, - pd_entry_t ptepde, struct spglist *free, struct rwlock **lockp); + pd_entry_t l2e, struct spglist *free, struct rwlock **lockp); static boolean_t pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, vm_page_t m, struct rwlock **lockp); @@ -280,7 +282,8 @@ static vm_page_t _pmap_alloc_l3(pmap_t pmap, vm_pindex static void _pmap_unwire_l3(pmap_t pmap, vm_offset_t va, vm_page_t m, struct spglist *free); -static int pmap_unuse_l3(pmap_t, vm_offset_t, pd_entry_t, struct spglist *); +static int pmap_unuse_pt(pmap_t, vm_offset_t, pd_entry_t, struct spglist *); +static __inline vm_page_t pmap_remove_pt_page(pmap_t pmap, vm_offset_t va); /* * These load the old table data and store the new value. @@ -1373,11 +1376,11 @@ _pmap_unwire_l3(pmap_t pmap, vm_offset_t va, vm_page_t } /* - * After removing an l3 entry, this routine is used to + * After removing a page table entry, this routine is used to * conditionally free the page, and manage the hold/wire counts. */ static int -pmap_unuse_l3(pmap_t pmap, vm_offset_t va, pd_entry_t ptepde, +pmap_unuse_pt(pmap_t pmap, vm_offset_t va, pd_entry_t ptepde, struct spglist *free) { vm_page_t mpte; @@ -1873,7 +1876,7 @@ reclaim_pv_chunk(pmap_t locked_pmap, struct rwlock **l } } pc->pc_map[field] |= 1UL << bit; - pmap_unuse_l3(pmap, va, pmap_load(pde), &free); + pmap_unuse_pt(pmap, va, pmap_load(pde), &free); freed++; } } @@ -2231,6 +2234,55 @@ pmap_try_insert_pv_entry(pmap_t pmap, vm_offset_t va, } /* + * pmap_remove_l2: do the things to unmap a level 2 superpage in a process + */ +static int +pmap_remove_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t sva, + pd_entry_t l1e, struct spglist *free, struct rwlock **lockp) +{ + struct md_page *pvh; + pt_entry_t old_l2; + vm_offset_t eva, va; + vm_page_t m, ml3; + + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + KASSERT((sva & L2_OFFSET) == 0, ("pmap_remove_l2: sva is not aligned")); + old_l2 = pmap_load_clear(l2); + pmap_invalidate_range(pmap, sva, sva + L2_SIZE); + if (old_l2 & ATTR_SW_WIRED) + pmap->pm_stats.wired_count -= L2_SIZE / PAGE_SIZE; + pmap_resident_count_dec(pmap, L2_SIZE / PAGE_SIZE); + if (old_l2 & ATTR_SW_MANAGED) { + CHANGE_PV_LIST_LOCK_TO_PHYS(lockp, old_l2 & ~ATTR_MASK); + pvh = pa_to_pvh(old_l2 & ~ATTR_MASK); + pmap_pvh_free(pvh, pmap, sva); + eva = sva + L2_SIZE; + for (va = sva, m = PHYS_TO_VM_PAGE(old_l2 & ~ATTR_MASK); + va < eva; va += PAGE_SIZE, m++) { + if (pmap_page_dirty(old_l2)) + vm_page_dirty(m); + if (old_l2 & ATTR_AF) + vm_page_aflag_set(m, PGA_REFERENCED); + if (TAILQ_EMPTY(&m->md.pv_list) && + TAILQ_EMPTY(&pvh->pv_list)) + vm_page_aflag_clear(m, PGA_WRITEABLE); + } + } + KASSERT(pmap != kernel_pmap, + ("Attempting to remove an l2 kernel page")); + ml3 = pmap_remove_pt_page(pmap, sva); + if (ml3 != NULL) { + pmap_resident_count_dec(pmap, 1); + KASSERT(ml3->wire_count == NL3PG, + ("pmap_remove_pages: l3 page wire count error")); + ml3->wire_count = 0; + pmap_add_delayed_free_list(ml3, free, FALSE); + atomic_subtract_int(&vm_cnt.v_wire_count, 1); + } + return (pmap_unuse_pt(pmap, sva, l1e, free)); +} + +/* * pmap_remove_l3: do the things to unmap a page in a process */ static int @@ -2262,7 +2314,7 @@ pmap_remove_l3(pmap_t pmap, pt_entry_t *l3, vm_offset_ vm_page_aflag_clear(m, PGA_WRITEABLE); } } - return (pmap_unuse_l3(pmap, va, l2e, free)); + return (pmap_unuse_pt(pmap, va, l2e, free)); } /* @@ -2328,10 +2380,13 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t l3_paddr = pmap_load(l2); if ((l3_paddr & ATTR_DESCR_MASK) == L2_BLOCK) { - /* TODO: Add pmap_remove_l2 */ - if (pmap_demote_l2_locked(pmap, l2, sva & ~L2_OFFSET, - &lock) == NULL) + if (sva + L2_SIZE == va_next && eva >= va_next) { + pmap_remove_l2(pmap, l2, sva, pmap_load(l1), + &free, &lock); continue; + } else if (pmap_demote_l2_locked(pmap, l2, + sva &~L2_OFFSET, &lock) == NULL) + continue; l3_paddr = pmap_load(l2); } @@ -2474,7 +2529,7 @@ retry: */ if (pmap_page_dirty(tpte)) vm_page_dirty(m); - pmap_unuse_l3(pmap, pv->pv_va, tpde, &free); + pmap_unuse_pt(pmap, pv->pv_va, tpde, &free); TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); m->md.pv_gen++; free_pv_entry(pmap, pv); @@ -3664,7 +3719,7 @@ pmap_remove_pages(pmap_t pmap) } break; } - pmap_unuse_l3(pmap, pv->pv_va, pmap_load(pde), + pmap_unuse_pt(pmap, pv->pv_va, pmap_load(pde), &free); freed++; }