
From: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>

This patch includes IA64 architecture specific changes(ported form i386) to
support temporary disarming on reentrancy of probes.

In case of reentrancy we single step without calling user handler.

Signed-of-by: Anil S Keshavamurth <anil.s.keshavamurthy@intel.com>

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 arch/ia64/kernel/kprobes.c |   49 +++++++++++++++++++++++++++++++++++++++------
 1 files changed, 43 insertions(+), 6 deletions(-)

diff -puN arch/ia64/kernel/kprobes.c~kprobes-temporary-disarming-of-reentrant-probe-for-ia64 arch/ia64/kernel/kprobes.c
--- 25/arch/ia64/kernel/kprobes.c~kprobes-temporary-disarming-of-reentrant-probe-for-ia64	2005-06-18 02:49:06.000000000 -0700
+++ 25-akpm/arch/ia64/kernel/kprobes.c	2005-06-18 02:49:06.000000000 -0700
@@ -41,8 +41,8 @@ extern void jprobe_inst_return(void);
 #define KPROBE_HIT_ACTIVE	0x00000001
 #define KPROBE_HIT_SS		0x00000002
 
-static struct kprobe *current_kprobe;
-static unsigned long kprobe_status;
+static struct kprobe *current_kprobe, *kprobe_prev;
+static unsigned long kprobe_status, kprobe_status_prev;
 static struct pt_regs jprobe_saved_regs;
 
 enum instruction_type {A, I, M, F, B, L, X, u};
@@ -273,6 +273,23 @@ static int valid_kprobe_addr(int templat
 	return 0;
 }
 
+static inline void save_previous_kprobe(void)
+{
+	kprobe_prev = current_kprobe;
+	kprobe_status_prev = kprobe_status;
+}
+
+static inline void restore_previous_kprobe(void)
+{
+	current_kprobe = kprobe_prev;
+	kprobe_status = kprobe_status_prev;
+}
+
+static inline void set_current_kprobe(struct kprobe *p)
+{
+	current_kprobe = p;
+}
+
 int arch_prepare_kprobe(struct kprobe *p)
 {
 	unsigned long addr = (unsigned long) p->addr;
@@ -436,8 +453,18 @@ static int pre_kprobes_handler(struct di
 				unlock_kprobes();
 				goto no_kprobe;
 			}
-			arch_disarm_kprobe(p);
-			ret = 1;
+			/* We have reentered the pre_kprobe_handler(), since
+			 * another probe was hit while within the handler.
+			 * We here save the original kprobes variables and
+			 * just single step on the instruction of the new probe
+			 * without calling any user handlers.
+			 */
+			save_previous_kprobe();
+			set_current_kprobe(p);
+			p->nmissed++;
+			prepare_ss(p, regs);
+			kprobe_status = KPROBE_REENTER;
+			return 1;
 		} else if (args->err == __IA64_BREAK_JPROBE) {
 			/*
 			 * jprobe instrumented function just completed
@@ -460,7 +487,7 @@ static int pre_kprobes_handler(struct di
 	}
 
 	kprobe_status = KPROBE_HIT_ACTIVE;
-	current_kprobe = p;
+	set_current_kprobe(p);
 
 	if (p->pre_handler && p->pre_handler(p, regs))
 		/*
@@ -485,12 +512,22 @@ static int post_kprobes_handler(struct p
 	if (!kprobe_running())
 		return 0;
 
-	if (current_kprobe->post_handler)
+	if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
+		kprobe_status = KPROBE_HIT_SSDONE;
 		current_kprobe->post_handler(current_kprobe, regs, 0);
+	}
 
 	resume_execution(current_kprobe, regs);
 
+	/*Restore back the original saved kprobes variables and continue. */
+	if (kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe();
+		goto out;
+	}
+
 	unlock_kprobes();
+
+out:
 	preempt_enable_no_resched();
 	return 1;
 }
_
