diff options
author | Paul Mundt <lethal@linux-sh.org> | 2008-09-07 23:22:47 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2008-09-07 23:22:47 -0400 |
commit | 037c10a612e8b7461e33672fb3848807ac6e2346 (patch) | |
tree | 97f41894ffa408c7e4a9b14e08fa7ffdc19e3cfd /arch | |
parent | fc63562ac2107dfa843f5288fe985fc6f0021c17 (diff) |
sh: kprobes: Hook up kprobe_fault_handler() in the page fault path.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sh/include/asm/kprobes.h | 3 | ||||
-rw-r--r-- | arch/sh/kernel/kprobes.c | 2 | ||||
-rw-r--r-- | arch/sh/mm/fault_32.c | 29 |
3 files changed, 30 insertions, 4 deletions
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h index 70fc629df904..756a5cd96378 100644 --- a/arch/sh/include/asm/kprobes.h +++ b/arch/sh/include/asm/kprobes.h | |||
@@ -6,8 +6,6 @@ | |||
6 | #include <linux/types.h> | 6 | #include <linux/types.h> |
7 | #include <linux/ptrace.h> | 7 | #include <linux/ptrace.h> |
8 | 8 | ||
9 | struct pt_regs; | ||
10 | |||
11 | typedef u16 kprobe_opcode_t; | 9 | typedef u16 kprobe_opcode_t; |
12 | #define BREAKPOINT_INSTRUCTION 0xc3ff | 10 | #define BREAKPOINT_INSTRUCTION 0xc3ff |
13 | 11 | ||
@@ -48,6 +46,7 @@ struct kprobe_ctlblk { | |||
48 | struct prev_kprobe prev_kprobe; | 46 | struct prev_kprobe prev_kprobe; |
49 | }; | 47 | }; |
50 | 48 | ||
49 | extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); | ||
51 | extern int kprobe_exceptions_notify(struct notifier_block *self, | 50 | extern int kprobe_exceptions_notify(struct notifier_block *self, |
52 | unsigned long val, void *data); | 51 | unsigned long val, void *data); |
53 | extern int kprobe_handle_illslot(unsigned long pc); | 52 | extern int kprobe_handle_illslot(unsigned long pc); |
diff --git a/arch/sh/kernel/kprobes.c b/arch/sh/kernel/kprobes.c index ac6074942fd6..81a3725e5155 100644 --- a/arch/sh/kernel/kprobes.c +++ b/arch/sh/kernel/kprobes.c | |||
@@ -393,7 +393,7 @@ static inline int post_kprobe_handler(struct pt_regs *regs) | |||
393 | return 1; | 393 | return 1; |
394 | } | 394 | } |
395 | 395 | ||
396 | static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) | 396 | int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) |
397 | { | 397 | { |
398 | struct kprobe *cur = kprobe_running(); | 398 | struct kprobe *cur = kprobe_running(); |
399 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 399 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index e8efda9846bb..659811c179e6 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Page fault handler for SH with an MMU. | 2 | * Page fault handler for SH with an MMU. |
3 | * | 3 | * |
4 | * Copyright (C) 1999 Niibe Yutaka | 4 | * Copyright (C) 1999 Niibe Yutaka |
5 | * Copyright (C) 2003 - 2007 Paul Mundt | 5 | * Copyright (C) 2003 - 2008 Paul Mundt |
6 | * | 6 | * |
7 | * Based on linux/arch/i386/mm/fault.c: | 7 | * Based on linux/arch/i386/mm/fault.c: |
8 | * Copyright (C) 1995 Linus Torvalds | 8 | * Copyright (C) 1995 Linus Torvalds |
@@ -21,6 +21,27 @@ | |||
21 | #include <asm/tlbflush.h> | 21 | #include <asm/tlbflush.h> |
22 | #include <asm/kgdb.h> | 22 | #include <asm/kgdb.h> |
23 | 23 | ||
24 | #ifdef CONFIG_KPROBES | ||
25 | static inline int notify_page_fault(struct pt_regs *regs, int trap) | ||
26 | { | ||
27 | int ret = 0; | ||
28 | |||
29 | if (!user_mode(regs)) { | ||
30 | preempt_disable(); | ||
31 | if (kprobe_running() && kprobe_fault_handler(regs, trap)) | ||
32 | ret = 1; | ||
33 | preempt_enable(); | ||
34 | } | ||
35 | |||
36 | return ret; | ||
37 | } | ||
38 | #else | ||
39 | static inline int notify_page_fault(struct pt_regs *regs, int trap) | ||
40 | { | ||
41 | return 0; | ||
42 | } | ||
43 | #endif | ||
44 | |||
24 | /* | 45 | /* |
25 | * This routine handles page faults. It determines the address, | 46 | * This routine handles page faults. It determines the address, |
26 | * and the problem, and then passes it off to one of the appropriate | 47 | * and the problem, and then passes it off to one of the appropriate |
@@ -37,6 +58,9 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |||
37 | int fault; | 58 | int fault; |
38 | siginfo_t info; | 59 | siginfo_t info; |
39 | 60 | ||
61 | if (notify_page_fault(regs, writeaccess)) | ||
62 | return; | ||
63 | |||
40 | #ifdef CONFIG_SH_KGDB | 64 | #ifdef CONFIG_SH_KGDB |
41 | if (kgdb_nofault && kgdb_bus_err_hook) | 65 | if (kgdb_nofault && kgdb_bus_err_hook) |
42 | kgdb_bus_err_hook(); | 66 | kgdb_bus_err_hook(); |
@@ -269,6 +293,9 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs, | |||
269 | pte_t *pte; | 293 | pte_t *pte; |
270 | pte_t entry; | 294 | pte_t entry; |
271 | 295 | ||
296 | if (notify_page_fault(regs, writeaccess)) | ||
297 | return 0; | ||
298 | |||
272 | #ifdef CONFIG_SH_KGDB | 299 | #ifdef CONFIG_SH_KGDB |
273 | if (kgdb_nofault && kgdb_bus_err_hook) | 300 | if (kgdb_nofault && kgdb_bus_err_hook) |
274 | kgdb_bus_err_hook(); | 301 | kgdb_bus_err_hook(); |