MIPS: Read watch registers with interrupts disabled.
authorDavid Daney <ddaney@caviumnetworks.com>
Mon, 5 Jan 2009 23:29:58 +0000 (15:29 -0800)
committerRalf Baechle <ralf@linux-mips.org>
Fri, 30 Jan 2009 21:32:58 +0000 (21:32 +0000)
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>
arch/mips/kernel/genex.S
arch/mips/kernel/traps.c

index fb6f73148df2f7c7459648ed110fcdde62145f2a..8882e5766f27ce5b7a8a57932b4b103b7a69eaa7 100644 (file)
@@ -458,7 +458,11 @@ NESTED(nmi_handler, PT_SIZE, sp)
        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
index fa06460cbf2c7668218a0e16fed9d8c749e44a23..b2d7041341b8f5afa3e313302c21b90e34e5ea3d 100644 (file)
@@ -944,6 +944,9 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
        force_sig(SIGILL, current);
 }
 
+/*
+ * Called with interrupts disabled.
+ */
 asmlinkage void do_watch(struct pt_regs *regs)
 {
        u32 cause;
@@ -963,9 +966,12 @@ asmlinkage void do_watch(struct pt_regs *regs)
         */
        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)