diff options
author | David Daney <ddaney@avtrex.com> | 2008-09-23 03:08:45 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2008-10-11 11:18:56 -0400 |
commit | b67b2b703047bfaf62687ca64c9486599b609ef0 (patch) | |
tree | ae9eee050db78869d62c5ca85953d0c1b93639f3 /arch/mips/kernel/traps.c | |
parent | 654f57bfb467996fb730eae96dc30ea4de989fdc (diff) |
MIPS: Watch exception handling for HARDWARE_WATCHPOINTS.
Here we hook up the watch exception handler so that it sends SIGTRAP when
the hardware watch registers are triggered.
Signed-off-by: David Daney <ddaney@avtrex.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r-- | arch/mips/kernel/traps.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index b602ac6eb47d..80b9e070c207 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <asm/tlbdebug.h> | 42 | #include <asm/tlbdebug.h> |
43 | #include <asm/traps.h> | 43 | #include <asm/traps.h> |
44 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
45 | #include <asm/watch.h> | ||
45 | #include <asm/mmu_context.h> | 46 | #include <asm/mmu_context.h> |
46 | #include <asm/types.h> | 47 | #include <asm/types.h> |
47 | #include <asm/stacktrace.h> | 48 | #include <asm/stacktrace.h> |
@@ -912,13 +913,26 @@ asmlinkage void do_mdmx(struct pt_regs *regs) | |||
912 | 913 | ||
913 | asmlinkage void do_watch(struct pt_regs *regs) | 914 | asmlinkage void do_watch(struct pt_regs *regs) |
914 | { | 915 | { |
916 | u32 cause; | ||
917 | |||
915 | /* | 918 | /* |
916 | * We use the watch exception where available to detect stack | 919 | * Clear WP (bit 22) bit of cause register so we don't loop |
917 | * overflows. | 920 | * forever. |
918 | */ | 921 | */ |
919 | dump_tlb_all(); | 922 | cause = read_c0_cause(); |
920 | show_regs(regs); | 923 | cause &= ~(1 << 22); |
921 | panic("Caught WATCH exception - probably caused by stack overflow."); | 924 | write_c0_cause(cause); |
925 | |||
926 | /* | ||
927 | * If the current thread has the watch registers loaded, save | ||
928 | * their values and send SIGTRAP. Otherwise another thread | ||
929 | * left the registers set, clear them and continue. | ||
930 | */ | ||
931 | if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) { | ||
932 | mips_read_watch_registers(); | ||
933 | force_sig(SIGTRAP, current); | ||
934 | } else | ||
935 | mips_clear_watch_registers(); | ||
922 | } | 936 | } |
923 | 937 | ||
924 | asmlinkage void do_mcheck(struct pt_regs *regs) | 938 | asmlinkage void do_mcheck(struct pt_regs *regs) |