aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2007-10-16 04:24:07 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:42:50 -0400
commit74a0b5762713a26496db72eac34fbbed46f20fce (patch)
tree4a14df7c07ebc16283454f33713519a0e10b5c43
parentd5a7430ddcdb598261d70f7eb1bf450b5be52085 (diff)
x86: optimize page faults like all other achitectures and kill notifier cruft
x86(-64) are the last architectures still using the page fault notifier cruft for the kprobes page fault hook. This patch converts them to the proper direct calls, and removes the now unused pagefault notifier bits aswell as the cruft in kprobes.c that was related to this mess. I know Andi didn't really like this, but all other architecture maintainers agreed the direct calls are much better and besides the obvious cruft removal a common way of dealing with kprobes across architectures is important aswell. [akpm@linux-foundation.org: build fix] [akpm@linux-foundation.org: fix sparc64] Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: Andi Kleen <ak@suse.de> Cc: <linux-arch@vger.kernel.org> Cc: Prasanna S Panchamukhi <prasanna@in.ibm.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/x86/kernel/kprobes_32.c3
-rw-r--r--arch/x86/kernel/kprobes_64.c1
-rw-r--r--arch/x86/mm/fault_32.c43
-rw-r--r--arch/x86/mm/fault_64.c44
-rw-r--r--include/asm-avr32/kdebug.h16
-rw-r--r--include/asm-avr32/kprobes.h2
-rw-r--r--include/asm-ia64/kdebug.h15
-rw-r--r--include/asm-ia64/kprobes.h1
-rw-r--r--include/asm-powerpc/kdebug.h19
-rw-r--r--include/asm-powerpc/kprobes.h1
-rw-r--r--include/asm-s390/kdebug.h15
-rw-r--r--include/asm-s390/kprobes.h1
-rw-r--r--include/asm-sh/kdebug.h2
-rw-r--r--include/asm-sparc64/kdebug.h18
-rw-r--r--include/asm-sparc64/kprobes.h1
-rw-r--r--include/asm-x86/kdebug_32.h6
-rw-r--r--include/asm-x86/kdebug_64.h6
-rw-r--r--include/asm-x86/kprobes_32.h2
-rw-r--r--include/asm-x86/kprobes_64.h1
-rw-r--r--kernel/kprobes.c39
20 files changed, 44 insertions, 192 deletions
diff --git a/arch/x86/kernel/kprobes_32.c b/arch/x86/kernel/kprobes_32.c
index e7d0d3c2ef64..06b86e5617f6 100644
--- a/arch/x86/kernel/kprobes_32.c
+++ b/arch/x86/kernel/kprobes_32.c
@@ -584,7 +584,7 @@ out:
584 return 1; 584 return 1;
585} 585}
586 586
587static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) 587int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
588{ 588{
589 struct kprobe *cur = kprobe_running(); 589 struct kprobe *cur = kprobe_running();
590 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 590 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -666,7 +666,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
666 ret = NOTIFY_STOP; 666 ret = NOTIFY_STOP;
667 break; 667 break;
668 case DIE_GPF: 668 case DIE_GPF:
669 case DIE_PAGE_FAULT:
670 /* kprobe_running() needs smp_processor_id() */ 669 /* kprobe_running() needs smp_processor_id() */
671 preempt_disable(); 670 preempt_disable();
672 if (kprobe_running() && 671 if (kprobe_running() &&
diff --git a/arch/x86/kernel/kprobes_64.c b/arch/x86/kernel/kprobes_64.c
index 62e28e52d784..7c16506d681f 100644
--- a/arch/x86/kernel/kprobes_64.c
+++ b/arch/x86/kernel/kprobes_64.c
@@ -657,7 +657,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
657 ret = NOTIFY_STOP; 657 ret = NOTIFY_STOP;
658 break; 658 break;
659 case DIE_GPF: 659 case DIE_GPF:
660 case DIE_PAGE_FAULT:
661 /* kprobe_running() needs smp_processor_id() */ 660 /* kprobe_running() needs smp_processor_id() */
662 preempt_disable(); 661 preempt_disable();
663 if (kprobe_running() && 662 if (kprobe_running() &&
diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c
index fcb38e7f3543..be72c2a5b03b 100644
--- a/arch/x86/mm/fault_32.c
+++ b/arch/x86/mm/fault_32.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/desc.h> 31#include <asm/desc.h>
@@ -32,33 +33,27 @@
32 33
33extern void die(const char *,struct pt_regs *,long); 34extern void die(const char *,struct pt_regs *,long);
34 35
35static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); 36#ifdef CONFIG_KPROBES
36 37static inline int notify_page_fault(struct pt_regs *regs)
37int register_page_fault_notifier(struct notifier_block *nb)
38{ 38{
39 vmalloc_sync_all(); 39 int ret = 0;
40 return atomic_notifier_chain_register(&notify_page_fault_chain, nb); 40
41} 41 /* kprobe_running() needs smp_processor_id() */
42EXPORT_SYMBOL_GPL(register_page_fault_notifier); 42 if (!user_mode_vm(regs)) {
43 preempt_disable();
44 if (kprobe_running() && kprobe_fault_handler(regs, 14))
45 ret = 1;
46 preempt_enable();
47 }
43 48
44int unregister_page_fault_notifier(struct notifier_block *nb) 49 return ret;
45{
46 return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
47} 50}
48EXPORT_SYMBOL_GPL(unregister_page_fault_notifier); 51#else
49 52static inline int notify_page_fault(struct pt_regs *regs)
50static inline int notify_page_fault(struct pt_regs *regs, long err)
51{ 53{
52 struct die_args args = { 54 return 0;
53 .regs = regs,
54 .str = "page fault",
55 .err = err,
56 .trapnr = 14,
57 .signr = SIGSEGV
58 };
59 return atomic_notifier_call_chain(&notify_page_fault_chain,
60 DIE_PAGE_FAULT, &args);
61} 55}
56#endif
62 57
63/* 58/*
64 * Return EIP plus the CS segment base. The segment limit is also 59 * Return EIP plus the CS segment base. The segment limit is also
@@ -331,7 +326,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
331 if (unlikely(address >= TASK_SIZE)) { 326 if (unlikely(address >= TASK_SIZE)) {
332 if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0) 327 if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0)
333 return; 328 return;
334 if (notify_page_fault(regs, error_code) == NOTIFY_STOP) 329 if (notify_page_fault(regs))
335 return; 330 return;
336 /* 331 /*
337 * Don't take the mm semaphore here. If we fixup a prefetch 332 * Don't take the mm semaphore here. If we fixup a prefetch
@@ -340,7 +335,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
340 goto bad_area_nosemaphore; 335 goto bad_area_nosemaphore;
341 } 336 }
342 337
343 if (notify_page_fault(regs, error_code) == NOTIFY_STOP) 338 if (notify_page_fault(regs))
344 return; 339 return;
345 340
346 /* It's safe to allow irq's after cr2 has been saved and the vmalloc 341 /* It's safe to allow irq's after cr2 has been saved and the vmalloc
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
43static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); 44#ifdef CONFIG_KPROBES
44 45static inline int notify_page_fault(struct pt_regs *regs)
45/* Hook to register for page fault notifications */
46int register_page_fault_notifier(struct notifier_block *nb)
47{ 46{
48 vmalloc_sync_all(); 47 int ret = 0;
49 return atomic_notifier_chain_register(&notify_page_fault_chain, nb); 48
50} 49 /* kprobe_running() needs smp_processor_id() */
51EXPORT_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
53int unregister_page_fault_notifier(struct notifier_block *nb) 57 return ret;
54{
55 return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
56} 58}
57EXPORT_SYMBOL_GPL(unregister_page_fault_notifier); 59#else
58 60static inline int notify_page_fault(struct pt_regs *regs)
59static 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(&notify_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))
diff --git a/include/asm-avr32/kdebug.h b/include/asm-avr32/kdebug.h
index 7f54e2b15d13..fd7e99046b2f 100644
--- a/include/asm-avr32/kdebug.h
+++ b/include/asm-avr32/kdebug.h
@@ -1,26 +1,10 @@
1#ifndef __ASM_AVR32_KDEBUG_H 1#ifndef __ASM_AVR32_KDEBUG_H
2#define __ASM_AVR32_KDEBUG_H 2#define __ASM_AVR32_KDEBUG_H
3 3
4#include <linux/notifier.h>
5
6/* Grossly misnamed. */ 4/* Grossly misnamed. */
7enum die_val { 5enum die_val {
8 DIE_BREAKPOINT, 6 DIE_BREAKPOINT,
9 DIE_SSTEP, 7 DIE_SSTEP,
10}; 8};
11 9
12/*
13 * These are only here because kprobes.c wants them to implement a
14 * blatant layering violation. Will hopefully go away soon once all
15 * architectures are updated.
16 */
17static inline int register_page_fault_notifier(struct notifier_block *nb)
18{
19 return 0;
20}
21static inline int unregister_page_fault_notifier(struct notifier_block *nb)
22{
23 return 0;
24}
25
26#endif /* __ASM_AVR32_KDEBUG_H */ 10#endif /* __ASM_AVR32_KDEBUG_H */
diff --git a/include/asm-avr32/kprobes.h b/include/asm-avr32/kprobes.h
index 190a6377c809..0f3e636e6e4d 100644
--- a/include/asm-avr32/kprobes.h
+++ b/include/asm-avr32/kprobes.h
@@ -17,8 +17,6 @@ typedef u16 kprobe_opcode_t;
17#define BREAKPOINT_INSTRUCTION 0xd673 /* breakpoint */ 17#define BREAKPOINT_INSTRUCTION 0xd673 /* breakpoint */
18#define MAX_INSN_SIZE 2 18#define MAX_INSN_SIZE 2
19 19
20#define ARCH_INACTIVE_KPROBE_COUNT 1
21
22#define arch_remove_kprobe(p) do { } while (0) 20#define arch_remove_kprobe(p) do { } while (0)
23 21
24/* Architecture specific copy of original instruction */ 22/* Architecture specific copy of original instruction */
diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h
index 320cd8e754ea..35e49407d06c 100644
--- a/include/asm-ia64/kdebug.h
+++ b/include/asm-ia64/kdebug.h
@@ -26,21 +26,6 @@
26 * 2005-Oct Keith Owens <kaos@sgi.com>. Expand notify_die to cover more 26 * 2005-Oct Keith Owens <kaos@sgi.com>. Expand notify_die to cover more
27 * events. 27 * events.
28 */ 28 */
29#include <linux/notifier.h>
30
31/*
32 * These are only here because kprobes.c wants them to implement a
33 * blatant layering violation. Will hopefully go away soon once all
34 * architectures are updated.
35 */
36static inline int register_page_fault_notifier(struct notifier_block *nb)
37{
38 return 0;
39}
40static inline int unregister_page_fault_notifier(struct notifier_block *nb)
41{
42 return 0;
43}
44 29
45enum die_val { 30enum die_val {
46 DIE_BREAK = 1, 31 DIE_BREAK = 1,
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index 067d9dea68f9..6c79edf24d73 100644
--- a/include/asm-ia64/kprobes.h
+++ b/include/asm-ia64/kprobes.h
@@ -83,7 +83,6 @@ struct kprobe_ctlblk {
83}; 83};
84 84
85#define ARCH_SUPPORTS_KRETPROBES 85#define ARCH_SUPPORTS_KRETPROBES
86#define ARCH_INACTIVE_KPROBE_COUNT 1
87 86
88#define SLOT0_OPCODE_SHIFT (37) 87#define SLOT0_OPCODE_SHIFT (37)
89#define SLOT1_p1_OPCODE_SHIFT (37 - (64-46)) 88#define SLOT1_p1_OPCODE_SHIFT (37 - (64-46))
diff --git a/include/asm-powerpc/kdebug.h b/include/asm-powerpc/kdebug.h
index 295f0162c608..ae6d206728af 100644
--- a/include/asm-powerpc/kdebug.h
+++ b/include/asm-powerpc/kdebug.h
@@ -2,25 +2,6 @@
2#define _ASM_POWERPC_KDEBUG_H 2#define _ASM_POWERPC_KDEBUG_H
3#ifdef __KERNEL__ 3#ifdef __KERNEL__
4 4
5/* nearly identical to x86_64/i386 code */
6
7#include <linux/notifier.h>
8
9/*
10 * These are only here because kprobes.c wants them to implement a
11 * blatant layering violation. Will hopefully go away soon once all
12 * architectures are updated.
13 */
14static inline int register_page_fault_notifier(struct notifier_block *nb)
15{
16 return 0;
17}
18static inline int unregister_page_fault_notifier(struct notifier_block *nb)
19{
20 return 0;
21}
22extern struct atomic_notifier_head powerpc_die_chain;
23
24/* Grossly misnamed. */ 5/* Grossly misnamed. */
25enum die_val { 6enum die_val {
26 DIE_OOPS = 1, 7 DIE_OOPS = 1,
diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
index 8b08b447d6f3..c16973d5de62 100644
--- a/include/asm-powerpc/kprobes.h
+++ b/include/asm-powerpc/kprobes.h
@@ -81,7 +81,6 @@ typedef unsigned int kprobe_opcode_t;
81#endif 81#endif
82 82
83#define ARCH_SUPPORTS_KRETPROBES 83#define ARCH_SUPPORTS_KRETPROBES
84#define ARCH_INACTIVE_KPROBE_COUNT 1
85#define flush_insn_slot(p) do { } while (0) 84#define flush_insn_slot(p) do { } while (0)
86 85
87void kretprobe_trampoline(void); 86void kretprobe_trampoline(void);
diff --git a/include/asm-s390/kdebug.h b/include/asm-s390/kdebug.h
index 04418af08f85..40db27cd6e60 100644
--- a/include/asm-s390/kdebug.h
+++ b/include/asm-s390/kdebug.h
@@ -4,24 +4,9 @@
4/* 4/*
5 * Feb 2006 Ported to s390 <grundym@us.ibm.com> 5 * Feb 2006 Ported to s390 <grundym@us.ibm.com>
6 */ 6 */
7#include <linux/notifier.h>
8 7
9struct pt_regs; 8struct pt_regs;
10 9
11/*
12 * These are only here because kprobes.c wants them to implement a
13 * blatant layering violation. Will hopefully go away soon once all
14 * architectures are updated.
15 */
16static inline int register_page_fault_notifier(struct notifier_block *nb)
17{
18 return 0;
19}
20static inline int unregister_page_fault_notifier(struct notifier_block *nb)
21{
22 return 0;
23}
24
25enum die_val { 10enum die_val {
26 DIE_OOPS = 1, 11 DIE_OOPS = 1,
27 DIE_BPT, 12 DIE_BPT,
diff --git a/include/asm-s390/kprobes.h b/include/asm-s390/kprobes.h
index 340ba10446ea..8bc67cc9ffd2 100644
--- a/include/asm-s390/kprobes.h
+++ b/include/asm-s390/kprobes.h
@@ -47,7 +47,6 @@ typedef u16 kprobe_opcode_t;
47 : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) 47 : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
48 48
49#define ARCH_SUPPORTS_KRETPROBES 49#define ARCH_SUPPORTS_KRETPROBES
50#define ARCH_INACTIVE_KPROBE_COUNT 0
51 50
52#define KPROBE_SWAP_INST 0x10 51#define KPROBE_SWAP_INST 0x10
53 52
diff --git a/include/asm-sh/kdebug.h b/include/asm-sh/kdebug.h
index 382cfc7deb73..49cd69051a88 100644
--- a/include/asm-sh/kdebug.h
+++ b/include/asm-sh/kdebug.h
@@ -1,8 +1,6 @@
1#ifndef __ASM_SH_KDEBUG_H 1#ifndef __ASM_SH_KDEBUG_H
2#define __ASM_SH_KDEBUG_H 2#define __ASM_SH_KDEBUG_H
3 3
4#include <linux/notifier.h>
5
6/* Grossly misnamed. */ 4/* Grossly misnamed. */
7enum die_val { 5enum die_val {
8 DIE_TRAP, 6 DIE_TRAP,
diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
index 9974c7b0aebc..f905b773235a 100644
--- a/include/asm-sparc64/kdebug.h
+++ b/include/asm-sparc64/kdebug.h
@@ -1,26 +1,8 @@
1#ifndef _SPARC64_KDEBUG_H 1#ifndef _SPARC64_KDEBUG_H
2#define _SPARC64_KDEBUG_H 2#define _SPARC64_KDEBUG_H
3 3
4/* Nearly identical to x86_64/i386 code. */
5
6#include <linux/notifier.h>
7
8struct pt_regs; 4struct pt_regs;
9 5
10/*
11 * These are only here because kprobes.c wants them to implement a
12 * blatant layering violation. Will hopefully go away soon once all
13 * architectures are updated.
14 */
15static inline int register_page_fault_notifier(struct notifier_block *nb)
16{
17 return 0;
18}
19static inline int unregister_page_fault_notifier(struct notifier_block *nb)
20{
21 return 0;
22}
23
24extern void bad_trap(struct pt_regs *, long); 6extern void bad_trap(struct pt_regs *, long);
25 7
26/* Grossly misnamed. */ 8/* Grossly misnamed. */
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index 7f6774dca5f4..a04145b77f96 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/include/asm-sparc64/kprobes.h
@@ -11,7 +11,6 @@ typedef u32 kprobe_opcode_t;
11#define MAX_INSN_SIZE 2 11#define MAX_INSN_SIZE 2
12 12
13#define arch_remove_kprobe(p) do {} while (0) 13#define arch_remove_kprobe(p) do {} while (0)
14#define ARCH_INACTIVE_KPROBE_COUNT 0
15 14
16#define flush_insn_slot(p) \ 15#define flush_insn_slot(p) \
17do { flushi(&(p)->ainsn.insn[0]); \ 16do { flushi(&(p)->ainsn.insn[0]); \
diff --git a/include/asm-x86/kdebug_32.h b/include/asm-x86/kdebug_32.h
index a185b5f73e7f..181d437eef4b 100644
--- a/include/asm-x86/kdebug_32.h
+++ b/include/asm-x86/kdebug_32.h
@@ -5,14 +5,9 @@
5 * Aug-05 2004 Ported by Prasanna S Panchamukhi <prasanna@in.ibm.com> 5 * Aug-05 2004 Ported by Prasanna S Panchamukhi <prasanna@in.ibm.com>
6 * from x86_64 architecture. 6 * from x86_64 architecture.
7 */ 7 */
8#include <linux/notifier.h>
9 8
10struct pt_regs; 9struct pt_regs;
11 10
12extern int register_page_fault_notifier(struct notifier_block *);
13extern int unregister_page_fault_notifier(struct notifier_block *);
14
15
16/* Grossly misnamed. */ 11/* Grossly misnamed. */
17enum die_val { 12enum die_val {
18 DIE_OOPS = 1, 13 DIE_OOPS = 1,
@@ -27,7 +22,6 @@ enum die_val {
27 DIE_GPF, 22 DIE_GPF,
28 DIE_CALL, 23 DIE_CALL,
29 DIE_NMI_IPI, 24 DIE_NMI_IPI,
30 DIE_PAGE_FAULT,
31}; 25};
32 26
33#endif 27#endif
diff --git a/include/asm-x86/kdebug_64.h b/include/asm-x86/kdebug_64.h
index d7e2bcf49e4f..df413e05375e 100644
--- a/include/asm-x86/kdebug_64.h
+++ b/include/asm-x86/kdebug_64.h
@@ -1,13 +1,10 @@
1#ifndef _X86_64_KDEBUG_H 1#ifndef _X86_64_KDEBUG_H
2#define _X86_64_KDEBUG_H 1 2#define _X86_64_KDEBUG_H 1
3 3
4#include <linux/notifier.h> 4#include <linux/compiler.h>
5 5
6struct pt_regs; 6struct pt_regs;
7 7
8extern int register_page_fault_notifier(struct notifier_block *);
9extern int unregister_page_fault_notifier(struct notifier_block *);
10
11/* Grossly misnamed. */ 8/* Grossly misnamed. */
12enum die_val { 9enum die_val {
13 DIE_OOPS = 1, 10 DIE_OOPS = 1,
@@ -22,7 +19,6 @@ enum die_val {
22 DIE_GPF, 19 DIE_GPF,
23 DIE_CALL, 20 DIE_CALL,
24 DIE_NMI_IPI, 21 DIE_NMI_IPI,
25 DIE_PAGE_FAULT,
26}; 22};
27 23
28extern void printk_address(unsigned long address); 24extern void printk_address(unsigned long address);
diff --git a/include/asm-x86/kprobes_32.h b/include/asm-x86/kprobes_32.h
index 06f7303c30ca..f2489d07ce88 100644
--- a/include/asm-x86/kprobes_32.h
+++ b/include/asm-x86/kprobes_32.h
@@ -43,7 +43,6 @@ typedef u8 kprobe_opcode_t;
43 : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) 43 : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
44 44
45#define ARCH_SUPPORTS_KRETPROBES 45#define ARCH_SUPPORTS_KRETPROBES
46#define ARCH_INACTIVE_KPROBE_COUNT 0
47#define flush_insn_slot(p) do { } while (0) 46#define flush_insn_slot(p) do { } while (0)
48 47
49void arch_remove_kprobe(struct kprobe *p); 48void arch_remove_kprobe(struct kprobe *p);
@@ -89,4 +88,5 @@ static inline void restore_interrupts(struct pt_regs *regs)
89 88
90extern int kprobe_exceptions_notify(struct notifier_block *self, 89extern int kprobe_exceptions_notify(struct notifier_block *self,
91 unsigned long val, void *data); 90 unsigned long val, void *data);
91extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
92#endif /* _ASM_KPROBES_H */ 92#endif /* _ASM_KPROBES_H */
diff --git a/include/asm-x86/kprobes_64.h b/include/asm-x86/kprobes_64.h
index 7db825403e01..3f495e5308b1 100644
--- a/include/asm-x86/kprobes_64.h
+++ b/include/asm-x86/kprobes_64.h
@@ -42,7 +42,6 @@ typedef u8 kprobe_opcode_t;
42 : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) 42 : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
43 43
44#define ARCH_SUPPORTS_KRETPROBES 44#define ARCH_SUPPORTS_KRETPROBES
45#define ARCH_INACTIVE_KPROBE_COUNT 1
46 45
47void kretprobe_trampoline(void); 46void kretprobe_trampoline(void);
48extern void arch_remove_kprobe(struct kprobe *p); 47extern void arch_remove_kprobe(struct kprobe *p);
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 4b8a4493c541..f9798ff7899f 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -64,7 +64,6 @@
64 64
65static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; 65static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
66static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; 66static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
67static atomic_t kprobe_count;
68 67
69/* NOTE: change this value only with kprobe_mutex held */ 68/* NOTE: change this value only with kprobe_mutex held */
70static bool kprobe_enabled; 69static bool kprobe_enabled;
@@ -73,11 +72,6 @@ DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */
73DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */ 72DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */
74static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; 73static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
75 74
76static struct notifier_block kprobe_page_fault_nb = {
77 .notifier_call = kprobe_exceptions_notify,
78 .priority = 0x7fffffff /* we need to notified first */
79};
80
81#ifdef __ARCH_WANT_KPROBES_INSN_SLOT 75#ifdef __ARCH_WANT_KPROBES_INSN_SLOT
82/* 76/*
83 * kprobe->ainsn.insn points to the copy of the instruction to be 77 * kprobe->ainsn.insn points to the copy of the instruction to be
@@ -556,8 +550,6 @@ static int __kprobes __register_kprobe(struct kprobe *p,
556 old_p = get_kprobe(p->addr); 550 old_p = get_kprobe(p->addr);
557 if (old_p) { 551 if (old_p) {
558 ret = register_aggr_kprobe(old_p, p); 552 ret = register_aggr_kprobe(old_p, p);
559 if (!ret)
560 atomic_inc(&kprobe_count);
561 goto out; 553 goto out;
562 } 554 }
563 555
@@ -569,13 +561,9 @@ static int __kprobes __register_kprobe(struct kprobe *p,
569 hlist_add_head_rcu(&p->hlist, 561 hlist_add_head_rcu(&p->hlist,
570 &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); 562 &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
571 563
572 if (kprobe_enabled) { 564 if (kprobe_enabled)
573 if (atomic_add_return(1, &kprobe_count) == \
574 (ARCH_INACTIVE_KPROBE_COUNT + 1))
575 register_page_fault_notifier(&kprobe_page_fault_nb);
576
577 arch_arm_kprobe(p); 565 arch_arm_kprobe(p);
578 } 566
579out: 567out:
580 mutex_unlock(&kprobe_mutex); 568 mutex_unlock(&kprobe_mutex);
581 569
@@ -658,16 +646,6 @@ valid_p:
658 } 646 }
659 mutex_unlock(&kprobe_mutex); 647 mutex_unlock(&kprobe_mutex);
660 } 648 }
661
662 /* Call unregister_page_fault_notifier()
663 * if no probes are active
664 */
665 mutex_lock(&kprobe_mutex);
666 if (atomic_add_return(-1, &kprobe_count) == \
667 ARCH_INACTIVE_KPROBE_COUNT)
668 unregister_page_fault_notifier(&kprobe_page_fault_nb);
669 mutex_unlock(&kprobe_mutex);
670 return;
671} 649}
672 650
673static struct notifier_block kprobe_exceptions_nb = { 651static struct notifier_block kprobe_exceptions_nb = {
@@ -815,7 +793,6 @@ static int __init init_kprobes(void)
815 INIT_HLIST_HEAD(&kprobe_table[i]); 793 INIT_HLIST_HEAD(&kprobe_table[i]);
816 INIT_HLIST_HEAD(&kretprobe_inst_table[i]); 794 INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
817 } 795 }
818 atomic_set(&kprobe_count, 0);
819 796
820 /* By default, kprobes are enabled */ 797 /* By default, kprobes are enabled */
821 kprobe_enabled = true; 798 kprobe_enabled = true;
@@ -921,13 +898,6 @@ static void __kprobes enable_all_kprobes(void)
921 if (kprobe_enabled) 898 if (kprobe_enabled)
922 goto already_enabled; 899 goto already_enabled;
923 900
924 /*
925 * Re-register the page fault notifier only if there are any
926 * active probes at the time of enabling kprobes globally
927 */
928 if (atomic_read(&kprobe_count) > ARCH_INACTIVE_KPROBE_COUNT)
929 register_page_fault_notifier(&kprobe_page_fault_nb);
930
931 for (i = 0; i < KPROBE_TABLE_SIZE; i++) { 901 for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
932 head = &kprobe_table[i]; 902 head = &kprobe_table[i];
933 hlist_for_each_entry_rcu(p, node, head, hlist) 903 hlist_for_each_entry_rcu(p, node, head, hlist)
@@ -968,10 +938,7 @@ static void __kprobes disable_all_kprobes(void)
968 mutex_unlock(&kprobe_mutex); 938 mutex_unlock(&kprobe_mutex);
969 /* Allow all currently running kprobes to complete */ 939 /* Allow all currently running kprobes to complete */
970 synchronize_sched(); 940 synchronize_sched();
971 941 return;
972 mutex_lock(&kprobe_mutex);
973 /* Unconditionally unregister the page_fault notifier */
974 unregister_page_fault_notifier(&kprobe_page_fault_nb);
975 942
976already_disabled: 943already_disabled:
977 mutex_unlock(&kprobe_mutex); 944 mutex_unlock(&kprobe_mutex);