Andrew Smith has reported some time ago (*cough* years...) that exiting X on zaurus would keep the console frame buffer memory uncached, thus making the console much slower.
I think the following diff would fix this. It makes sure the pv list flags are kept in sync with cacheability when bus_dma(9) forces a page to become uncached. Please test if you have a Zaurus - which I don't (-: Miod Index: arm/arm/bus_dma.c =================================================================== RCS file: /cvs/src/sys/arch/arm/arm/bus_dma.c,v retrieving revision 1.18 diff -u -p -r1.18 bus_dma.c --- arm/arm/bus_dma.c 20 Nov 2010 20:33:23 -0000 1.18 +++ arm/arm/bus_dma.c 12 Dec 2010 17:04:20 -0000 @@ -686,7 +686,9 @@ _bus_dmamem_map(bus_dma_tag_t t, bus_dma size_t ssize; bus_addr_t addr; int curseg, error; - pt_entry_t *ptep/*, pte*/; +#ifdef DEBUG_DMA + pt_entry_t *ptep; +#endif #ifdef DEBUG_DMA printf("dmamem_map: t=%p segs=%p nsegs=%x size=%lx flags=%x\n", t, @@ -735,9 +737,7 @@ _bus_dmamem_map(bus_dma_tag_t t, bus_dma if (flags & BUS_DMA_COHERENT) { cpu_dcache_wbinv_range(va, PAGE_SIZE); cpu_drain_writebuf(); - ptep = vtopte(va); - *ptep &= ~L2_S_CACHE_MASK; - PTE_SYNC(ptep); + pmap_uncache_page(va, addr); tlb_flush(); } #ifdef DEBUG_DMA Index: arm/arm/pmap.c =================================================================== RCS file: /cvs/src/sys/arch/arm/arm/pmap.c,v retrieving revision 1.29 diff -u -p -r1.29 pmap.c --- arm/arm/pmap.c 6 Dec 2010 20:57:13 -0000 1.29 +++ arm/arm/pmap.c 12 Dec 2010 17:04:22 -0000 @@ -1496,6 +1496,29 @@ pmap_vac_me_user(struct vm_page *pg, pma } /* + * Make a pmap_kernel() mapping uncached. Used by bus_dma for coherent pages. + */ +void +pmap_uncache_page(paddr_t va, vaddr_t pa) +{ + struct vm_page *pg; + struct pv_entry *pv; + pt_entry_t *pte; + + if ((pg = PHYS_TO_VM_PAGE(pa)) != NULL) { + simple_lock(&pg->mdpage.pvh_slock); + pv = pmap_find_pv(pg, pmap_kernel(), va); + if (pv != NULL) + pv->pv_flags |= PVF_NC; + simple_unlock(&pg->mdpage.pvh_slock); + } + + pte = vtopte(va); + *pte &= ~L2_S_CACHE_MASK; + PTE_SYNC(pte); +} + +/* * Modify pte bits for all ptes corresponding to the given physical address. * We use `maskbits' rather than `clearbits' because we're always passing * constants and the latter would require an extra inversion at run-time. @@ -2438,25 +2461,9 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, v void pmap_kenter_cache(vaddr_t va, paddr_t pa, vm_prot_t prot, int cacheable) { - struct vm_page *pg; - struct pv_entry *pv; - pt_entry_t *pte; - pmap_kenter_pa(va, pa, prot); - - if (cacheable == 0) { - if ((pg = PHYS_TO_VM_PAGE(pa)) != NULL) { - simple_lock(&pg->mdpage.pvh_slock); - pv = pmap_find_pv(pg, pmap_kernel(), va); - if (pv != NULL) - pv->pv_flags |= PVF_NC; - simple_unlock(&pg->mdpage.pvh_slock); - } - - pte = vtopte(va); - *pte &= ~L2_S_CACHE_MASK; - PTE_SYNC(pte); - } + if (cacheable == 0) + pmap_uncache_page(va, pa); } void Index: arm/include/pmap.h =================================================================== RCS file: /cvs/src/sys/arch/arm/include/pmap.h,v retrieving revision 1.14 diff -u -p -r1.14 pmap.h --- arm/include/pmap.h 6 Dec 2010 20:57:15 -0000 1.14 +++ arm/include/pmap.h 12 Dec 2010 17:04:23 -0000 @@ -253,6 +253,7 @@ extern int pmap_debug_level; /* Only ex void pmap_procwr(struct proc *, vaddr_t, int); void pmap_remove_all(pmap_t); boolean_t pmap_extract(pmap_t, vaddr_t, paddr_t *); +void pmap_uncache_page(paddr_t, vaddr_t); #define PMAP_NEED_PROCWR #define PMAP_GROWKERNEL /* turn on pmap_growkernel interface */