aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel/kprobes.c
diff options
context:
space:
mode:
authorAnil S Keshavamurthy <anil.s.keshavamurthy@intel.com>2005-06-23 03:09:40 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-23 12:45:25 -0400
commit852caccc89d3883522e87a91bfa89fd9c9cfe15a (patch)
treedbbb98df18b04f7624f72d4a80731d7309038b79 /arch/ia64/kernel/kprobes.c
parente539c2331414e73a5a1b79fb57369d79447c1cf8 (diff)
[PATCH] Kprobes/ia64: temporary disarming of reentrant probe
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> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/ia64/kernel/kprobes.c')
-rw-r--r--arch/ia64/kernel/kprobes.c49
1 files changed, 43 insertions, 6 deletions
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 41e80b42d3f3..5978823d5c63 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -41,8 +41,8 @@ extern void jprobe_inst_return(void);
41#define KPROBE_HIT_ACTIVE 0x00000001 41#define KPROBE_HIT_ACTIVE 0x00000001
42#define KPROBE_HIT_SS 0x00000002 42#define KPROBE_HIT_SS 0x00000002
43 43
44static struct kprobe *current_kprobe; 44static struct kprobe *current_kprobe, *kprobe_prev;
45static unsigned long kprobe_status; 45static unsigned long kprobe_status, kprobe_status_prev;
46static struct pt_regs jprobe_saved_regs; 46static struct pt_regs jprobe_saved_regs;
47 47
48enum instruction_type {A, I, M, F, B, L, X, u}; 48enum instruction_type {A, I, M, F, B, L, X, u};
@@ -273,6 +273,23 @@ static int valid_kprobe_addr(int template, int slot, unsigned long addr)
273 return 0; 273 return 0;
274} 274}
275 275
276static inline void save_previous_kprobe(void)
277{
278 kprobe_prev = current_kprobe;
279 kprobe_status_prev = kprobe_status;
280}
281
282static inline void restore_previous_kprobe(void)
283{
284 current_kprobe = kprobe_prev;
285 kprobe_status = kprobe_status_prev;
286}
287
288static inline void set_current_kprobe(struct kprobe *p)
289{
290 current_kprobe = p;
291}
292
276int arch_prepare_kprobe(struct kprobe *p) 293int arch_prepare_kprobe(struct kprobe *p)
277{ 294{
278 unsigned long addr = (unsigned long) p->addr; 295 unsigned long addr = (unsigned long) p->addr;
@@ -436,8 +453,18 @@ static int pre_kprobes_handler(struct die_args *args)
436 unlock_kprobes(); 453 unlock_kprobes();
437 goto no_kprobe; 454 goto no_kprobe;
438 } 455 }
439 arch_disarm_kprobe(p); 456 /* We have reentered the pre_kprobe_handler(), since
440 ret = 1; 457 * another probe was hit while within the handler.
458 * We here save the original kprobes variables and
459 * just single step on the instruction of the new probe
460 * without calling any user handlers.
461 */
462 save_previous_kprobe();
463 set_current_kprobe(p);
464 p->nmissed++;
465 prepare_ss(p, regs);
466 kprobe_status = KPROBE_REENTER;
467 return 1;
441 } else if (args->err == __IA64_BREAK_JPROBE) { 468 } else if (args->err == __IA64_BREAK_JPROBE) {
442 /* 469 /*
443 * jprobe instrumented function just completed 470 * jprobe instrumented function just completed
@@ -460,7 +487,7 @@ static int pre_kprobes_handler(struct die_args *args)
460 } 487 }
461 488
462 kprobe_status = KPROBE_HIT_ACTIVE; 489 kprobe_status = KPROBE_HIT_ACTIVE;
463 current_kprobe = p; 490 set_current_kprobe(p);
464 491
465 if (p->pre_handler && p->pre_handler(p, regs)) 492 if (p->pre_handler && p->pre_handler(p, regs))
466 /* 493 /*
@@ -485,12 +512,22 @@ static int post_kprobes_handler(struct pt_regs *regs)
485 if (!kprobe_running()) 512 if (!kprobe_running())
486 return 0; 513 return 0;
487 514
488 if (current_kprobe->post_handler) 515 if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
516 kprobe_status = KPROBE_HIT_SSDONE;
489 current_kprobe->post_handler(current_kprobe, regs, 0); 517 current_kprobe->post_handler(current_kprobe, regs, 0);
518 }
490 519
491 resume_execution(current_kprobe, regs); 520 resume_execution(current_kprobe, regs);
492 521
522 /*Restore back the original saved kprobes variables and continue. */
523 if (kprobe_status == KPROBE_REENTER) {
524 restore_previous_kprobe();
525 goto out;
526 }
527
493 unlock_kprobes(); 528 unlock_kprobes();
529
530out:
494 preempt_enable_no_resched(); 531 preempt_enable_no_resched();
495 return 1; 532 return 1;
496} 533}