Module Name: src Committed By: matt Date: Fri Mar 29 13:27:09 UTC 2013
Modified Files: src/sys/arch/arm/arm32: pmap.c Log Message: Fix pmap_flush_page to also flush the secondary cache, if there is one. This solves a bus_dma problem with DMA from uncached pages. To generate a diff of this commit: cvs rdiff -u -r1.253 -r1.254 src/sys/arch/arm/arm32/pmap.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/arm32/pmap.c diff -u src/sys/arch/arm/arm32/pmap.c:1.253 src/sys/arch/arm/arm32/pmap.c:1.254 --- src/sys/arch/arm/arm32/pmap.c:1.253 Wed Feb 13 23:14:35 2013 +++ src/sys/arch/arm/arm32/pmap.c Fri Mar 29 13:27:08 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.253 2013/02/13 23:14:35 matt Exp $ */ +/* $NetBSD: pmap.c,v 1.254 2013/03/29 13:27:08 matt Exp $ */ /* * Copyright 2003 Wasabi Systems, Inc. @@ -212,7 +212,7 @@ #include <arm/cpuconf.h> #include <arm/arm32/katelib.h> -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.253 2013/02/13 23:14:35 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.254 2013/03/29 13:27:08 matt Exp $"); #ifdef PMAP_DEBUG @@ -2502,7 +2502,7 @@ void pmap_flush_page(struct vm_page_md *md, paddr_t pa, enum pmap_flush_op flush) { vsize_t va_offset, end_va; - void (*cf)(vaddr_t, vsize_t); + bool wbinv_p; if (arm_cache_prefer_mask == 0) return; @@ -2523,19 +2523,19 @@ pmap_flush_page(struct vm_page_md *md, p * Mark that the page is no longer dirty. */ md->pvh_attrs &= ~PVF_DIRTY; - cf = cpufuncs.cf_idcache_wbinv_range; + wbinv_p = true; break; case PMAP_FLUSH_SECONDARY: va_offset = 0; end_va = arm_cache_prefer_mask; - cf = cpufuncs.cf_idcache_wbinv_range; + wbinv_p = true; md->pvh_attrs &= ~PVF_MULTCLR; PMAPCOUNT(vac_flush_lots); break; case PMAP_CLEAN_PRIMARY: va_offset = md->pvh_attrs & arm_cache_prefer_mask; end_va = va_offset; - cf = cpufuncs.cf_dcache_wb_range; + wbinv_p = false; /* * Mark that the page is no longer dirty. */ @@ -2552,6 +2552,8 @@ pmap_flush_page(struct vm_page_md *md, p NPDEBUG(PDB_VAC, printf("pmap_flush_page: md=%p (attrs=%#x)\n", md, md->pvh_attrs)); + const size_t scache_line_size = arm_scache.dcache_line_size; + for (; va_offset <= end_va; va_offset += PAGE_SIZE) { const size_t pte_offset = va_offset >> PGSHIFT; pt_entry_t * const ptep = &cdst_pte[pte_offset]; @@ -2575,7 +2577,22 @@ pmap_flush_page(struct vm_page_md *md, p /* * Flush it. */ - (*cf)(cdstp + va_offset, PAGE_SIZE); + vaddr_t va = cdstp + va_offset; + if (scache_line_size != 0) { + cpu_dcache_wb_range(va, PAGE_SIZE); + if (wbinv_p) { + cpu_sdcache_wbinv_range(va, pa, PAGE_SIZE); + cpu_dcache_inv_range(va, PAGE_SIZE); + } else { + cpu_sdcache_wb_range(va, pa, PAGE_SIZE); + } + } else { + if (wbinv_p) { + cpu_dcache_wbinv_range(va, PAGE_SIZE); + } else { + cpu_dcache_wb_range(va, PAGE_SIZE); + } + } /* * Restore the page table entry since we might have interrupted