svn commit: r227040 - in projects/armv6/sys: arm/arm conf
Olivier Houchard
cognet at FreeBSD.org
Wed Nov 2 21:48:31 UTC 2011
Author: cognet
Date: Wed Nov 2 21:48:31 2011
New Revision: 227040
URL: http://svn.freebsd.org/changeset/base/227040
Log:
Introduce ARM_L2_PIPT, as arm can have either a PIPT or a VIPT L2 cache.
Based on work by Ben Gray, as found here :
https://gitorious.org/+freebsd-omap-team/freebsd/freebsd-omap/commits/bengray-wip
Modified:
projects/armv6/sys/arm/arm/busdma_machdep-v6.c
projects/armv6/sys/arm/arm/pmap-v6.c
projects/armv6/sys/arm/arm/vm_machdep.c
projects/armv6/sys/conf/options.arm
Modified: projects/armv6/sys/arm/arm/busdma_machdep-v6.c
==============================================================================
--- projects/armv6/sys/arm/arm/busdma_machdep-v6.c Wed Nov 2 21:46:22 2011 (r227039)
+++ projects/armv6/sys/arm/arm/busdma_machdep-v6.c Wed Nov 2 21:48:31 2011 (r227040)
@@ -106,6 +106,7 @@ struct bounce_page {
struct sync_list {
vm_offset_t vaddr; /* kva of bounce buffer */
+ bus_addr_t busaddr; /* Physical address */
bus_size_t datacount; /* client data count */
STAILQ_ENTRY(sync_list) slinks;
};
@@ -785,6 +786,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm
STAILQ_INSERT_TAIL(&(map->slist), sl, slinks);
sl->vaddr = vaddr;
sl->datacount = sgsize;
+ sl->busaddr = curaddr;
}
@@ -1090,6 +1092,16 @@ _bus_dmamap_fix_user(vm_offset_t buf, bu
}
#endif
+#ifdef ARM_L2_PIPT
+#define l2cache_wb_range(va, pa, size) cpu_l2cache_wb_range(pa, size)
+#define l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range(pa, size)
+#define l2cache_inv_range(va, pa, size) cpu_l2cache_inv_range(pa, size)
+#else
+#define l2cache_wb_range(va, pa, size) cpu_l2cache_wb_range(va, size)
+#define l2cache_wbinv_range(va, pa, size) cpu_l2cache_wbinv_range(va, size)
+#define l2cache_inv_range(va, pa, size) cpu_l2cache_wbinv_range(va, size)
+#endif
+
void
_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
{
@@ -1101,6 +1113,7 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
vm_offset_t bbuf;
char _tmp_cl[arm_dcache_align], _tmp_clend[arm_dcache_align];
#endif
+ int listcount = 0;
/* if buffer was from user space, it it possible that this
* is not the same vm map. The fix is to map each page in
@@ -1116,10 +1129,10 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
/* Handle data bouncing. */
-
CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x op 0x%x "
"performing bounce", __func__, dmat, dmat->flags, op);
+ printf("FAUT QUE CA BOUNCE\n");
if (op & BUS_DMASYNC_PREWRITE) {
while (bpage != NULL) {
bcopy((void *)bpage->datavaddr,
@@ -1127,6 +1140,9 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
bpage->datacount);
cpu_dcache_wb_range((vm_offset_t)bpage->vaddr,
bpage->datacount);
+ l2cache_wb_range((vm_offset_t)bpage->vaddr,
+ (vm_offset_t)bpage->busaddr,
+ bpage->datacount);
bpage = STAILQ_NEXT(bpage, links);
}
dmat->bounce_zone->total_bounced++;
@@ -1138,6 +1154,9 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
cpu_dcache_inv_range((vm_offset_t)bpage->vaddr,
bpage->datacount);
+ l2cache_inv_range((vm_offset_t)bpage->vaddr,
+ (vm_offset_t)bpage->busaddr,
+ bpage->datacount);
while (bpage != NULL) {
bcopy((void *)bpage->vaddr,
(void *)bpage->datavaddr,
@@ -1148,6 +1167,11 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
}
}
+ sl = STAILQ_FIRST(&map->slist);
+ while (sl) {
+ listcount++;
+ sl = STAILQ_NEXT(sl, slinks);
+ }
if ((sl = STAILQ_FIRST(&map->slist)) != NULL) {
/* ARM caches are not self-snooping for dma */
@@ -1158,6 +1182,8 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
case BUS_DMASYNC_PREWRITE:
while (sl != NULL) {
cpu_dcache_wb_range(sl->vaddr, sl->datacount);
+ l2cache_wb_range(sl->vaddr, sl->busaddr,
+ sl->datacount);
sl = STAILQ_NEXT(sl, slinks);
}
break;
@@ -1165,17 +1191,23 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
case BUS_DMASYNC_PREREAD:
while (sl != NULL) {
/* write back the unaligned portions */
+ vm_paddr_t physaddr = sl->busaddr, ephysaddr;
buf = sl->vaddr;
len = sl->datacount;
ebuf = buf + len; /* end of buffer */
+ ephysaddr = physaddr + len;
unalign = buf & arm_dcache_align_mask;
if (unalign) {
/* wbinv leading fragment */
buf &= ~arm_dcache_align_mask;
+ physaddr &= ~arm_dcache_align_mask;
cpu_dcache_wbinv_range(buf,
arm_dcache_align);
+ l2cache_wbinv_range(buf, physaddr,
+ arm_dcache_align);
buf += arm_dcache_align;
- /* number byte in buffer wbinv */
+ physaddr += arm_dcache_align;
+ /* number byte in buffer wbinv */
unalign = arm_dcache_align - unalign;
if (len > unalign)
len -= unalign;
@@ -1187,11 +1219,15 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
/* wbinv trailing fragment */
len -= unalign;
ebuf -= unalign;
+ ephysaddr -= unalign;
cpu_dcache_wbinv_range(ebuf,
- arm_dcache_align);
+ arm_dcache_align);
+ l2cache_wbinv_range(ebuf, ephysaddr,
+ arm_dcache_align);
}
if (ebuf > buf) {
cpu_dcache_inv_range(buf, len);
+ l2cache_inv_range(buf, physaddr, len);
}
sl = STAILQ_NEXT(sl, slinks);
}
@@ -1200,6 +1236,8 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
case BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD:
while (sl != NULL) {
cpu_dcache_wbinv_range(sl->vaddr, sl->datacount);
+ l2cache_wbinv_range(sl->vaddr,
+ sl->busaddr, sl->datacount);
sl = STAILQ_NEXT(sl, slinks);
}
break;
@@ -1210,10 +1248,13 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
panic("_bus_dmamap_sync: wrong user map. apply fix");
while (sl != NULL) {
/* write back the unaligned portions */
+ vm_paddr_t physaddr;
buf = sl->vaddr;
len = sl->datacount;
+ physaddr = sl->busaddr;
bbuf = buf & ~arm_dcache_align_mask;
ebuf = buf + len;
+ physaddr = physaddr & ~arm_dcache_align_mask;
unalign = buf & arm_dcache_align_mask;
if (unalign) {
memcpy(_tmp_cl, (void *)bbuf, unalign);
@@ -1227,6 +1268,7 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
}
/* inv are cache length aligned */
cpu_dcache_inv_range(bbuf, len);
+ l2cache_inv_range(bbuf, physaddr, len);
unalign = (vm_offset_t)buf & arm_dcache_align_mask;
if (unalign) {
Modified: projects/armv6/sys/arm/arm/pmap-v6.c
==============================================================================
--- projects/armv6/sys/arm/arm/pmap-v6.c Wed Nov 2 21:46:22 2011 (r227039)
+++ projects/armv6/sys/arm/arm/pmap-v6.c Wed Nov 2 21:48:31 2011 (r227040)
@@ -2372,7 +2372,11 @@ pmap_change_attr(vm_offset_t sva, vm_siz
pte = *ptep &~ L2_S_CACHE_MASK;
cpu_idcache_wbinv_range(tmpva, PAGE_SIZE);
+#ifdef ARM_L2_PIPT
+ cpu_l2cache_wbinv_range(pte & L2_S_FRAME, PAGE_SIZE);
+#else
cpu_l2cache_wbinv_range(tmpva, PAGE_SIZE);
+#endif
cpu_tlb_flushID_SE(tmpva);
dprintf("%s: for va:%x ptep:%x pte:%x\n",
Modified: projects/armv6/sys/arm/arm/vm_machdep.c
==============================================================================
--- projects/armv6/sys/arm/arm/vm_machdep.c Wed Nov 2 21:46:22 2011 (r227039)
+++ projects/armv6/sys/arm/arm/vm_machdep.c Wed Nov 2 21:48:31 2011 (r227040)
@@ -485,7 +485,11 @@ arm_remap_nocache(void *addr, vm_size_t
for (; tomap < (vm_offset_t)ret + size; tomap += PAGE_SIZE,
vaddr += PAGE_SIZE, physaddr += PAGE_SIZE, i++) {
cpu_idcache_wbinv_range(vaddr, PAGE_SIZE);
+#ifdef ARM_L2_PIPT
+ cpu_l2cache_wbinv_range(physaddr, PAGE_SIZE);
+#else
cpu_l2cache_wbinv_range(vaddr, PAGE_SIZE);
+#endif
pmap_kenter_nocache(tomap, physaddr);
cpu_tlb_flushID_SE(vaddr);
arm_nocache_allocated[i / BITS_PER_INT] |= 1 << (i %
Modified: projects/armv6/sys/conf/options.arm
==============================================================================
--- projects/armv6/sys/conf/options.arm Wed Nov 2 21:46:22 2011 (r227039)
+++ projects/armv6/sys/conf/options.arm Wed Nov 2 21:48:31 2011 (r227040)
@@ -3,6 +3,7 @@ ARM9_CACHE_WRITE_THROUGH opt_global.h
ARM_CACHE_LOCK_ENABLE opt_global.h
ARMFPE opt_global.h
ARM_KERN_DIRECTMAP opt_vm.h
+ARM_L2_PIPT opt_global.h
ARM_USE_SMALL_ALLOC opt_global.h
AT91C_MASTER_CLOCK opt_global.h
AT91C_MAIN_CLOCK opt_at91.h
More information about the svn-src-projects
mailing list