linux-mips
[Top] [All Lists]

[PATCH] TX49 MFC0 bug workaround

To: linux-mips@linux-mips.org
Subject: [PATCH] TX49 MFC0 bug workaround
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Fri, 03 Feb 2006 01:34:01 +0900 (JST)
Cc: ralf@linux-mips.org
Original-recipient: rfc822;linux-mips@linux-mips.org
Sender: linux-mips-bounce@linux-mips.org
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

<Prev in Thread] Current Thread [Next in Thread>