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