From owner-svn-src-all@FreeBSD.ORG Wed Jul 16 21:06:44 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 269C1F4A; Wed, 16 Jul 2014 21:06:44 +0000 (UTC) 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)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1471A238E; Wed, 16 Jul 2014 21:06:44 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6GL6hDa009195; Wed, 16 Jul 2014 21:06:43 GMT (envelope-from alc@svn.freebsd.org) Received: (from alc@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6GL6hrT009193; Wed, 16 Jul 2014 21:06:43 GMT (envelope-from alc@svn.freebsd.org) Message-Id: <201407162106.s6GL6hrT009193@svn.freebsd.org> From: Alan Cox Date: Wed, 16 Jul 2014 21:06:43 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r268776 - 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.18 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: Wed, 16 Jul 2014 21:06:44 -0000 Author: alc Date: Wed Jul 16 21:06:43 2014 New Revision: 268776 URL: http://svnweb.freebsd.org/changeset/base/268776 Log: Implement pmap_unwire(). See r268327 for the motivation behind this change. Modified: head/sys/arm/arm/pmap-v6.c head/sys/arm/arm/pmap.c Modified: head/sys/arm/arm/pmap-v6.c ============================================================================== --- head/sys/arm/arm/pmap-v6.c Wed Jul 16 21:04:31 2014 (r268775) +++ head/sys/arm/arm/pmap-v6.c Wed Jul 16 21:06:43 2014 (r268776) @@ -3302,6 +3302,79 @@ out: PMAP_UNLOCK(pmap); } +/* + * Clear the wired attribute from the mappings for the specified range of + * addresses in the given pmap. Every valid mapping within that range + * must have the wired attribute set. In contrast, invalid mappings + * cannot have the wired attribute set, so they are ignored. + * + * XXX Wired mappings of unmanaged pages cannot be counted by this pmap + * implementation. + */ +void +pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) +{ + struct l2_bucket *l2b; + struct md_page *pvh; + pd_entry_t l1pd; + pt_entry_t *ptep, pte; + pv_entry_t pv; + vm_offset_t next_bucket; + vm_paddr_t pa; + vm_page_t m; + + rw_wlock(&pvh_global_lock); + PMAP_LOCK(pmap); + while (sva < eva) { + next_bucket = L2_NEXT_BUCKET(sva); + l1pd = pmap->pm_l1->l1_kva[L1_IDX(sva)]; + if ((l1pd & L1_TYPE_MASK) == L1_S_PROTO) { + pa = l1pd & L1_S_FRAME; + m = PHYS_TO_VM_PAGE(pa); + KASSERT(m != NULL && (m->oflags & VPO_UNMANAGED) == 0, + ("pmap_unwire: unmanaged 1mpage %p", m)); + pvh = pa_to_pvh(pa); + pv = pmap_find_pv(pvh, pmap, trunc_1mpage(sva)); + if ((pv->pv_flags & PVF_WIRED) == 0) + panic("pmap_unwire: pv %p isn't wired", pv); + + /* + * Are we unwiring the entire large page? If not, + * demote the mapping and fall through. + */ + if (sva + L1_S_SIZE == next_bucket && + eva >= next_bucket) { + pv->pv_flags &= ~PVF_WIRED; + pmap->pm_stats.wired_count -= L2_PTE_NUM_TOTAL; + sva = next_bucket; + continue; + } else if (!pmap_demote_section(pmap, sva)) + panic("pmap_unwire: demotion failed"); + } + if (next_bucket > eva) + next_bucket = eva; + l2b = pmap_get_l2_bucket(pmap, sva); + if (l2b == NULL) { + sva = next_bucket; + continue; + } + for (ptep = &l2b->l2b_kva[l2pte_index(sva)]; sva < next_bucket; + sva += PAGE_SIZE, ptep++) { + if ((pte = *ptep) == 0 || + (m = PHYS_TO_VM_PAGE(l2pte_pa(pte))) == NULL || + (m->oflags & VPO_UNMANAGED) != 0) + continue; + pv = pmap_find_pv(&m->md, pmap, sva); + if ((pv->pv_flags & PVF_WIRED) == 0) + panic("pmap_unwire: pv %p isn't wired", pv); + pv->pv_flags &= ~PVF_WIRED; + pmap->pm_stats.wired_count--; + } + } + rw_wunlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); +} + /* * Copy the range specified by src_addr/len Modified: head/sys/arm/arm/pmap.c ============================================================================== --- head/sys/arm/arm/pmap.c Wed Jul 16 21:04:31 2014 (r268775) +++ head/sys/arm/arm/pmap.c Wed Jul 16 21:06:43 2014 (r268776) @@ -3570,6 +3570,52 @@ pmap_change_wiring(pmap_t pmap, vm_offse PMAP_UNLOCK(pmap); } +/* + * Clear the wired attribute from the mappings for the specified range of + * addresses in the given pmap. Every valid mapping within that range + * must have the wired attribute set. In contrast, invalid mappings + * cannot have the wired attribute set, so they are ignored. + * + * XXX Wired mappings of unmanaged pages cannot be counted by this pmap + * implementation. + */ +void +pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) +{ + struct l2_bucket *l2b; + pt_entry_t *ptep, pte; + pv_entry_t pv; + vm_offset_t next_bucket; + vm_page_t m; + + rw_wlock(&pvh_global_lock); + PMAP_LOCK(pmap); + while (sva < eva) { + next_bucket = L2_NEXT_BUCKET(sva); + if (next_bucket > eva) + next_bucket = eva; + l2b = pmap_get_l2_bucket(pmap, sva); + if (l2b == NULL) { + sva = next_bucket; + continue; + } + for (ptep = &l2b->l2b_kva[l2pte_index(sva)]; sva < next_bucket; + sva += PAGE_SIZE, ptep++) { + if ((pte = *ptep) == 0 || + (m = PHYS_TO_VM_PAGE(l2pte_pa(pte))) == NULL || + (m->oflags & VPO_UNMANAGED) != 0) + continue; + pv = pmap_find_pv(m, pmap, sva); + if ((pv->pv_flags & PVF_WIRED) == 0) + panic("pmap_unwire: pv %p isn't wired", pv); + pv->pv_flags &= ~PVF_WIRED; + pmap->pm_stats.wired_count--; + } + } + rw_wunlock(&pvh_global_lock); + PMAP_UNLOCK(pmap); +} + /* * Copy the range specified by src_addr/len