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 */

Reply via email to