diff options
-rw-r--r-- | sys/arch/mvme88k/mvme88k/m88110.c | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/sys/arch/mvme88k/mvme88k/m88110.c b/sys/arch/mvme88k/mvme88k/m88110.c index deb4525c1e8..acc86352093 100644 --- a/sys/arch/mvme88k/mvme88k/m88110.c +++ b/sys/arch/mvme88k/mvme88k/m88110.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m88110.c,v 1.63 2009/04/19 17:56:13 miod Exp $ */ +/* $OpenBSD: m88110.c,v 1.64 2010/04/17 22:10:13 miod Exp $ */ /* * Copyright (c) 1998 Steve Murphree, Jr. * All rights reserved. @@ -488,6 +488,30 @@ m88110_flush_tlb(cpuid_t cpu, u_int kernel, vaddr_t vaddr, u_int count) * will occur before we do, it is not necessary to pay attention to this. */ +#ifdef MULTIPROCESSOR +/* + * 88110 rev 4.2 errata #17: + * ``A copyback initiated by a flush page/line with invalidate command, + * which is retried on the external bus, and is preceded by a snoop + * copyback before the retry cycle occurs, can be incorrectly marked + * as invalid, and not copied back to memory. + * Suggested fix: Use flush page/line followed by flush page/line with + * invalidate to avoid this condition.'' + * + * This really only matters to us when running a MULTIPROCESSOR kernel + * (otherwise there is no snooping happening), and given the intrusive + * changes it requires (see the comment about invalidates being turned + * into flushes with invalidate in m88110_cmmu_inval_cache below), as + * well as the small performance impact it has), we define a specific + * symbol to enable the suggested workaround. + * + * Also, note that m88110_dma_cachectl() is never invoked when running on + * a multiprocessor system, therefore does not need to implement this + * workaround. + */ +#define ENABLE_88110_ERRATA_17 +#endif + #define trunc_cache_line(a) ((a) & ~(MC88110_CACHE_LINE - 1)) #define round_cache_line(a) trunc_cache_line((a) + MC88110_CACHE_LINE - 1) @@ -577,19 +601,28 @@ m88410_flush_inst_cache(cpuid_t cpu, paddr_t pa, psize_t size) void m88110_cmmu_sync_cache(paddr_t pa, psize_t size) { +#ifdef ENABLE_88110_ERRATA_17 + mc88110_flush_data_page(pa); +#else if (size <= MC88110_CACHE_LINE) mc88110_flush_data_line(pa); else mc88110_flush_data_page(pa); +#endif } void m88110_cmmu_sync_inval_cache(paddr_t pa, psize_t size) { +#ifdef ENABLE_88110_ERRATA_17 + mc88110_flush_data_page(pa); + mc88110_sync_data_page(pa); +#else if (size <= MC88110_CACHE_LINE) mc88110_sync_data_line(pa); else mc88110_sync_data_page(pa); +#endif } void @@ -678,7 +711,11 @@ m88410_dma_cachectl_local(paddr_t pa, psize_t size, int op) ext_flusher = mc88410_sync; break; default: +#ifdef ENABLE_88110_ERRATA_17 + flusher = m88110_cmmu_sync_inval_cache; +#else flusher = m88110_cmmu_inval_cache; +#endif #ifdef notyet ext_flusher = mc88410_inval; #else @@ -702,8 +739,12 @@ m88410_dma_cachectl_local(paddr_t pa, psize_t size, int op) } else { mc88110_inval_inst(); while (size != 0) { +#ifdef ENABLE_88110_ERRATA_17 + count = PAGE_SIZE; +#else count = (pa & PAGE_MASK) == 0 && size >= PAGE_SIZE ? PAGE_SIZE : MC88110_CACHE_LINE; +#endif (*flusher)(pa, count); @@ -724,6 +765,15 @@ m88410_dma_cachectl(paddr_t _pa, psize_t _size, int op) paddr_t pa; psize_t size; +#ifdef ENABLE_88110_ERRATA_17 + pa = trunc_page(_pa); + size = round_page(_pa + _size) - pa; + +#if 0 /* not required since m88410_dma_cachectl_local() behaves identically */ + if (op == DMA_CACHE_INV) + op = DMA_CACHE_SYNC_INVAL; +#endif +#else if (op == DMA_CACHE_SYNC) { pa = trunc_page(_pa); size = round_page(_pa + _size) - pa; @@ -736,6 +786,7 @@ m88410_dma_cachectl(paddr_t _pa, psize_t _size, int op) op = DMA_CACHE_SYNC_INVAL; } } +#endif m88410_dma_cachectl_local(pa, size, op); #ifdef MULTIPROCESSOR |