Subject: Changes for R5k secondary caches, please review!
To: None <port-mips@netbsd.org>
From: Rafal Boni <rafal@attbi.com>
List: port-sgimips
Date: 01/06/2003 02:07:25
Folks:
	Attached are the current set of changes I've got to handle the R5k
	secondary caches as found on the SGI O2 (both in R5k and Rm5200
	flavors).  Some cleanup still needs to be done (see also my last
	mail on naming the CP0_CONFIG bits 8-), but this should be close
	to the intended effect in form and function.

	Besides these changes, one needs the pmap hacks I posted a while
	back, as the hardware does not do virtual coherency detection.
	I would like feedback on this stuff independently of the needed
	pmap changes, as I'd like to get all the small issues sorted out
	before I go attack the pmap code.

	I'm also considering for the short term (before I get the pmap 
	issues sorted out) the pmap a `no virtual coherency detection'
	hint which would cause to behave much as it does not when there
	is no secondary cache.  Is anyone deeply grossed out by this as
	a short-term band-aid?

	I've broken out the R5k (and R4600, since AFAICT the two are more
	alike than the R4k and R4600) declarations into a separate header
	file, "cache_r5k.h", but the code still depends on the cache ops
	declared in "cache_r4k.h"; should I have the former include the
	latter, or is having the dependency implicit (as I do in these
	patches) OK?

	Changes attached, please let me know what you all think!  Giving
	credit where credit is due, almost all of this code was originally
	written by Chris Sekiya -- all bugs and butcheries after the fact
	are most likely my doing, as are some of the small improvements..

Thanks for any feedback!
--rafal

Index: conf/files.mips
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/conf/files.mips,v
retrieving revision 1.45
diff -b -u -p -r1.45 files.mips
--- conf/files.mips	2002/11/15 01:02:49	1.45
+++ conf/files.mips	2003/01/06 06:53:33
@@ -45,6 +45,7 @@ file	arch/mips/mips/cache_tx39.c		mips1 
 file	arch/mips/mips/cache_tx39_subr.S	mips1 & enable_mips_tx3900
 file	arch/mips/mips/cache_r4k.c		mips3 | mips4
 file	arch/mips/mips/cache_r5k.c		mips3 | mips4
+file	arch/mips/mips/cache_r5k_subr.S		mips3 | mips4
 file	arch/mips/mips/cache_r5900.c		mips3 & mips3_5900
 file	arch/mips/mips/cache_mipsNN.c		mips32 | mips64
 
Index: include/cache_r4k.h
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/include/cache_r4k.h,v
retrieving revision 1.8
diff -b -u -p -r1.8 cache_r4k.h
--- include/cache_r4k.h	2002/11/17 06:40:43	1.8
+++ include/cache_r4k.h	2003/01/06 06:53:34
@@ -357,29 +357,6 @@ void	r4k_pdcache_wbinv_range_index_32(va
 void	r4k_pdcache_inv_range_32(vaddr_t, vsize_t);
 void	r4k_pdcache_wb_range_32(vaddr_t, vsize_t);
 
-void	r5k_icache_sync_all_32(void);
-void	r5k_icache_sync_range_32(vaddr_t, vsize_t);
-void	r5k_icache_sync_range_index_32(vaddr_t, vsize_t);
-
-void	r5k_pdcache_wbinv_all_16(void);
-void	r5k_pdcache_wbinv_all_32(void);
-void	r4600v1_pdcache_wbinv_range_32(vaddr_t, vsize_t);
-void	r4600v2_pdcache_wbinv_range_32(vaddr_t, vsize_t);
-void	vr4131v1_pdcache_wbinv_range_16(vaddr_t, vsize_t);
-void	r5k_pdcache_wbinv_range_16(vaddr_t, vsize_t);
-void	r5k_pdcache_wbinv_range_32(vaddr_t, vsize_t);
-void	r5k_pdcache_wbinv_range_index_16(vaddr_t, vsize_t);
-void	r5k_pdcache_wbinv_range_index_32(vaddr_t, vsize_t);
-
-void	r4600v1_pdcache_inv_range_32(vaddr_t, vsize_t);
-void	r4600v2_pdcache_inv_range_32(vaddr_t, vsize_t);
-void	r5k_pdcache_inv_range_16(vaddr_t, vsize_t);
-void	r5k_pdcache_inv_range_32(vaddr_t, vsize_t);
-void	r4600v1_pdcache_wb_range_32(vaddr_t, vsize_t);
-void	r4600v2_pdcache_wb_range_32(vaddr_t, vsize_t);
-void	r5k_pdcache_wb_range_16(vaddr_t, vsize_t);
-void	r5k_pdcache_wb_range_32(vaddr_t, vsize_t);
-
 void	r4k_sdcache_wbinv_all_32(void);
 void	r4k_sdcache_wbinv_range_32(vaddr_t, vsize_t);
 void	r4k_sdcache_wbinv_range_index_32(vaddr_t, vsize_t);
Index: include/cache_r5k.h
===================================================================
RCS file: cache_r5k.h
diff -N cache_r5k.h
--- /dev/null	Mon Jan  6 08:53:12 2003
+++ cache_r5k.h	Mon Jan  6 08:53:34 2003
@@ -0,0 +1,71 @@
+/*	$NetBSD: cache_r4k.h,v 1.8 2002/11/17 06:40:43 simonb Exp $	*/
+
+/*
+ * Copyright 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed for the NetBSD Project by
+ *	Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(_KERNEL) && !defined(_LOCORE)
+
+void	r5k_icache_sync_all_32(void);
+void	r5k_icache_sync_range_32(vaddr_t, vsize_t);
+void	r5k_icache_sync_range_index_32(vaddr_t, vsize_t);
+
+void	r5k_pdcache_wbinv_all_16(void);
+void	r5k_pdcache_wbinv_all_32(void);
+void	r4600v1_pdcache_wbinv_range_32(vaddr_t, vsize_t);
+void	r4600v2_pdcache_wbinv_range_32(vaddr_t, vsize_t);
+void	vr4131v1_pdcache_wbinv_range_16(vaddr_t, vsize_t);
+void	r5k_pdcache_wbinv_range_16(vaddr_t, vsize_t);
+void	r5k_pdcache_wbinv_range_32(vaddr_t, vsize_t);
+void	r5k_pdcache_wbinv_range_index_16(vaddr_t, vsize_t);
+void	r5k_pdcache_wbinv_range_index_32(vaddr_t, vsize_t);
+
+void	r4600v1_pdcache_inv_range_32(vaddr_t, vsize_t);
+void	r4600v2_pdcache_inv_range_32(vaddr_t, vsize_t);
+void	r5k_pdcache_inv_range_16(vaddr_t, vsize_t);
+void	r5k_pdcache_inv_range_32(vaddr_t, vsize_t);
+void	r4600v1_pdcache_wb_range_32(vaddr_t, vsize_t);
+void	r4600v2_pdcache_wb_range_32(vaddr_t, vsize_t);
+void	r5k_pdcache_wb_range_16(vaddr_t, vsize_t);
+void	r5k_pdcache_wb_range_32(vaddr_t, vsize_t);
+
+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_inv_range(vaddr_t, vsize_t);
+void	r5k_sdcache_wb_range(vaddr_t, vsize_t);
+
+#endif /* _KERNEL && !_LOCORE */
Index: include/cpuregs.h
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/include/cpuregs.h,v
retrieving revision 1.58
diff -b -u -p -r1.58 cpuregs.h
--- include/cpuregs.h	2002/11/15 01:15:11	1.58
+++ include/cpuregs.h	2003/01/06 06:53:34
@@ -322,6 +322,17 @@
 	((base) << (((config) & (mask)) >> (shift)))
 #endif
 
+/* 
+ * XXXrkb: should we put the following into a different namespace, seeing
+ * as it breaks the rule of being R/O (it's actually R/W) and it's only
+ * there on the R5k, QED Rm52xx and NEC Vr5000 (which, AFAIK is just a
+ * R5k made/sold by NEC instead of MIPS)?  Actually, not sure of about
+ * the NEC Vr5400 and Vr5500 and QED Rm7000; should check those and 
+ * maybe the older QED models as well.
+ */
+/* L2 cache-enable bit for R5000/Rm52xx */
+#define MIPS3_CONFIG_SC_ENABLE	0x00001000
+
 /* Block ordering: 0: sequential, 1: sub-block */
 #define	MIPS3_CONFIG_EB		0x00002000
 
Index: mips/cache.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/mips/cache.c,v
retrieving revision 1.15
diff -b -u -p -r1.15 cache.c
--- mips/cache.c	2002/12/17 12:04:30	1.15
+++ mips/cache.c	2003/01/06 06:53:35
@@ -82,7 +82,8 @@
 #endif
 
 #ifdef MIPS3_PLUS
-#include <mips/cache_r4k.h>	/* includes r5k and greater */
+#include <mips/cache_r4k.h>
+#include <mips/cache_r5k.h>
 #endif
 
 #if defined(MIPS32) || defined(MIPS64)
@@ -619,6 +620,7 @@ primary_cache_is_2way:
 	}
 
 	mips_dcache_compute_align();
+	printf("configging sdcache\n");
 
 	if (mips_sdcache_line_size == 0)
 		return;
@@ -644,10 +646,6 @@ primary_cache_is_2way:
 #ifdef ENABLE_MIPS_R4700
 	case MIPS_R4700:
 #endif
-#ifndef ENABLE_MIPS_R3NKK
-	case MIPS_R5000:
-#endif
-	case MIPS_RM5200:
 		switch (mips_sdcache_ways) {
 		case 1:
 			switch (mips_sdcache_line_size) {
@@ -702,6 +700,22 @@ primary_cache_is_2way:
 			    mips_sdcache_ways, mips_sdcache_line_size);
 		}
 		break;
+#ifndef ENABLE_MIPS_R3NKK
+	case MIPS_R5000:
+#endif
+	case MIPS_RM5200:
+		printf("R5000/Rm5200 SCACHE\n");
+		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? */
+		mips_cache_ops.mco_sdcache_inv_range =
+		    r5k_sdcache_wbinv_range;
+		mips_cache_ops.mco_sdcache_wb_range =
+		    r5k_sdcache_wb_range;
+		break;
 #endif /* MIPS3 || MIPS4 */
 
 	default:
@@ -797,6 +811,7 @@ tx39_cache_config_write_through(void)
 void
 mips3_get_cache_config(int csizebase)
 {
+	int has_sdcache_enable = 0;
 	uint32_t config = mips3_cp0_config_read();
 
 	mips_picache_size = MIPS3_CONFIG_CACHE_SIZE(config,
@@ -814,10 +829,29 @@ mips3_get_cache_config(int csizebase)
 	mips_cache_prefer_mask =
 	    max(mips_pdcache_size, mips_picache_size) - 1;
 
+	if (MIPS_PRID_IMPL(cpu_id) == MIPS_R5000 || 
+	    MIPS_PRID_IMPL(cpu_id) == MIPS_RM5200)
+		has_sdcache_enable = 1;
+	
+	/* 
+ 	 * If CPU has a software-enabled L2 cache, check both if it's
+	 * present and if it's enabled before making assumptions the
+	 * L2 is usable.  If the L2 is disabled, we treat it the same
+	 * as if there were no L2 cache.
+	 */
 	if ((config & MIPS3_CONFIG_SC) == 0) {
-		mips_sdcache_line_size = MIPS3_CONFIG_CACHE_L2_LSIZE(config);
+		if (has_sdcache_enable == 0 ||
+		    (has_sdcache_enable && (config & MIPS3_CONFIG_SC_ENABLE))) {
+			mips_sdcache_line_size = 
+				MIPS3_CONFIG_CACHE_L2_LSIZE(config);
 		if ((config & MIPS3_CONFIG_SS) == 0)
 			mips_scache_unified = 1;
+		} else {
+#define CACHE_DEBUG
+#ifdef CACHE_DEBUG
+			printf("MIPS3 Secondary cache detected, but is disabled -- WILL NOT ENABLE!\n");
+#endif	/* CACHE_DEBUG */
+		}
 	}
 }
 #endif /* MIPS3 || MIPS4 */
Index: mips/cache_r5k.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mips/mips/cache_r5k.c,v
retrieving revision 1.6
diff -b -u -p -r1.6 cache_r5k.c
--- mips/cache_r5k.c	2002/11/07 23:03:21	1.6
+++ mips/cache_r5k.c	2003/01/06 06:53:36
@@ -39,6 +39,7 @@
 
 #include <mips/cache.h>
 #include <mips/cache_r4k.h>
+#include <mips/cache_r5k.h>
 #include <mips/locore.h>
 
 /*
@@ -581,3 +582,57 @@ r5k_pdcache_wb_range_32(vaddr_t va, vsiz
 #undef trunc_line16
 #undef round_line
 #undef trunc_line
+
+/*
+ * Cache operations for R5000-style secondary caches:
+ *
+ *	- Direct-mapped
+ *	- Write-through
+ *	- Physically indexed, physically tagged
+ *
+ */
+
+
+__asm(".set mips3");
+
+#define R5K_Page_Invalidate_S   0x17
+
+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);
+	}
+}
+
+/* XXX: want wbinv_range_index here instead? */
+void
+r5k_sdcache_wbinv_rangeall(vaddr_t va, vsize_t size)
+{
+	r5k_sdcache_wbinv_all();
+}
+
+#define	round_page(x)		(((x) + (128 * 32 - 1)) & ~(128 * 32 - 1))
+#define	trunc_page(x)		((x) & ~(128 * 32 - 1))
+
+void
+r5k_sdcache_wbinv_range(vaddr_t va, vsize_t size)
+{
+	vaddr_t eva = round_page(va + size);
+	va = trunc_page(va);
+
+	while (va < eva) {
+		cache_op_r4k_line(va, R5K_Page_Invalidate_S);
+		va += (128 * 32);
+	}
+}
+
+void
+r5k_sdcache_wb_range(vaddr_t va, vsize_t size)
+{
+	/* Write-through cache, no need to WB */
+}
Index: mips/cache_r5k_subr.S
===================================================================
RCS file: cache_r5k_subr.S
diff -N cache_r5k_subr.S
--- /dev/null	Mon Jan  6 08:53:12 2003
+++ cache_r5k_subr.S	Mon Jan  6 08:53:36 2003
@@ -0,0 +1,77 @@
+/*	$NetBSD$ 	*/
+
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permited provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <mips/asm.h>
+#include <mips/cpuregs.h>
+#include <mips/cache_r4k.h>
+#include <mips/cache_r5k.h>
+
+	.set mips3
+	.set noreorder
+
+/*
+ * r5k_enable_sdcache:
+ *
+ *	Enable and clear out the R5k secondary (unified) cache.
+ */
+LEAF_NOPROFILE(r5k_enable_sdcache)
+	lw	t2, _C_LABEL(mips_sdcache_size)
+	la	t1, MIPS_KSEG0_START
+
+	beq	t2, zero, 3f		# if no sdcache, we can bail now
+	nop
+
+	add	t2, t1, t2
+
+	la	v0, 1f
+	or	v0, MIPS_KSEG1_START
+
+	j	v0			# run the rest from uncached space
+	nop
+
+1:
+        mfc0    v0, MIPS_COP_0_CONFIG	
+        or      v1, v0, MIPS3_CONFIG_SC_ENABLE	
+        mtc0    v1, MIPS_COP_0_CONFIG	# enable the secondary cache 
+	nop
+	nop
+	nop
+
+2:
+	cache	0x17, 0(t1)		# 0x17 == Page_Invalidate_SD
+	addiu	t1, t1, 4096
+
+	sltu	v0, t1, t2
+	bne	v0, zero, 2b
+	nop
+
+3:
+	j	ra
+	nop	
+END(r5k_enable_sdcache)
+
----
Rafal Boni                                                     rafal@attbi.com
  We are all worms.  But I do believe I am a glowworm.  -- Winston Churchill