Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/atari/atari Replace bus_dmamap_sync(9) op with a ne...
details: https://anonhg.NetBSD.org/src/rev/e0c064fa10a0
branches: trunk
changeset: 321305:e0c064fa10a0
user: tsutsui <tsutsui%NetBSD.org@localhost>
date: Sat Mar 10 03:44:43 2018 +0000
description:
Replace bus_dmamap_sync(9) op with a newer one taken from m68k/bus_dma.c.
This could fix memory corruption issue caused by PREREAD ops with regions
whose boundaries are not aligned at cacheline size.
diffstat:
sys/arch/atari/atari/bus.c | 209 +++++++++++++++++++++++++++++++++++++++-----
1 files changed, 183 insertions(+), 26 deletions(-)
diffs (246 lines):
diff -r 8e5c9216ca70 -r e0c064fa10a0 sys/arch/atari/atari/bus.c
--- a/sys/arch/atari/atari/bus.c Sat Mar 10 02:48:51 2018 +0000
+++ b/sys/arch/atari/atari/bus.c Sat Mar 10 03:44:43 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: bus.c,v 1.59 2018/01/20 17:37:15 tsutsui Exp $ */
+/* $NetBSD: bus.c,v 1.60 2018/03/10 03:44:43 tsutsui Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
#include "opt_m68k_arch.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bus.c,v 1.59 2018/01/20 17:37:15 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bus.c,v 1.60 2018/03/10 03:44:43 tsutsui Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -548,46 +548,203 @@
* by bus-specific DMA map synchronization functions.
*/
void
-_bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t off,
+_bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
bus_size_t len, int ops)
{
#if defined(M68040) || defined(M68060)
- int i, pa_off, inc, seglen;
- u_long pa, end_pa;
+ bus_addr_t p, e, ps, pe;
+ bus_size_t seglen;
+ bus_dma_segment_t *seg;
+ int i;
+#endif
- pa_off = t->_displacement;
+#if defined(M68020) || defined(M68030)
+#if defined(M68040) || defined(M68060)
+ if (cputype == CPU_68020 || cputype == CPU_68030)
+#endif
+ /* assume no L2 physical cache */
+ return;
+#endif
- /* Flush granularity */
- inc = (len > 1024) ? PAGE_SIZE : 16;
+#if defined(M68040) || defined(M68060)
+ /* If the whole DMA map is uncached, do nothing. */
+ if ((map->_dm_flags & BUS_DMA_COHERENT) != 0)
+ return;
+
+ /* Short-circuit for unsupported `ops' */
+ if ((ops & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)) == 0)
+ return;
- for (i = 0; i < map->dm_nsegs && len > 0; i++) {
- if (map->dm_segs[i].ds_len <= off) {
+ /*
+ * flush/purge the cache.
+ */
+ for (i = 0; i < map->dm_nsegs && len != 0; i++) {
+ seg = &map->dm_segs[i];
+ if (seg->ds_len <= offset) {
/* Segment irrelevant - before requested offset */
- off -= map->dm_segs[i].ds_len;
+ offset -= seg->ds_len;
continue;
}
- seglen = map->dm_segs[i].ds_len - off;
+
+ /*
+ * Now at the first segment to sync; nail
+ * each segment until we have exhausted the
+ * length.
+ */
+ seglen = seg->ds_len - offset;
if (seglen > len)
seglen = len;
- len -= seglen;
- pa = map->dm_segs[i].ds_addr + off - pa_off;
- end_pa = pa + seglen;
+
+ ps = seg->ds_addr + offset;
+ pe = ps + seglen;
+
+ if (ops & BUS_DMASYNC_PREWRITE) {
+ p = ps & ~CACHELINE_MASK;
+ e = (pe + CACHELINE_MASK) & ~CACHELINE_MASK;
+
+ /* flush cacheline */
+ while ((p < e) && (p & (CACHELINE_SIZE * 8 - 1)) != 0) {
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ }
- if (inc == 16) {
- pa &= ~15;
- while (pa < end_pa) {
- DCFL(pa);
- pa += 16;
+ /* flush cachelines per 128bytes */
+ while ((p < e) && (p & PAGE_MASK) != 0) {
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ }
+
+ /* flush page */
+ while (p + PAGE_SIZE <= e) {
+ DCFP(p);
+ p += PAGE_SIZE;
}
- } else {
- pa &= ~PGOFSET;
- while (pa < end_pa) {
- DCFP(pa);
- pa += PAGE_SIZE;
+
+ /* flush cachelines per 128bytes */
+ while (p + CACHELINE_SIZE * 8 <= e) {
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ DCFL(p);
+ p += CACHELINE_SIZE;
+ }
+
+ /* flush cacheline */
+ while (p < e) {
+ DCFL(p);
+ p += CACHELINE_SIZE;
}
}
+
+ /*
+ * Normally, the `PREREAD' flag instructs us to purge the
+ * cache for the specified offset and length. However, if
+ * the offset/length is not aligned to a cacheline boundary,
+ * we may end up purging some legitimate data from the
+ * start/end of the cache. In such a case, *flush* the
+ * cachelines at the start and end of the required region.
+ */
+ else if (ops & BUS_DMASYNC_PREREAD) {
+ /* flush cacheline on start boundary */
+ if (ps & CACHELINE_MASK) {
+ DCFL(ps & ~CACHELINE_MASK);
+ }
+
+ p = (ps + CACHELINE_MASK) & ~CACHELINE_MASK;
+ e = pe & ~CACHELINE_MASK;
+
+ /* purge cacheline */
+ while ((p < e) && (p & (CACHELINE_SIZE * 8 - 1)) != 0) {
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ }
+
+ /* purge cachelines per 128bytes */
+ while ((p < e) && (p & PAGE_MASK) != 0) {
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ }
+
+ /* purge page */
+ while (p + PAGE_SIZE <= e) {
+ DCPP(p);
+ p += PAGE_SIZE;
+ }
+
+ /* purge cachelines per 128bytes */
+ while (p + CACHELINE_SIZE * 8 <= e) {
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ }
+
+ /* purge cacheline */
+ while (p < e) {
+ DCPL(p);
+ p += CACHELINE_SIZE;
+ }
+
+ /* flush cacheline on end boundary */
+ if (p < pe) {
+ DCFL(p);
+ }
+ }
+ offset = 0;
+ len -= seglen;
}
-#endif
+#endif /* defined(M68040) || defined(M68060) */
}
/*
Home |
Main Index |
Thread Index |
Old Index