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