[PATCH 5/6] RM9000 arch, WAR

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



- Add code to flush scache also (need to revisit if any missing)
- Add init code for scache
- Add WAR for E9000 ENTRYHI bug, aha! And this brings back OPCODE for "or"

Signed-off-by: Kiran Kumar Thota <kiran_thota@xxxxxxxxxxxxxx>


diff -Naur a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
--- a/arch/mips/mm/c-r4k.c	2005-07-11 11:28:10.000000000 -0700
+++ b/arch/mips/mm/c-r4k.c	2006-06-22 11:48:21.000000000 -0700
@@ -649,7 +649,11 @@
 		a = addr & ~(dc_lsize - 1);
 		end = (addr + size - 1) & ~(dc_lsize - 1);
 		while (1) {
+#ifdef CONFIG_CPU_RM9000
+			flush_scache_line(a);	/* Hit_Writeback_Inv_SD */
+#else
 			flush_dcache_line(a);	/* Hit_Writeback_Inv_D */
+#endif
 			if (a == end)
 				break;
 			a += dc_lsize;
@@ -694,7 +698,11 @@
 		a = addr & ~(dc_lsize - 1);
 		end = (addr + size - 1) & ~(dc_lsize - 1);
 		while (1) {
+#ifdef CONFIG_CPU_RM9000
+			flush_scache_line(a);	/* Hit_Writeback_Inv_SD */
+#else
 			flush_dcache_line(a);	/* Hit_Writeback_Inv_D */
+#endif
 			if (a == end)
 				break;
 			a += dc_lsize;
@@ -1164,6 +1172,9 @@
 	case CPU_RM9000:
 #ifdef CONFIG_RM7000_CPU_SCACHE
 		rm7k_sc_init();
+#ifdef CONFIG_CPU_RM9000
+		sc_present = 1;
+#endif
 #endif
 		return;
 
diff -Naur a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c
--- a/arch/mips/mm/sc-rm7k.c	2005-07-11 11:28:10.000000000 -0700
+++ b/arch/mips/mm/sc-rm7k.c	2006-06-22 11:48:21.000000000 -0700
@@ -144,6 +144,9 @@
 void __init rm7k_sc_init(void)
 {
 	unsigned int config = read_c0_config();
+#ifdef CONFIG_CPU_RM9000
+	struct cpuinfo_mips *c = &current_cpu_data;
+#endif
 
 	if ((config & RM7K_CONF_SC))
 		return;
@@ -154,6 +157,12 @@
 	if (!(config & RM7K_CONF_SE))
 		rm7k_sc_enable();
 
+#ifdef CONFIG_CPU_RM9000
+	c->scache.linesz = 16<<((config & R4K_CONF_SB) >> 22);
+	c->scache.ways = 4;
+	c->scache.waybit = 5;
+	c->options |= MIPS_CPU_CACHE_CDEX_S;
+#endif
 	/*
 	 * While we're at it let's deal with the tertiary cache.
 	 */
diff -Naur a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
--- a/arch/mips/mm/tlbex.c	2005-07-11 11:28:10.000000000 -0700
+++ b/arch/mips/mm/tlbex.c	2006-06-22 12:24:19.000000000 -0700
@@ -50,6 +50,12 @@
 	return R10000_LLSC_WAR;
 }
 
+static __init int __attribute__((unused)) e9000_llsc_war(void)
+{
+	return E9000_ENTRYHI_WAR;
+}
+
+
 /*
  * A little micro-assembler, intended for TLB refill handler
  * synthesizing. It is intentionally kept simple, does only support
@@ -95,7 +101,7 @@
 	insn_dsll, insn_dsll32, insn_dsra, insn_dsrl,
 	insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld,
 	insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0,
-	insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
+	insn_or, insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
 	insn_sra, insn_srl, insn_subu, insn_sw, insn_tlbp, insn_tlbwi,
 	insn_tlbwr, insn_xor, insn_xori
 };
@@ -147,6 +153,7 @@
 	{ insn_lw, M(lw_op,0,0,0,0,0), RS | RT | SIMM },
 	{ insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD },
 	{ insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD },
+	{ insn_or, M(spec_op,0,0,0,0,or_op), RS | RT | RD },
 	{ insn_ori, M(ori_op,0,0,0,0,0), RS | RT | UIMM },
 	{ insn_rfe, M(cop0_op,cop_op,0,0,0,rfe_op), 0 },
 	{ insn_sc, M(sc_op,0,0,0,0,0), RS | RT | SIMM },
@@ -378,6 +385,7 @@
 I_u2s3u1(_lw);
 I_u1u2(_mfc0);
 I_u1u2(_mtc0);
+I_u3u1u2(_or);
 I_u2u1u3(_ori);
 I_0(_rfe);
 I_u2s3u1(_sc);
@@ -1157,6 +1165,16 @@
 		/* No need for i_nop */
 	}
 
+	if (e9000_llsc_war()) {
+		i_MFC0(&p, K0, C0_BADVADDR);
+		i_MFC0(&p, K1, C0_ENTRYHI);
+		i_ori(&p, K0, K0, 0x1fff);
+		i_xori(&p, K0, K0, 0x1fff);
+		i_andi(&p, K1, K1, 0x0fff);
+		i_or(&p, K0, K0, K1);
+		i_MTC0(&p, K0, C0_ENTRYHI);
+        }
+
 #ifdef CONFIG_MIPS64
 	build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
 #else
@@ -1665,6 +1683,16 @@
 		/* No need for i_nop */
 	}
 
+        if (e9000_llsc_war()) {
+                i_MFC0(&p, K0, C0_BADVADDR);
+                i_MFC0(&p, K1, C0_ENTRYHI);
+                i_ori(&p, K0, K0, 0x1fff);
+                i_xori(&p, K0, K0, 0x1fff);
+                i_andi(&p, K1, K1, 0x0fff);
+                i_or(&p, K0, K0, K1);
+                i_MTC0(&p, K0, C0_ENTRYHI);
+        }
+
 	build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
 	build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl);
 	build_make_valid(&p, &r, K0, K1);
@@ -1704,6 +1732,16 @@
 	memset(labels, 0, sizeof(labels));
 	memset(relocs, 0, sizeof(relocs));
 
+        if (e9000_llsc_war()) {
+                i_MFC0(&p, K0, C0_BADVADDR);
+                i_MFC0(&p, K1, C0_ENTRYHI);
+                i_ori(&p, K0, K0, 0x1fff);
+                i_xori(&p, K0, K0, 0x1fff);
+                i_andi(&p, K1, K1, 0x0fff);
+                i_or(&p, K0, K0, K1);
+                i_MTC0(&p, K0, C0_ENTRYHI);
+        }
+
 	build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
 	build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs);
 	build_make_write(&p, &r, K0, K1);
@@ -1743,6 +1781,16 @@
 	memset(labels, 0, sizeof(labels));
 	memset(relocs, 0, sizeof(relocs));
 
+        if (e9000_llsc_war()) {
+                i_MFC0(&p, K0, C0_BADVADDR);
+                i_MFC0(&p, K1, C0_ENTRYHI);
+                i_ori(&p, K0, K0, 0x1fff);
+                i_xori(&p, K0, K0, 0x1fff);
+                i_andi(&p, K1, K1, 0x0fff);
+                i_or(&p, K0, K0, K1);
+                i_MTC0(&p, K0, C0_ENTRYHI);
+        }
+
 	build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
 	build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm);
 	/* Present and writable bits set, set accessed and dirty bits. */
diff -Naur a/include/asm-mips/war.h b/include/asm-mips/war.h
--- a/include/asm-mips/war.h	2005-07-11 11:28:10.000000000 -0700
+++ b/include/asm-mips/war.h	2006-06-22 11:48:21.000000000 -0700
@@ -182,10 +182,16 @@
  * being fetched may case spurious exceptions.
  */
 #if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_MOMENCO_OCELOT_3) || \
-    defined(CONFIG_PMC_YOSEMITE)
+    defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_PMC_SEQUOIA)
 #define ICACHE_REFILLS_WORKAROUND_WAR	1
 #endif
 
+/* E9000 has a bug - The EntryHi register gets corrupt in some exceptional cases */
+#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_MOMENCO_OCELOT_3) || \
+    defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_PMC_SEQUOIA)
+#define E9000_ENTRYHI_WAR	1
+#endif
+
 
 /*
  * ON the R10000 upto version 2.6 (not sure about 2.7) there is a bug that
@@ -198,6 +204,9 @@
 /*
  * Workarounds default to off
  */
+#ifndef E9000_ENTRYHI_WAR
+#define E9000_ENTRYHI_WAR		0
+#endif
 #ifndef ICACHE_REFILLS_WORKAROUND_WAR
 #define ICACHE_REFILLS_WORKAROUND_WAR	0
 #endif


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux