[RFC] [yeeloong] cache algorithms

Vladimir 'φ-coder/phcoder' Serbinenko phcoder at gmail.com
Mon Sep 27 11:08:50 UTC 2010


On 09/27/2010 09:21 AM, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
> On Loongson the cache maintenance routines are subtly different (took me
> a very long time to figure out). Here I attach the patch which would
> adapt the algorithms for Loongson but it would also break other CPUs so
> I would like your comment on how to best incorporate it into current
> tree? The problems are:
> 1) Other bits are used to specify the way
> 2) i-cache has only index_invalidate and no hit_invalidate
> 3) secondary cache flush is a must on dma operations
> Is it better to copy-paste mipsNN_* to something like mipsNN_loongson_*
> or is it better to use #ifdef's ?
> Should I define mips_sdcache_* to a nop on non-Loongson?
>
>
>   


-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko

-------------- next part --------------
=== modified file 'mips/mips/bus_space_generic.c'
--- mips/mips/bus_space_generic.c	2010-08-13 22:16:49 +0000
+++ mips/mips/bus_space_generic.c	2010-08-15 04:18:21 +0000
@@ -593,6 +593,9 @@
 {
 #if 0
 	if (flags & BUS_SPACE_BARRIER_WRITE)
+	{
 		mips_dcache_wbinv_all();
+		mips_sdcache_wbinv_all();
+	}
 #endif
 }

=== modified file 'mips/mips/busdma_machdep.c'
--- mips/mips/busdma_machdep.c	2010-08-13 22:16:49 +0000
+++ mips/mips/busdma_machdep.c	2010-08-17 14:02:19 +0000
@@ -638,6 +638,8 @@
 			newmap->allocbuffer = tmpaddr;
 			mips_dcache_wbinv_range((vm_offset_t)*vaddr,
 			    dmat->maxsize);
+			mips_sdcache_wbinv_range((vm_offset_t)*vaddr,
+			    dmat->maxsize);
 			*vaddr = tmpaddr;
 		} else
 			newmap->origbuffer = newmap->allocbuffer = NULL;
@@ -1074,6 +1079,7 @@
 		if (size_clend)
 			memcpy (tmp_clend, (void*)buf_clend, size_clend);
 		mips_dcache_inv_range((vm_offset_t)buf, len);
+		mips_sdcache_inv_range((vm_offset_t)buf, len);
 		/* 
 		 * Restore them
 		 */
@@ -1088,15 +1094,23 @@
 		 * necessary.
 		 */
 		if (size_cl)
+		{
 			mips_dcache_wbinv_range((vm_offset_t)buf_cl, size_cl);
+			mips_sdcache_wbinv_range((vm_offset_t)buf_cl, size_cl);
+		}
 		if (size_clend && (size_cl == 0 ||
                     buf_clend - buf_cl > mips_pdcache_linesize))
+		{
 			mips_dcache_wbinv_range((vm_offset_t)buf_clend,
 			   size_clend);
+			mips_sdcache_wbinv_range((vm_offset_t)buf_clend,
+			   size_clend);
+		}
 		break;
 
 	case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE:
 		mips_dcache_wbinv_range((vm_offset_t)buf_cl, len);
+		mips_sdcache_wbinv_range((vm_offset_t)buf_cl, len);
 		break;
 
 	case BUS_DMASYNC_PREREAD:
@@ -1108,6 +1122,7 @@
 		if (size_clend)
 			memcpy (tmp_clend, (void *)buf_clend, size_clend);
 		mips_dcache_inv_range((vm_offset_t)buf, len);
+		mips_sdcache_inv_range((vm_offset_t)buf, len);
 		/*
 		 * Restore them
 		 */
@@ -1122,15 +1137,23 @@
 		 * necessary.
 		 */
 		if (size_cl)
+		{
 			mips_dcache_wbinv_range((vm_offset_t)buf_cl, size_cl);
+			mips_sdcache_wbinv_range((vm_offset_t)buf_cl, size_cl);
+		}
 		if (size_clend && (size_cl == 0 ||
                     buf_clend - buf_cl > mips_pdcache_linesize))
+		{
 			mips_dcache_wbinv_range((vm_offset_t)buf_clend,
 			   size_clend);
+			mips_sdcache_wbinv_range((vm_offset_t)buf_clend,
+			   size_clend);
+		}
 		break;
 
 	case BUS_DMASYNC_PREWRITE:
 		mips_dcache_wb_range((vm_offset_t)buf, len);
+		mips_sdcache_wb_range((vm_offset_t)buf, len);
 		break;
 	}
 }
@@ -1149,6 +1172,8 @@
 			if (bpage->vaddr_nocache == 0) {
 				mips_dcache_wb_range(bpage->vaddr,
 				    bpage->datacount);
+				mips_sdcache_wb_range(bpage->vaddr,
+				    bpage->datacount);
 			}
 			dmat->bounce_zone->total_bounced++;
 		}
@@ -1156,6 +1181,8 @@
 			if (bpage->vaddr_nocache == 0) {
 				mips_dcache_inv_range(bpage->vaddr,
 				    bpage->datacount);
+				mips_sdcache_inv_range(bpage->vaddr,
+				    bpage->datacount);
 			}
 			bcopy((void *)(bpage->vaddr_nocache != 0 ? 
 	       		    bpage->vaddr_nocache : bpage->vaddr),

=== modified file 'mips/include/cache.h'
--- mips/include/cache.h	2010-08-13 22:16:49 +0000
+++ mips/include/cache.h	2010-08-15 07:38:23 +0000
@@ -213,6 +213,22 @@
 #define mips_intern_dcache_wb_range(v, s)				\
 	__mco_2args(intern_, dcache_wb_range, (v), (s))
 
+#define	mips_sdcache_wbinv_all()					\
+	__mco_noargs(, dcache_wbinv_all)
+
+#define	mips_sdcache_wbinv_range(v, s)					\
+	__mco_2args(, dcache_wbinv_range, (v), (s))
+
+#define	mips_sdcache_wbinv_range_index(v, s)				\
+	__mco_2args(, dcache_wbinv_range_index, (v), (s))
+
+#define	mips_sdcache_inv_range(v, s)					\
+	__mco_2args(, dcache_inv_range, (v), (s))
+
+#define	mips_sdcache_wb_range(v, s)					\
+	__mco_2args(, dcache_wb_range, (v), (s))
+
+
 /* forward declaration */
 struct mips_cpuinfo;
 

=== modified file 'mips/include/cache_mipsNN.h'
--- mips/include/cache_mipsNN.h	2010-08-13 22:16:49 +0000
+++ mips/include/cache_mipsNN.h	2010-08-15 07:39:31 +0000
@@ -57,6 +57,13 @@
 void	mipsNN_pdcache_inv_range_32(vm_offset_t, vm_size_t);
 void	mipsNN_pdcache_wb_range_16(vm_offset_t, vm_size_t);
 void	mipsNN_pdcache_wb_range_32(vm_offset_t, vm_size_t);
+
+void	mipsNN_sdcache_wbinv_all_32(void);
+void	mipsNN_sdcache_wbinv_range_32(vm_offset_t, vm_size_t);
+void	mipsNN_sdcache_wbinv_range_index_32(vm_offset_t, vm_size_t);
+void	mipsNN_sdcache_inv_range_32(vm_offset_t, vm_size_t);
+void	mipsNN_sdcache_wb_range_32(vm_offset_t, vm_size_t);
+
 #ifdef CPU_CNMIPS
 void	mipsNN_icache_sync_all_128(void);
 void	mipsNN_icache_sync_range_128(vm_offset_t, vm_size_t);

=== modified file 'mips/include/cpuinfo.h'
--- mips/include/cpuinfo.h	2010-08-13 22:16:49 +0000
+++ mips/include/cpuinfo.h	2010-08-15 07:43:39 +0000
@@ -67,6 +67,12 @@
 		u_int8_t	dc_nways;
 		u_int16_t	dc_nsets;
 	} l1;
+	struct {
+		u_int32_t	dc_size;
+		u_int8_t	dc_linesize;
+		u_int8_t	dc_nways;
+		u_int16_t	dc_nsets;
+	} l2;
 };
 
 extern struct mips_cpuinfo cpuinfo;

=== modified file 'mips/include/cpuregs.h'
--- mips/include/cpuregs.h	2010-08-13 22:16:49 +0000
+++ mips/include/cpuregs.h	2010-08-15 11:09:51 +0000
@@ -136,6 +136,10 @@
 #define	MIPS_CCA_UC		0x02	/* Uncached. */
 #define	MIPS_CCA_C		0x03	/* Cacheable, coherency unspecified. */
 
+#if defined (CPU_R10000) || defined (TARGET_YEELOONG)
+#define	MIPS_CCA_UA	0x07
+#endif
+
 #if defined(CPU_R4000) || defined(CPU_R10000)
 #define	MIPS_CCA_CNC	0x03
 #define	MIPS_CCA_CCE	0x04
@@ -145,10 +149,6 @@
 #define	MIPS_CCA_CCUOW	0x06
 #endif
 
-#ifdef CPU_R10000
-#define	MIPS_CCA_UA	0x07
-#endif
-
 #define	MIPS_CCA_CACHED	MIPS_CCA_CCEW
 #endif /* defined(CPU_R4000) || defined(CPU_R10000) */
 
@@ -188,8 +188,14 @@
 #define	MIPS_XKSEG_START		0xc000000000000000
 #define	MIPS_XKSEG_END			0xc00000ff80000000
 
+#if __mips == 32 || __mips == 64
+#define SSNOP ssnop
+#else
+#define SSNOP nop
+#endif
+ 
 /* CPU dependent mtc0 hazard hook */
-#ifdef CPU_CNMIPS
+#if defined (CPU_CNMIPS) || defined (TARGET_YEELOONG)
 #define	COP0_SYNC  nop; nop; nop; nop; nop;
 #elif defined(CPU_SB1)
 #define COP0_SYNC  ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop; ssnop
@@ -416,7 +422,7 @@
 #define	MIPS_VEC_EJTAG		0xBFC00480
 #define	MIPS_VEC_TLB		0x80000000
 #define	MIPS_VEC_XTLB		0x80000080
-#define	MIPS_VEC_CACHE		0x80000100
+#define	MIPS_VEC_CACHE		0xa0000100
 #define	MIPS_VEC_GENERIC	0x80000180	/* Most exceptions */
 #define	MIPS_VEC_INTERRUPT	0x80000200
 

=== modified file 'mips/mips/cache.c'
--- mips/mips/cache.c	2010-08-13 22:16:49 +0000
+++ mips/mips/cache.c	2010-08-15 04:07:37 +0000
@@ -194,6 +194,28 @@
 		    cpuinfo->l1.dc_linesize);
 	}
 
+	switch (cpuinfo->l2.dc_linesize) {
+	case 32:
+		mips_cache_ops.mco_sdcache_wbinv_all =
+		    mips_cache_ops.mco_intern_sdcache_wbinv_all =
+		    mipsNN_sdcache_wbinv_all_32;
+		mips_cache_ops.mco_sdcache_wbinv_range =
+		    mipsNN_sdcache_wbinv_range_32;
+		mips_cache_ops.mco_sdcache_wbinv_range_index =
+		    mips_cache_ops.mco_intern_sdcache_wbinv_range_index =
+		    mipsNN_sdcache_wbinv_range_index_32;
+		mips_cache_ops.mco_sdcache_inv_range =
+		    mipsNN_sdcache_inv_range_32;
+		mips_cache_ops.mco_sdcache_wb_range =
+		    mips_cache_ops.mco_intern_sdcache_wb_range =
+		    mipsNN_sdcache_wb_range_32;
+		break;
+	default:
+		panic("no SDcache ops for %d byte lines",
+		    cpuinfo->l1.dc_linesize);
+	}
+
+
 	mipsNN_cache_init(cpuinfo);
 
 #if 0

=== modified file 'mips/mips/cache_mipsNN.c'
--- mips/mips/cache_mipsNN.c	2010-08-13 22:16:49 +0000
+++ mips/mips/cache_mipsNN.c	2010-08-16 22:00:16 +0000
@@ -82,6 +82,12 @@
 static int pdcache_loopcount;
 static int pdcache_way_mask;
 
+static int sdcache_size;
+static int sdcache_stride;
+static int sdcache_loopcount;
+static int sdcache_way_mask;
+
+
 void
 mipsNN_cache_init(struct mips_cpuinfo * cpuinfo)
 {
@@ -115,6 +121,15 @@
 		    cpuinfo->l1.dc_nways;
 	}
 
+	if (cpuinfo->l2.dc_nsets * cpuinfo->l2.dc_linesize < PAGE_SIZE) {
+		sdcache_stride = cpuinfo->l2.dc_nsets * cpuinfo->l2.dc_linesize;
+		sdcache_loopcount = cpuinfo->l2.dc_nways;
+	} else {
+		sdcache_stride = PAGE_SIZE;
+		sdcache_loopcount = (cpuinfo->l2.dc_nsets * cpuinfo->l2.dc_linesize / PAGE_SIZE) *
+		    cpuinfo->l2.dc_nways;
+	}
+
 	mips_picache_linesize = cpuinfo->l1.ic_linesize;
 	mips_pdcache_linesize = cpuinfo->l1.dc_linesize;
 
@@ -123,6 +138,9 @@
 	pdcache_size = cpuinfo->l1.dc_size;
 	pdcache_way_mask = cpuinfo->l1.dc_nways - 1;
 
+	sdcache_size = cpuinfo->l2.dc_size;
+	sdcache_way_mask = cpuinfo->l2.dc_nways - 1;
+
 #define CACHE_DEBUG
 #ifdef CACHE_DEBUG
 	printf("Cache info:\n");
@@ -181,6 +199,12 @@
 	SYNC;
 }
 
+#if __mips == 3
+#define HIT_I_INV CACHE_R4K_I|CACHEOP_R4K_INDEX_INV
+#else
+#define HIT_I_INV CACHE_R4K_I|CACHEOP_R4K_HIT_INV
+#endif
+
 void
 mipsNN_icache_sync_range_16(vm_offset_t va, vm_size_t size)
 {
@@ -192,12 +216,12 @@
 	mips_intern_dcache_wb_range(va, (eva - va));
 
 	while ((eva - va) >= (32 * 16)) {
-		cache_r4k_op_32lines_16(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
+		cache_r4k_op_32lines_16(va, HIT_I_INV);
 		va += (32 * 16);
 	}
 
 	while (va < eva) {
-		cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
+		cache_op_r4k_line(va, HIT_I_INV);
 		va += 16;
 	}
 
@@ -215,12 +239,12 @@
 	mips_intern_dcache_wb_range(va, (eva - va));
 
 	while ((eva - va) >= (32 * 32)) {
-		cache_r4k_op_32lines_32(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
+		cache_r4k_op_32lines_32(va, HIT_I_INV);
 		va += (32 * 32);
 	}
 
 	while (va < eva) {
-		cache_op_r4k_line(va, CACHE_R4K_I|CACHEOP_R4K_HIT_INV);
+		cache_op_r4k_line(va, HIT_I_INV);
 		va += 32;
 	}
 
@@ -230,7 +254,7 @@
 void
 mipsNN_icache_sync_range_index_16(vm_offset_t va, vm_size_t size)
 {
-	unsigned int eva, tmpva;
+	vm_offset_t eva, tmpva;
 	int i, stride, loopcount;
 
 	/*
@@ -273,8 +297,8 @@
 void
 mipsNN_icache_sync_range_index_32(vm_offset_t va, vm_size_t size)
 {
-	unsigned int eva, tmpva;
-	int i, stride, loopcount;
+	vm_offset_t eva, tmpva;
+	int stride, loopcount;
 
 	/*
 	 * Since we're doing Index ops, we expect to not be able
@@ -282,7 +306,7 @@
 	 * bits that determine the cache index, and make a KSEG0
 	 * address out of them.
 	 */
-	va = MIPS_PHYS_TO_KSEG0(va & picache_way_mask);
+	va = MIPS_PHYS_TO_KSEG0(va & 0x3fe0);
 
 	eva = round_line32(va + size);
 	va = trunc_line32(va);
@@ -298,7 +322,7 @@
 
 	while ((eva - va) >= (8 * 32)) {
 		tmpva = va;
-		for (i = 0; i < loopcount; i++, tmpva += stride)
+//		for (i = 0; i < loopcount; i++, tmpva += stride)
 			cache_r4k_op_8lines_32(tmpva,
 			    CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
 		va += 8 * 32;
@@ -306,7 +330,7 @@
 
 	while (va < eva) {
 		tmpva = va;
-		for (i = 0; i < loopcount; i++, tmpva += stride)
+		//	for (i = 0; i < loopcount; i++, tmpva += stride)
 			cache_op_r4k_line(tmpva,
 			    CACHE_R4K_I|CACHEOP_R4K_INDEX_INV);
 		va += 32;
@@ -351,12 +375,19 @@
 	while (va < eva) {
 		cache_r4k_op_32lines_32(va,
 		    CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
+		cache_r4k_op_32lines_32(va + 1,
+		    CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
+		cache_r4k_op_32lines_32(va + 2,
+		    CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
+		cache_r4k_op_32lines_32(va + 3,
+		    CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
 		va += (32 * 32);
 	}
 
 	SYNC;
 }
 
+
 void
 mipsNN_pdcache_wbinv_range_16(vm_offset_t va, vm_size_t size)
 {
@@ -390,11 +421,20 @@
 	while ((eva - va) >= (32 * 32)) {
 		cache_r4k_op_32lines_32(va,
 		    CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
+		cache_r4k_op_32lines_32(va + 1,
+		    CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
+		cache_r4k_op_32lines_32(va + 2,
+		    CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
+		cache_r4k_op_32lines_32(va + 3,
+		    CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
 		va += (32 * 32);
 	}
 
 	while (va < eva) {
 		cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
+		cache_op_r4k_line(va + 1, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
+		cache_op_r4k_line(va + 2, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
+		cache_op_r4k_line(va + 3, CACHE_R4K_D|CACHEOP_R4K_HIT_WB_INV);
 		va += 32;
 	}
 
@@ -413,7 +453,7 @@
 	 * bits that determine the cache index, and make a KSEG0
 	 * address out of them.
 	 */
-	va = MIPS_PHYS_TO_KSEG0(va & pdcache_way_mask);
+	va = MIPS_PHYS_TO_KSEG0(va & 0x3ff);
 
 	eva = round_line16(va + size);
 	va = trunc_line16(va);
@@ -427,7 +467,7 @@
 
 	while ((eva - va) >= (8 * 16)) {
 		tmpva = va;
-		for (i = 0; i < loopcount; i++, tmpva += stride)
+		for (i = 0; i < 4; i++, tmpva ++)
 			cache_r4k_op_8lines_16(tmpva,
 			    CACHE_R4K_D|CACHEOP_R4K_INDEX_WB_INV);
 		va += 8 * 16;
@@ -454,7 +494,7 @@
 	 * bits that determine the cache index, and make a KSEG0
 	 * address out of them.
 	 */
-	va = MIPS_PHYS_TO_KSEG0(va & pdcache_way_mask);
+	va = MIPS_PHYS_TO_KSEG0 (va & pdcache_way_mask);
 
 	eva = round_line32(va + size);
 	va = trunc_line32(va);
@@ -482,7 +522,7 @@
 		va += 32;
 	}
 }
- 
+
 void
 mipsNN_pdcache_inv_range_16(vm_offset_t va, vm_size_t size)
 {
@@ -514,11 +554,18 @@
 
 	while ((eva - va) >= (32 * 32)) {
 		cache_r4k_op_32lines_32(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
+		cache_r4k_op_32lines_32(va + 1, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
+		cache_r4k_op_32lines_32(va + 2, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
+		cache_r4k_op_32lines_32(va + 3, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
+
 		va += (32 * 32);
 	}
 
 	while (va < eva) {
 		cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
+		cache_op_r4k_line(va + 1, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
+		cache_op_r4k_line(va + 2, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
+		cache_op_r4k_line(va + 3, CACHE_R4K_D|CACHEOP_R4K_HIT_INV);
 		va += 32;
 	}
 
@@ -556,18 +603,23 @@
 
 	while ((eva - va) >= (32 * 32)) {
 		cache_r4k_op_32lines_32(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
+		cache_r4k_op_32lines_32(va + 1, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
+		cache_r4k_op_32lines_32(va + 2, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
+		cache_r4k_op_32lines_32(va + 3, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
 		va += (32 * 32);
 	}
 
 	while (va < eva) {
 		cache_op_r4k_line(va, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
+		cache_op_r4k_line(va + 1, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
+		cache_op_r4k_line(va + 2, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
+		cache_op_r4k_line(va + 3, CACHE_R4K_D|CACHEOP_R4K_HIT_WB);
 		va += 32;
 	}
 
 	SYNC;
 }
 
-
 #ifdef CPU_CNMIPS
 
 void
@@ -617,3 +669,136 @@
 }
 
 #endif
+
+void
+mipsNN_sdcache_wbinv_all_32(void)
+{
+	vm_offset_t va, eva;
+
+	va = MIPS_PHYS_TO_KSEG0(0);
+	eva = va + sdcache_size;
+
+	/*
+	 * Since we're hitting the whole thing, we don't have to
+	 * worry about the N different "ways".
+	 */
+
+	while (va < eva) {
+		cache_r4k_op_32lines_32(va,
+		    CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
+		cache_r4k_op_32lines_32(va + 1,
+		    CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
+		cache_r4k_op_32lines_32(va + 2,
+		    CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
+		cache_r4k_op_32lines_32(va + 3,
+		    CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
+		va += (32 * 32);
+	}
+
+	SYNC;
+}
+
+void
+mipsNN_sdcache_wbinv_range_32(vm_offset_t va, vm_size_t size)
+{
+	vm_offset_t eva;
+
+	eva = round_line32(va + size);
+	va = trunc_line32(va);
+
+	while ((eva - va) >= (32 * 32)) {
+		cache_r4k_op_32lines_32(va,
+		    CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
+		va += (32 * 32);
+	}
+
+	while (va < eva) {
+		cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB_INV);
+		va += 32;
+	}
+
+	SYNC;
+}
+
+void
+mipsNN_sdcache_wbinv_range_index_32(vm_offset_t va, vm_size_t size)
+{
+	vm_offset_t eva, tmpva;
+	int i, stride, loopcount;
+
+	/*
+	 * Since we're doing Index ops, we expect to not be able
+	 * to access the address we've been given.  So, get the
+	 * bits that determine the cache index, and make a KSEG0
+	 * address out of them.
+	 */
+	va = MIPS_PHYS_TO_KSEG0 (va & 0x1ffff);
+
+	eva = round_line32(va + size);
+	va = trunc_line32(va);
+
+	/*
+	 * GCC generates better code in the loops if we reference local
+	 * copies of these global variables.
+	 */
+	stride = sdcache_stride;
+	loopcount = sdcache_loopcount;
+
+	while ((eva - va) >= (8 * 32)) {
+		tmpva = va;
+		for (i = 0; i < 4; i++, tmpva++)
+			cache_r4k_op_8lines_32(tmpva,
+			    CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
+		va += 8 * 32;
+	}
+
+	while (va < eva) {
+		tmpva = va;
+		for (i = 0; i < loopcount; i++, tmpva += stride)
+			cache_op_r4k_line(tmpva,
+			    CACHE_R4K_SD|CACHEOP_R4K_INDEX_WB_INV);
+		va += 32;
+	}
+}
+
+void
+mipsNN_sdcache_inv_range_32(vm_offset_t va, vm_size_t size)
+{
+	vm_offset_t eva;
+
+	eva = round_line32(va + size);
+	va = trunc_line32(va);
+
+	while ((eva - va) >= (32 * 32)) {
+		cache_r4k_op_32lines_32(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
+		va += (32 * 32);
+	}
+
+	while (va < eva) {
+		cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_INV);
+		va += 32;
+	}
+
+	SYNC;
+}
+
+void
+mipsNN_sdcache_wb_range_32(vm_offset_t va, vm_size_t size)
+{
+	vm_offset_t eva;
+
+	eva = round_line32(va + size);
+	va = trunc_line32(va);
+
+	while ((eva - va) >= (32 * 32)) {
+		cache_r4k_op_32lines_32(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
+		va += (32 * 32);
+	}
+
+	while (va < eva) {
+		cache_op_r4k_line(va, CACHE_R4K_SD|CACHEOP_R4K_HIT_WB);
+		va += 32;
+	}
+
+	SYNC;
+}

=== modified file 'mips/mips/machdep.c'
--- mips/mips/machdep.c	2010-08-13 22:16:49 +0000
+++ mips/mips/machdep.c	2010-08-17 11:49:47 +0000
@@ -232,7 +232,8 @@
 void
 cpu_flush_dcache(void *ptr, size_t len)
 {
-	/* TBD */
+	mips_dcache_wbinv_range((vm_offset_t)ptr, len);
+	mips_sdcache_wbinv_range((vm_offset_t)ptr, len);
 }
 
 /* Get current clock frequency for the given cpu id. */
@@ -351,6 +353,7 @@
 	 */
 	mips_icache_sync_all();
 	mips_dcache_wbinv_all();
+	mips_sdcache_wbinv_all();
 
 	/* 
 	 * Mask all interrupts. Each interrupt will be enabled
=== modified file 'mips/mips/mp_machdep.c'
--- mips/mips/mp_machdep.c	2010-08-13 22:16:49 +0000
+++ mips/mips/mp_machdep.c	2010-08-15 04:18:27 +0000
@@ -272,6 +272,7 @@
 	 * on the BSP.
 	 */
 	mips_dcache_wbinv_all();
+	mips_sdcache_wbinv_all();
 	mips_icache_sync_all();
 
 	mips_sync();

=== modified file 'mips/mips/uio_machdep.c'
--- mips/mips/uio_machdep.c	2010-08-13 22:16:49 +0000
+++ mips/mips/uio_machdep.c	2010-08-15 09:23:26 +0000
@@ -100,6 +100,7 @@
 			 * in order to get it overwritten by correct data
 			 */
 			mips_dcache_wbinv_range((vm_offset_t)cp, cnt);
+			mips_sdcache_wbinv_range((vm_offset_t)cp, cnt);
 			pmap_flush_pvcache(m);
 		} else {
 			sf = sf_buf_alloc(m, 0);
@@ -131,7 +132,10 @@
 		if (sf != NULL)
 			sf_buf_free(sf);
 		else
+		{
 			mips_dcache_wbinv_range((vm_offset_t)cp, cnt);
+			mips_sdcache_wbinv_range((vm_offset_t)cp, cnt);
+		}
 		iov->iov_base = (char *)iov->iov_base + cnt;
 		iov->iov_len -= cnt;
 		uio->uio_resid -= cnt;


More information about the freebsd-mips mailing list