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 |
