diff options
Diffstat (limited to 'arch/sh/mm/fault.c')
-rw-r--r-- | arch/sh/mm/fault.c | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index fa5d7f0b9f18..0ecc117cade4 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.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 Paul Mundt | 5 | * Copyright (C) 2003 - 2007 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 |
@@ -15,12 +15,42 @@ | |||
15 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
16 | #include <linux/hardirq.h> | 16 | #include <linux/hardirq.h> |
17 | #include <linux/kprobes.h> | 17 | #include <linux/kprobes.h> |
18 | #include <asm/kdebug.h> | ||
18 | #include <asm/system.h> | 19 | #include <asm/system.h> |
19 | #include <asm/mmu_context.h> | 20 | #include <asm/mmu_context.h> |
20 | #include <asm/tlbflush.h> | 21 | #include <asm/tlbflush.h> |
21 | #include <asm/kgdb.h> | 22 | #include <asm/kgdb.h> |
22 | 23 | ||
23 | extern void die(const char *,struct pt_regs *,long); | 24 | #ifdef CONFIG_KPROBES |
25 | ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); | ||
26 | |||
27 | /* Hook to register for page fault notifications */ | ||
28 | int register_page_fault_notifier(struct notifier_block *nb) | ||
29 | { | ||
30 | return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); | ||
31 | } | ||
32 | |||
33 | int unregister_page_fault_notifier(struct notifier_block *nb) | ||
34 | { | ||
35 | return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); | ||
36 | } | ||
37 | |||
38 | static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, | ||
39 | int trap, int sig) | ||
40 | { | ||
41 | struct die_args args = { | ||
42 | .regs = regs, | ||
43 | .trapnr = trap, | ||
44 | }; | ||
45 | return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); | ||
46 | } | ||
47 | #else | ||
48 | static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, | ||
49 | int trap, int sig) | ||
50 | { | ||
51 | return NOTIFY_DONE; | ||
52 | } | ||
53 | #endif | ||
24 | 54 | ||
25 | /* | 55 | /* |
26 | * This routine handles page faults. It determines the address, | 56 | * This routine handles page faults. It determines the address, |
@@ -39,6 +69,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |||
39 | siginfo_t info; | 69 | siginfo_t info; |
40 | 70 | ||
41 | trace_hardirqs_on(); | 71 | trace_hardirqs_on(); |
72 | |||
73 | if (notify_page_fault(DIE_PAGE_FAULT, regs, | ||
74 | writeaccess, SIGSEGV) == NOTIFY_STOP) | ||
75 | return; | ||
76 | |||
42 | local_irq_enable(); | 77 | local_irq_enable(); |
43 | 78 | ||
44 | #ifdef CONFIG_SH_KGDB | 79 | #ifdef CONFIG_SH_KGDB |