diff options
Diffstat (limited to 'arch/i386/mm/fault.c')
-rw-r--r-- | arch/i386/mm/fault.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index bd6fe96cc16d..6ee7faaf2c1b 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c | |||
@@ -30,6 +30,40 @@ | |||
30 | 30 | ||
31 | extern void die(const char *,struct pt_regs *,long); | 31 | extern void die(const char *,struct pt_regs *,long); |
32 | 32 | ||
33 | #ifdef CONFIG_KPROBES | ||
34 | ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); | ||
35 | int register_page_fault_notifier(struct notifier_block *nb) | ||
36 | { | ||
37 | vmalloc_sync_all(); | ||
38 | return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); | ||
39 | } | ||
40 | |||
41 | int unregister_page_fault_notifier(struct notifier_block *nb) | ||
42 | { | ||
43 | return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); | ||
44 | } | ||
45 | |||
46 | static inline int notify_page_fault(enum die_val val, const char *str, | ||
47 | struct pt_regs *regs, long err, int trap, int sig) | ||
48 | { | ||
49 | struct die_args args = { | ||
50 | .regs = regs, | ||
51 | .str = str, | ||
52 | .err = err, | ||
53 | .trapnr = trap, | ||
54 | .signr = sig | ||
55 | }; | ||
56 | return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); | ||
57 | } | ||
58 | #else | ||
59 | static inline int notify_page_fault(enum die_val val, const char *str, | ||
60 | struct pt_regs *regs, long err, int trap, int sig) | ||
61 | { | ||
62 | return NOTIFY_DONE; | ||
63 | } | ||
64 | #endif | ||
65 | |||
66 | |||
33 | /* | 67 | /* |
34 | * Unlock any spinlocks which will prevent us from getting the | 68 | * Unlock any spinlocks which will prevent us from getting the |
35 | * message out | 69 | * message out |
@@ -324,7 +358,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, | |||
324 | if (unlikely(address >= TASK_SIZE)) { | 358 | if (unlikely(address >= TASK_SIZE)) { |
325 | if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0) | 359 | if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0) |
326 | return; | 360 | return; |
327 | if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, | 361 | if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, |
328 | SIGSEGV) == NOTIFY_STOP) | 362 | SIGSEGV) == NOTIFY_STOP) |
329 | return; | 363 | return; |
330 | /* | 364 | /* |
@@ -334,7 +368,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, | |||
334 | goto bad_area_nosemaphore; | 368 | goto bad_area_nosemaphore; |
335 | } | 369 | } |
336 | 370 | ||
337 | if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, | 371 | if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, |
338 | SIGSEGV) == NOTIFY_STOP) | 372 | SIGSEGV) == NOTIFY_STOP) |
339 | return; | 373 | return; |
340 | 374 | ||