]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/mips/kernel/traps.c
Merge branch 'agp-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[linux-2.6-omap-h63xx.git] / arch / mips / kernel / traps.c
index b602ac6eb47d8a41454d0bd5e48b7931d6f4ee7f..80b9e070c2078c1dbc988f5ae147832e1624c8b6 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/tlbdebug.h>
 #include <asm/traps.h>
 #include <asm/uaccess.h>
+#include <asm/watch.h>
 #include <asm/mmu_context.h>
 #include <asm/types.h>
 #include <asm/stacktrace.h>
@@ -912,13 +913,26 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
 
 asmlinkage void do_watch(struct pt_regs *regs)
 {
+       u32 cause;
+
        /*
-        * We use the watch exception where available to detect stack
-        * overflows.
+        * Clear WP (bit 22) bit of cause register so we don't loop
+        * forever.
         */
-       dump_tlb_all();
-       show_regs(regs);
-       panic("Caught WATCH exception - probably caused by stack overflow.");
+       cause = read_c0_cause();
+       cause &= ~(1 << 22);
+       write_c0_cause(cause);
+
+       /*
+        * If the current thread has the watch registers loaded, save
+        * their values and send SIGTRAP.  Otherwise another thread
+        * left the registers set, clear them and continue.
+        */
+       if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) {
+               mips_read_watch_registers();
+               force_sig(SIGTRAP, current);
+       } else
+               mips_clear_watch_registers();
 }
 
 asmlinkage void do_mcheck(struct pt_regs *regs)