Subject: R5000 cache code fixes...
To: None <port-sgimips@netbsd.org, port-mips@netbsd.org>
From: Rafal Boni <rafal@attbi.com>
List: port-mips
Date: 04/27/2003 01:01:30
Folks:
	While looking at some performance issues on my R5k O2, I fixed
	up the R5000 cache code to actually implement an indexed write-
	back-invalidate operation for the secondary cache (rather than
	flushing the whole cache), which made a tremendous difference
	in terms of performance -- as measured by build times for some
	stuff in pkgsrc, saving up to 20% on total time it took to do
	the builds.

	While digging in that code I also found a bug in how we use the
	R5k Page_Invalidate_S cacheop... The Rm52xx manual documents the
	fact that CP0 TagLo must be zeroed before this operation (since
	this cacheop just expands to a series of Index_Store_Tag opera-
	tions internally); I also attach a fix for that.  I'm not 100%
	sure if disabling all interrupts here is necessary, but figured
	I'd better be safe so the TagLo register doesn't get reloaded
	somewhere along the way with a non-zero value -- I'd especially
	like feedback on this bit.

	Please review and send back any comments...

Thanks!
--rafal

Index: include/cache_r5k.h
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/include/cache_r5k.h,v
retrieving revision 1.1
diff -b -u -p -r1.1 cache_r5k.h
--- include/cache_r5k.h	2003/03/08 04:43:26	1.1
+++ include/cache_r5k.h	2003/04/27 04:54:10
@@ -64,7 +64,7 @@ void	r5k_enable_sdcache(void);
 
 void	r5k_sdcache_wbinv_all(void);
 void	r5k_sdcache_wbinv_range(vaddr_t, vsize_t);
-void	r5k_sdcache_wbinv_rangeall(vaddr_t, vsize_t);
+void	r5k_sdcache_wbinv_range_index(vaddr_t, vsize_t);
 void	r5k_sdcache_inv_range(vaddr_t, vsize_t);
 void	r5k_sdcache_wb_range(vaddr_t, vsize_t);
 
Index: mips/cache.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/mips/cache.c,v
retrieving revision 1.19
diff -b -u -p -r1.19 cache.c
--- mips/cache.c	2003/03/08 05:18:25	1.19
+++ mips/cache.c	2003/04/27 04:54:11
@@ -702,12 +702,14 @@ primary_cache_is_2way:
 	case MIPS_R5000:
 #endif
 	case MIPS_RM5200:
+		mips_sdcache_write_through = 1;
+
 		mips_cache_ops.mco_sdcache_wbinv_all =
 		    r5k_sdcache_wbinv_all;
 		mips_cache_ops.mco_sdcache_wbinv_range =
 		    r5k_sdcache_wbinv_range;
 		mips_cache_ops.mco_sdcache_wbinv_range_index =
-		    r5k_sdcache_wbinv_rangeall;	/* XXX? */
+		    r5k_sdcache_wbinv_range_index;
 		mips_cache_ops.mco_sdcache_inv_range =
 		    r5k_sdcache_wbinv_range;
 		mips_cache_ops.mco_sdcache_wb_range =
Index: mips/cache_r5k.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/mips/cache_r5k.c,v
retrieving revision 1.8
diff -b -u -p -r1.8 cache_r5k.c
--- mips/cache_r5k.c	2003/03/08 04:43:25	1.8
+++ mips/cache_r5k.c	2003/04/27 04:54:11
@@ -600,20 +600,20 @@ __asm(".set mips3");
 void
 r5k_sdcache_wbinv_all(void)
 {
-	vaddr_t va = MIPS_PHYS_TO_KSEG0(0);
-	vaddr_t eva = va + mips_sdcache_size;
-
-	while (va < eva) {
-		cache_op_r4k_line(va, R5K_Page_Invalidate_S);
-		va += (128 * 32);
-	}
+	r5k_sdcache_wbinv_range(MIPS_PHYS_TO_KSEG0(0), mips_sdcache_size);
 }
 
-/* XXX: want wbinv_range_index here instead? */
 void
-r5k_sdcache_wbinv_rangeall(vaddr_t va, vsize_t size)
+r5k_sdcache_wbinv_range_index(vaddr_t va, vsize_t size)
 {
-	r5k_sdcache_wbinv_all();
+	/*
+	 * 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 & (mips_sdcache_size - 1));
+	r5k_sdcache_wbinv_range(va, size);
 }
 
 #define	round_page(x)		(((x) + (128 * 32 - 1)) & ~(128 * 32 - 1))
@@ -622,13 +622,30 @@ r5k_sdcache_wbinv_rangeall(vaddr_t va, v
 void
 r5k_sdcache_wbinv_range(vaddr_t va, vsize_t size)
 {
+	uint32_t ostatus, taglo;
 	vaddr_t eva = round_page(va + size);
+
 	va = trunc_page(va);
 
+	__asm __volatile(
+		".set noreorder		\r\n"
+		".set noat		\r\n"
+		"mfc0 %0, $12		\r\n"
+		"mtc0 $0, $12		\r\n"
+		".set reorder		\r\n"
+		".set at"
+		: "=r"(ostatus));
+
+	__asm __volatile("mfc0 %0, $28" : "=r"(taglo));
+	__asm __volatile("mtc0 $0, $28");
+
 	while (va < eva) {
 		cache_op_r4k_line(va, R5K_Page_Invalidate_S);
 		va += (128 * 32);
 	}
+
+	__asm __volatile("mtc0 %0, $12; nop" :: "r"(ostatus));
+	__asm __volatile("mtc0 %0, $28; nop" :: "r"(taglo));
 }
 
 void

----
Rafal Boni                                                     rafal@attbi.com
  We are all worms.  But I do believe I am a glowworm.  -- Winston Churchill