Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=796969104cab0d454dbc792ad0d12a4f365a8564
Commit:     796969104cab0d454dbc792ad0d12a4f365a8564
Parent:     785d3cd286f0bf67d1bf692559b9ae5de12678f5
Author:     Nicolas Pitre <[EMAIL PROTECTED]>
AuthorDate: Mon Dec 3 17:22:36 2007 -0500
Committer:  Russell King <[EMAIL PROTECTED]>
CommitDate: Sat Jan 26 15:25:17 2008 +0000

    ARM kprobes: special hook for the kprobes breakpoint handler
    
    The kprobes code is already able to cope with reentrant probes, so its
    handler must be called outside of the region protected by undef_lock.
    
    If ever this lock is released when handlers are called then this commit
    could be reverted.
    
    Signed-off-by: Nicolas Pitre <[EMAIL PROTECTED]>
---
 arch/arm/kernel/kprobes.c |    8 +-------
 arch/arm/kernel/traps.c   |   12 ++++++++++++
 include/asm-arm/kprobes.h |    7 +++++++
 3 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 450ee2c..a22a98c 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -26,12 +26,6 @@
 #include <asm/traps.h>
 #include <asm/cacheflush.h>
 
-/*
- * This undefined instruction must be unique and
- * reserved solely for kprobes' use.
- */
-#define KPROBE_BREAKPOINT_INSTRUCTION  0xe7f001f8
-
 #define MIN_STACK_SIZE(addr)                           \
        min((unsigned long)MAX_STACK_SIZE,              \
            (unsigned long)current_thread_info() + THREAD_START_SP - (addr))
@@ -206,7 +200,7 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
        }
 }
 
-static int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
+int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
 {
        kprobe_handler(regs);
        return 0;
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 65bb762..5595fdd 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -19,6 +19,7 @@
 #include <linux/kallsyms.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/kprobes.h>
 
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
@@ -313,6 +314,17 @@ asmlinkage void __exception do_undefinstr(struct pt_regs 
*regs)
                get_user(instr, (u32 __user *)pc);
        }
 
+#ifdef CONFIG_KPROBES
+       /*
+        * It is possible to have recursive kprobes, so we can't call
+        * the kprobe trap handler with the undef_lock held.
+        */
+       if (instr == KPROBE_BREAKPOINT_INSTRUCTION && !user_mode(regs)) {
+               kprobe_trap_handler(regs, instr);
+               return;
+       }
+#endif
+
        spin_lock_irqsave(&undef_lock, flags);
        list_for_each_entry(hook, &undef_hook, node) {
                if ((instr & hook->instr_mask) == hook->instr_val &&
diff --git a/include/asm-arm/kprobes.h b/include/asm-arm/kprobes.h
index 273f374..4e7bd32 100644
--- a/include/asm-arm/kprobes.h
+++ b/include/asm-arm/kprobes.h
@@ -25,6 +25,12 @@
 #define MAX_INSN_SIZE                  2
 #define MAX_STACK_SIZE                 64      /* 32 would probably be OK */
 
+/*
+ * This undefined instruction must be unique and
+ * reserved solely for kprobes' use.
+ */
+#define KPROBE_BREAKPOINT_INSTRUCTION  0xe7f001f8
+
 #define regs_return_value(regs)                ((regs)->ARM_r0)
 #define flush_insn_slot(p)             do { } while (0)
 #define kretprobe_blacklist_size       0
@@ -55,6 +61,7 @@ struct kprobe_ctlblk {
 
 void arch_remove_kprobe(struct kprobe *);
 
+int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr);
 int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
 int kprobe_exceptions_notify(struct notifier_block *self,
                             unsigned long val, void *data);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to