From owner-svn-src-all@FreeBSD.ORG Mon Sep 16 10:39:36 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 0FEEF1000; Mon, 16 Sep 2013 10:39:36 +0000 (UTC) (envelope-from zbb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id F0FB72EE3; Mon, 16 Sep 2013 10:39:35 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r8GAdZZ1079546; Mon, 16 Sep 2013 10:39:35 GMT (envelope-from zbb@svn.freebsd.org) Received: (from zbb@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r8GAdZEn079545; Mon, 16 Sep 2013 10:39:35 GMT (envelope-from zbb@svn.freebsd.org) Message-Id: <201309161039.r8GAdZEn079545@svn.freebsd.org> From: Zbigniew Bodek Date: Mon, 16 Sep 2013 10:39:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r255612 - head/sys/arm/arm X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 Sep 2013 10:39:36 -0000 Author: zbb Date: Mon Sep 16 10:39:35 2013 New Revision: 255612 URL: http://svnweb.freebsd.org/changeset/base/255612 Log: Implement pmap_advise() for ARMv6/v7 pmap module Apply the given advice to the specified range of addresses within the given pmap. Depending on the advice, clear the referenced and/or modified flags in each mapping. Superpage within the given range will be demoted or destroyed. Reviewed by: alc Approved by: cognet (mentor) Approved by: re Modified: head/sys/arm/arm/pmap-v6.c Modified: head/sys/arm/arm/pmap-v6.c ============================================================================== --- head/sys/arm/arm/pmap-v6.c Mon Sep 16 10:34:44 2013 (r255611) +++ head/sys/arm/arm/pmap-v6.c Mon Sep 16 10:39:35 2013 (r255612) @@ -4767,11 +4767,116 @@ pmap_is_modified(vm_page_t m) } /* - * This function is advisory. + * Apply the given advice to the specified range of addresses within the + * given pmap. Depending on the advice, clear the referenced and/or + * modified flags in each mapping. */ void pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, int advice) { + struct l2_bucket *l2b; + struct pv_entry *pve; + pd_entry_t *pl1pd, l1pd; + pt_entry_t *ptep, opte, pte; + vm_offset_t next_bucket; + vm_page_t m; + + if (advice != MADV_DONTNEED && advice != MADV_FREE) + return; + rw_wlock(&pvh_global_lock); + PMAP_LOCK(pmap); + for (; sva < eva; sva = next_bucket) { + next_bucket = L2_NEXT_BUCKET(sva); + if (next_bucket < sva) + next_bucket = eva; + pl1pd = &pmap->pm_l1->l1_kva[L1_IDX(sva)]; + l1pd = *pl1pd; + if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) { + if (pmap == pmap_kernel()) + continue; + if (!pmap_demote_section(pmap, sva)) { + /* + * The large page mapping was destroyed. + */ + continue; + } + /* + * Unless the page mappings are wired, remove the + * mapping to a single page so that a subsequent + * access may repromote. Since the underlying + * l2_bucket is fully populated, this removal + * never frees an entire l2_bucket. + */ + l2b = pmap_get_l2_bucket(pmap, sva); + KASSERT(l2b != NULL, + ("pmap_advise: no l2 bucket for " + "va 0x%#x, pmap 0x%p", sva, pmap)); + ptep = &l2b->l2b_kva[l2pte_index(sva)]; + opte = *ptep; + m = PHYS_TO_VM_PAGE(l2pte_pa(*ptep)); + KASSERT(m != NULL, + ("pmap_advise: no vm_page for demoted superpage")); + pve = pmap_find_pv(&m->md, pmap, sva); + KASSERT(pve != NULL, + ("pmap_advise: no PV entry for managed mapping")); + if ((pve->pv_flags & PVF_WIRED) == 0) { + pmap_free_l2_bucket(pmap, l2b, 1); + pve = pmap_remove_pv(m, pmap, sva); + pmap_free_pv_entry(pmap, pve); + *ptep = 0; + PTE_SYNC(ptep); + if (pmap_is_current(pmap)) { + if (PTE_BEEN_EXECD(opte)) + cpu_tlb_flushID_SE(sva); + else if (PTE_BEEN_REFD(opte)) + cpu_tlb_flushD_SE(sva); + } + } + } + if (next_bucket > eva) + next_bucket = eva; + l2b = pmap_get_l2_bucket(pmap, sva); + if (l2b == NULL) + continue; + for (ptep = &l2b->l2b_kva[l2pte_index(sva)]; + sva != next_bucket; ptep++, sva += PAGE_SIZE) { + opte = pte = *ptep; + if ((opte & L2_S_PROTO) == 0) + continue; + m = PHYS_TO_VM_PAGE(l2pte_pa(opte)); + if (m == NULL || (m->oflags & VPO_UNMANAGED) != 0) + continue; + else if (L2_S_WRITABLE(opte)) { + if (advice == MADV_DONTNEED) { + /* + * Don't need to mark the page + * dirty as it was already marked as + * such in pmap_fault_fixup() or + * pmap_enter_locked(). + * Just clear the state. + */ + } else + pte |= L2_APX; + + pte &= ~L2_S_REF; + *ptep = pte; + PTE_SYNC(ptep); + } else if (L2_S_REFERENCED(opte)) { + pte &= ~L2_S_REF; + *ptep = pte; + PTE_SYNC(ptep); + } else + continue; + if (pmap_is_current(pmap)) { + if (PTE_BEEN_EXECD(opte)) + cpu_tlb_flushID_SE(sva); + else if (PTE_BEEN_REFD(opte)) + cpu_tlb_flushD_SE(sva); + } + } + } + rw_wunlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); } /*