MIPS: Read watch registers with interrupts disabled.

If a context switch occurred between the watch exception and reading the
watch registers, it would be possible for the new process to corrupt their
state.  Enabling interrupts only after the watch registers are read avoids
this race.

Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index fb6f731..8882e57 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -458,7 +458,11 @@
 	BUILD_HANDLER fpe fpe fpe silent		/* #15 */
 	BUILD_HANDLER mdmx mdmx sti silent		/* #22 */
 #ifdef 	CONFIG_HARDWARE_WATCHPOINTS
-	BUILD_HANDLER watch watch sti silent		/* #23 */
+	/*
+	 * For watch, interrupts will be enabled after the watch
+	 * registers are read.
+	 */
+	BUILD_HANDLER watch watch cli silent		/* #23 */
 #else
 	BUILD_HANDLER watch watch sti verbose		/* #23 */
 #endif
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index fa06460..b2d7041 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -944,6 +944,9 @@
 	force_sig(SIGILL, current);
 }
 
+/*
+ * Called with interrupts disabled.
+ */
 asmlinkage void do_watch(struct pt_regs *regs)
 {
 	u32 cause;
@@ -963,9 +966,12 @@
 	 */
 	if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) {
 		mips_read_watch_registers();
+		local_irq_enable();
 		force_sig(SIGTRAP, current);
-	} else
+	} else {
 		mips_clear_watch_registers();
+		local_irq_enable();
+	}
 }
 
 asmlinkage void do_mcheck(struct pt_regs *regs)