From owner-svn-src-stable-8@FreeBSD.ORG Mon Feb 15 15:00:41 2010 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 26366106568B; Mon, 15 Feb 2010 15:00:41 +0000 (UTC) (envelope-from raj@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 13C778FC0A; Mon, 15 Feb 2010 15:00:41 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o1FF0eoi033486; Mon, 15 Feb 2010 15:00:40 GMT (envelope-from raj@svn.freebsd.org) Received: (from raj@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o1FF0eMo033484; Mon, 15 Feb 2010 15:00:40 GMT (envelope-from raj@svn.freebsd.org) Message-Id: <201002151500.o1FF0eMo033484@svn.freebsd.org> From: Rafal Jaworowski Date: Mon, 15 Feb 2010 15:00:40 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r203925 - stable/8/sys/arm/arm X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 15 Feb 2010 15:00:41 -0000 Author: raj Date: Mon Feb 15 15:00:40 2010 New Revision: 203925 URL: http://svn.freebsd.org/changeset/base/203925 Log: MFC r203637: Improve checking whether an ARM VA has a valid mapping before performing cache sync. VIPT/PIPT caches need valid VA-PA mapping in PTE for a cache operation to succeed (unlike VIVT). Prior to this fix pmap was using l2pte_valid() for that check, but this is not sufficient as the function merely checks if a PTE exists (there can be existing but _invalid_ entries in the table). A new pmap_has_valid_mapping() routine is introduced to do this job right by checking proper PTE flags. Among other potential problems this cures coherency issues with L2 caches on MV-78100. Submitted by: Grzegorz Bernacki, Piotr Ziecik Reviewed, tested by: marcel Obtained from: Semihalf Modified: stable/8/sys/arm/arm/pmap.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) stable/8/sys/netinet/ (props changed) Modified: stable/8/sys/arm/arm/pmap.c ============================================================================== --- stable/8/sys/arm/arm/pmap.c Mon Feb 15 14:38:30 2010 (r203924) +++ stable/8/sys/arm/arm/pmap.c Mon Feb 15 15:00:40 2010 (r203925) @@ -1199,79 +1199,38 @@ pmap_tlb_flushD(pmap_t pm) cpu_tlb_flushD(); } -static PMAP_INLINE void -pmap_l2cache_wbinv_range(pmap_t pm, vm_offset_t va, vm_size_t len) +static int +pmap_has_valid_mapping(pmap_t pm, vm_offset_t va) { - vm_size_t rest; pd_entry_t *pde; pt_entry_t *ptep; - rest = MIN(PAGE_SIZE - (va & PAGE_MASK), len); - - while (len > 0) { - CTR4(KTR_PMAP, "pmap_l2cache_wbinv_range: pmap %p is_kernel %d " - "va 0x%08x len 0x%x ", pm, pm == pmap_kernel(), va, rest); - if (pmap_get_pde_pte(pm, va, &pde, &ptep) && l2pte_valid(*ptep)) - cpu_l2cache_wbinv_range(va, rest); - - len -= rest; - va += rest; + if (pmap_get_pde_pte(pm, va, &pde, &ptep) && + ptep && ((*ptep & L2_TYPE_MASK) != L2_TYPE_INV)) + return (1); - rest = MIN(PAGE_SIZE, len); - } + return (0); } static PMAP_INLINE void pmap_idcache_wbinv_range(pmap_t pm, vm_offset_t va, vm_size_t len) { - - if (pmap_is_current(pm)) { - cpu_idcache_wbinv_range(va, len); - pmap_l2cache_wbinv_range(pm, va, len); - } -} - -static PMAP_INLINE void -pmap_l2cache_wb_range(pmap_t pm, vm_offset_t va, vm_size_t len) -{ - vm_size_t rest; - pd_entry_t *pde; - pt_entry_t *ptep; - - rest = MIN(PAGE_SIZE - (va & PAGE_MASK), len); - - while (len > 0) { - CTR4(KTR_PMAP, "pmap_l2cache_wb_range: pmap %p is_kernel %d " - "va 0x%08x len 0x%x ", pm, pm == pmap_kernel(), va, rest); - if (pmap_get_pde_pte(pm, va, &pde, &ptep) && l2pte_valid(*ptep)) - cpu_l2cache_wb_range(va, rest); - - len -= rest; - va += rest; - - rest = MIN(PAGE_SIZE, len); - } -} - -static PMAP_INLINE void -pmap_l2cache_inv_range(pmap_t pm, vm_offset_t va, vm_size_t len) -{ vm_size_t rest; - pd_entry_t *pde; - pt_entry_t *ptep; - - rest = MIN(PAGE_SIZE - (va & PAGE_MASK), len); - while (len > 0) { - CTR4(KTR_PMAP, "pmap_l2cache_wb_range: pmap %p is_kernel %d " - "va 0x%08x len 0x%x ", pm, pm == pmap_kernel(), va, rest); - if (pmap_get_pde_pte(pm, va, &pde, &ptep) && l2pte_valid(*ptep)) - cpu_l2cache_inv_range(va, rest); + CTR4(KTR_PMAP, "pmap_dcache_wbinv_range: pmap %p is_kernel %d va 0x%08x" + " len 0x%x ", pm, pm == pmap_kernel(), va, len); - len -= rest; - va += rest; - - rest = MIN(PAGE_SIZE, len); + if (pmap_is_current(pm) || pm == pmap_kernel()) { + rest = MIN(PAGE_SIZE - (va & PAGE_MASK), len); + while (len > 0) { + if (pmap_has_valid_mapping(pm, va)) { + cpu_idcache_wbinv_range(va, rest); + cpu_l2cache_wbinv_range(va, rest); + } + len -= rest; + va += rest; + rest = MIN(PAGE_SIZE, len); + } } } @@ -1279,24 +1238,31 @@ static PMAP_INLINE void pmap_dcache_wb_range(pmap_t pm, vm_offset_t va, vm_size_t len, boolean_t do_inv, boolean_t rd_only) { + vm_size_t rest; CTR4(KTR_PMAP, "pmap_dcache_wb_range: pmap %p is_kernel %d va 0x%08x " "len 0x%x ", pm, pm == pmap_kernel(), va, len); CTR2(KTR_PMAP, " do_inv %d rd_only %d", do_inv, rd_only); if (pmap_is_current(pm)) { - if (do_inv) { - if (rd_only) { - cpu_dcache_inv_range(va, len); - pmap_l2cache_inv_range(pm, va, len); - } - else { - cpu_dcache_wbinv_range(va, len); - pmap_l2cache_wbinv_range(pm, va, len); - } - } else if (!rd_only) { - cpu_dcache_wb_range(va, len); - pmap_l2cache_wb_range(pm, va, len); + rest = MIN(PAGE_SIZE - (va & PAGE_MASK), len); + while (len > 0) { + if (pmap_has_valid_mapping(pm, va)) { + if (do_inv && rd_only) { + cpu_dcache_inv_range(va, rest); + cpu_l2cache_inv_range(va, rest); + } else if (do_inv) { + cpu_dcache_wbinv_range(va, rest); + cpu_l2cache_wbinv_range(va, rest); + } else if (!rd_only) { + cpu_dcache_wb_range(va, rest); + cpu_l2cache_wb_range(va, rest); + } + } + len -= rest; + va += rest; + + rest = MIN(PAGE_SIZE, len); } } } @@ -3225,7 +3191,8 @@ pmap_remove_all(vm_page_t m) */ if (pmap_is_current(pv->pv_pmap)) { cpu_dcache_inv_range(pv->pv_va, PAGE_SIZE); - cpu_l2cache_inv_range(pv->pv_va, PAGE_SIZE); + if (pmap_has_valid_mapping(pv->pv_pmap, pv->pv_va)) + cpu_l2cache_inv_range(pv->pv_va, PAGE_SIZE); } if (pv->pv_flags & PVF_UNMAN) { @@ -3512,9 +3479,10 @@ do_l2b_alloc: if (pmap_is_current(pmap) && (oflags & PVF_NC) == 0 && (opte & L2_S_PROT_W) != 0 && - (prot & VM_PROT_WRITE) == 0) { + (prot & VM_PROT_WRITE) == 0 && + (opte & L2_TYPE_MASK) != L2_TYPE_INV) { cpu_dcache_wb_range(va, PAGE_SIZE); - pmap_l2cache_wb_range(pmap, va, PAGE_SIZE); + cpu_l2cache_wb_range(va, PAGE_SIZE); } } else { /*