diff options
Diffstat (limited to 'arch/x86/mm/fault_64.c')
-rw-r--r-- | arch/x86/mm/fault_64.c | 44 |
1 files changed, 19 insertions, 25 deletions
diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c index 54816adb8e93..5e0e54906c48 100644 --- a/arch/x86/mm/fault_64.c +++ b/arch/x86/mm/fault_64.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/kprobes.h> | 25 | #include <linux/kprobes.h> |
26 | #include <linux/uaccess.h> | 26 | #include <linux/uaccess.h> |
27 | #include <linux/kdebug.h> | 27 | #include <linux/kdebug.h> |
28 | #include <linux/kprobes.h> | ||
28 | 29 | ||
29 | #include <asm/system.h> | 30 | #include <asm/system.h> |
30 | #include <asm/pgalloc.h> | 31 | #include <asm/pgalloc.h> |
@@ -40,34 +41,27 @@ | |||
40 | #define PF_RSVD (1<<3) | 41 | #define PF_RSVD (1<<3) |
41 | #define PF_INSTR (1<<4) | 42 | #define PF_INSTR (1<<4) |
42 | 43 | ||
43 | static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); | 44 | #ifdef CONFIG_KPROBES |
44 | 45 | static inline int notify_page_fault(struct pt_regs *regs) | |
45 | /* Hook to register for page fault notifications */ | ||
46 | int register_page_fault_notifier(struct notifier_block *nb) | ||
47 | { | 46 | { |
48 | vmalloc_sync_all(); | 47 | int ret = 0; |
49 | return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); | 48 | |
50 | } | 49 | /* kprobe_running() needs smp_processor_id() */ |
51 | EXPORT_SYMBOL_GPL(register_page_fault_notifier); | 50 | if (!user_mode(regs)) { |
51 | preempt_disable(); | ||
52 | if (kprobe_running() && kprobe_fault_handler(regs, 14)) | ||
53 | ret = 1; | ||
54 | preempt_enable(); | ||
55 | } | ||
52 | 56 | ||
53 | int unregister_page_fault_notifier(struct notifier_block *nb) | 57 | return ret; |
54 | { | ||
55 | return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); | ||
56 | } | 58 | } |
57 | EXPORT_SYMBOL_GPL(unregister_page_fault_notifier); | 59 | #else |
58 | 60 | static inline int notify_page_fault(struct pt_regs *regs) | |
59 | static inline int notify_page_fault(struct pt_regs *regs, long err) | ||
60 | { | 61 | { |
61 | struct die_args args = { | 62 | return 0; |
62 | .regs = regs, | ||
63 | .str = "page fault", | ||
64 | .err = err, | ||
65 | .trapnr = 14, | ||
66 | .signr = SIGSEGV | ||
67 | }; | ||
68 | return atomic_notifier_call_chain(¬ify_page_fault_chain, | ||
69 | DIE_PAGE_FAULT, &args); | ||
70 | } | 63 | } |
64 | #endif | ||
71 | 65 | ||
72 | /* Sometimes the CPU reports invalid exceptions on prefetch. | 66 | /* Sometimes the CPU reports invalid exceptions on prefetch. |
73 | Check that here and ignore. | 67 | Check that here and ignore. |
@@ -345,7 +339,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |||
345 | if (vmalloc_fault(address) >= 0) | 339 | if (vmalloc_fault(address) >= 0) |
346 | return; | 340 | return; |
347 | } | 341 | } |
348 | if (notify_page_fault(regs, error_code) == NOTIFY_STOP) | 342 | if (notify_page_fault(regs)) |
349 | return; | 343 | return; |
350 | /* | 344 | /* |
351 | * Don't take the mm semaphore here. If we fixup a prefetch | 345 | * Don't take the mm semaphore here. If we fixup a prefetch |
@@ -354,7 +348,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |||
354 | goto bad_area_nosemaphore; | 348 | goto bad_area_nosemaphore; |
355 | } | 349 | } |
356 | 350 | ||
357 | if (notify_page_fault(regs, error_code) == NOTIFY_STOP) | 351 | if (notify_page_fault(regs)) |
358 | return; | 352 | return; |
359 | 353 | ||
360 | if (likely(regs->eflags & X86_EFLAGS_IF)) | 354 | if (likely(regs->eflags & X86_EFLAGS_IF)) |