svn commit: r244912 - head/sys/arm/arm
Oleksandr Tymoshenko
gonzo at FreeBSD.org
Mon Dec 31 21:00:39 UTC 2012
Author: gonzo
Date: Mon Dec 31 21:00:38 2012
New Revision: 244912
URL: http://svnweb.freebsd.org/changeset/base/244912
Log:
Merge r234561 from busdma_machdep.c to ARMv6 version of busdma:
Interrupts must be disabled while handling a partial cache line flush,
as otherwise the interrupt handling code may modify data in the non-DMA
part of the cache line while we have it stashed away in the temporary
stack buffer, then we end up restoring a stale value.
PR: 160431
Submitted by: Ian Lepore
Modified:
head/sys/arm/arm/busdma_machdep-v6.c
Modified: head/sys/arm/arm/busdma_machdep-v6.c
==============================================================================
--- head/sys/arm/arm/busdma_machdep-v6.c Mon Dec 31 16:52:52 2012 (r244911)
+++ head/sys/arm/arm/busdma_machdep-v6.c Mon Dec 31 21:00:38 2012 (r244912)
@@ -1347,35 +1347,49 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus
while (sl != NULL) {
/* write back the unaligned portions */
vm_paddr_t physaddr;
+ register_t s = 0;
+
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);
- len += unalign; /* inv entire cache line */
- }
- unalign = ebuf & arm_dcache_align_mask;
- if (unalign) {
- unalign = arm_dcache_align - unalign;
- memcpy(_tmp_clend, (void *)ebuf, unalign);
- len += unalign; /* inv entire cache line */
+
+
+ if ((buf & arm_dcache_align_mask) ||
+ (ebuf & arm_dcache_align_mask)) {
+ s = intr_disable();
+ unalign = buf & arm_dcache_align_mask;
+ if (unalign) {
+ memcpy(_tmp_cl, (void *)bbuf, unalign);
+ len += unalign; /* inv entire cache line */
+ }
+
+ unalign = ebuf & arm_dcache_align_mask;
+ if (unalign) {
+ unalign = arm_dcache_align - unalign;
+ memcpy(_tmp_clend, (void *)ebuf, unalign);
+ len += unalign; /* inv entire cache line */
+ }
}
- /* inv are cache length aligned */
+
+ /* 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) {
- memcpy((void *)bbuf, _tmp_cl, unalign);
- }
- unalign = ebuf & arm_dcache_align_mask;
- if (unalign) {
- unalign = arm_dcache_align - unalign;
- memcpy((void *)ebuf, _tmp_clend, unalign);
+ if ((buf & arm_dcache_align_mask) ||
+ (ebuf & arm_dcache_align_mask)) {
+ unalign = (vm_offset_t)buf & arm_dcache_align_mask;
+ if (unalign)
+ memcpy((void *)bbuf, _tmp_cl, unalign);
+
+ unalign = ebuf & arm_dcache_align_mask;
+ if (unalign)
+ memcpy((void *)ebuf, _tmp_clend,
+ arm_dcache_align - unalign);
+
+ intr_restore(s);
}
sl = STAILQ_NEXT(sl, slinks);
}
More information about the svn-src-head
mailing list