If mfc0 $12 follows store and the mfc0 is last instruction of a
page and fetching the next instruction causes TLB miss, the result
of the mfc0 might wrongly contain EXL bit.
ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
Workaround: mask EXL bit of the result or place a nop before mfc0.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
diff --git a/include/asm-mips/interrupt.h b/include/asm-mips/interrupt.h
index 0da5818..951ee7a 100644
--- a/include/asm-mips/interrupt.h
+++ b/include/asm-mips/interrupt.h
@@ -13,6 +13,7 @@
#include <linux/config.h>
#include <asm/hazards.h>
+#include <asm/war.h>
__asm__ (
" .macro local_irq_enable \n"
@@ -55,8 +56,13 @@ __asm__ (
" di \n"
#else
" mfc0 $1,$12 \n"
+#if TX49XX_MFC0_WAR && defined(MODULE)
+ " ori $1,3 \n"
+ " xori $1,3 \n"
+#else
" ori $1,1 \n"
" xori $1,1 \n"
+#endif
" .set noreorder \n"
" mtc0 $1,$12 \n"
#endif
@@ -96,8 +102,13 @@ __asm__ (
" andi \\result, 1 \n"
#else
" mfc0 \\result, $12 \n"
+#if TX49XX_MFC0_WAR && defined(MODULE)
+ " ori $1, \\result, 3 \n"
+ " xori $1, 3 \n"
+#else
" ori $1, \\result, 1 \n"
" xori $1, 1 \n"
+#endif
" .set noreorder \n"
" mtc0 $1, $12 \n"
#endif
@@ -136,8 +147,13 @@ __asm__ (
#else
" mfc0 $1, $12 \n"
" andi \\flags, 1 \n"
+#if TX49XX_MFC0_WAR && defined(MODULE)
+ " ori $1, 3 \n"
+ " xori $1, 3 \n"
+#else
" ori $1, 1 \n"
" xori $1, 1 \n"
+#endif
" or \\flags, $1 \n"
" mtc0 \\flags, $12 \n"
#endif
diff --git a/include/asm-mips/war.h b/include/asm-mips/war.h
index ad374bd..859520a 100644
--- a/include/asm-mips/war.h
+++ b/include/asm-mips/war.h
@@ -169,6 +169,19 @@
#endif
/*
+ * If mfc0 $12 follows store and the mfc0 is last instruction of a
+ * page and fetching the next instruction causes TLB miss, the result
+ * of the mfc0 might wrongly contain EXL bit.
+ *
+ * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
+ *
+ * Workaround: mask EXL bit of the result or place a nop before mfc0.
+ */
+#ifdef CONFIG_CPU_TX49XX
+#define TX49XX_MFC0_WAR 1
+#endif
+
+/*
* On the RM9000 there is a problem which makes the CreateDirtyExclusive
* cache operation unusable on SMP systems.
*/
@@ -228,6 +241,9 @@
#ifndef TX49XX_ICACHE_INDEX_INV_WAR
#define TX49XX_ICACHE_INDEX_INV_WAR 0
#endif
+#ifndef TX49XX_MFC0_WAR
+#define TX49XX_MFC0_WAR 0
+#endif
#ifndef RM9000_CDEX_SMP_WAR
#define RM9000_CDEX_SMP_WAR 0
#endif
|