aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnanth N Mavinakayanahalli <ananth@in.ibm.com>2005-11-07 04:00:09 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-07 10:53:45 -0500
commit8a5c4dc5e5d72b7802f5647082ccf3861a94f013 (patch)
tree6a152d01d9b9653201a113af9c1ce3f94771bf49
parent9a0e3a86837ac7542e601c18346102c9d9e65fa5 (diff)
[PATCH] Kprobes: Track kprobe on a per_cpu basis - ia64 changes
IA64 changes to track kprobe execution on a per-cpu basis. We now track the kprobe state machine independently on each cpu using an arch specific kprobe control block. Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/ia64/kernel/kprobes.c83
-rw-r--r--include/asm-ia64/kprobes.h13
2 files changed, 58 insertions, 38 deletions
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 1e80ec80dd21..17e70b1b8d79 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -38,13 +38,8 @@
38 38
39extern void jprobe_inst_return(void); 39extern void jprobe_inst_return(void);
40 40
41/* kprobe_status settings */ 41DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
42#define KPROBE_HIT_ACTIVE 0x00000001 42DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
43#define KPROBE_HIT_SS 0x00000002
44
45static struct kprobe *current_kprobe, *kprobe_prev;
46static unsigned long kprobe_status, kprobe_status_prev;
47static struct pt_regs jprobe_saved_regs;
48 43
49enum instruction_type {A, I, M, F, B, L, X, u}; 44enum instruction_type {A, I, M, F, B, L, X, u};
50static enum instruction_type bundle_encoding[32][3] = { 45static enum instruction_type bundle_encoding[32][3] = {
@@ -313,21 +308,22 @@ static int __kprobes valid_kprobe_addr(int template, int slot,
313 return 0; 308 return 0;
314} 309}
315 310
316static inline void save_previous_kprobe(void) 311static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
317{ 312{
318 kprobe_prev = current_kprobe; 313 kcb->prev_kprobe.kp = kprobe_running();
319 kprobe_status_prev = kprobe_status; 314 kcb->prev_kprobe.status = kcb->kprobe_status;
320} 315}
321 316
322static inline void restore_previous_kprobe(void) 317static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
323{ 318{
324 current_kprobe = kprobe_prev; 319 __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
325 kprobe_status = kprobe_status_prev; 320 kcb->kprobe_status = kcb->prev_kprobe.status;
326} 321}
327 322
328static inline void set_current_kprobe(struct kprobe *p) 323static inline void set_current_kprobe(struct kprobe *p,
324 struct kprobe_ctlblk *kcb)
329{ 325{
330 current_kprobe = p; 326 __get_cpu_var(current_kprobe) = p;
331} 327}
332 328
333static void kretprobe_trampoline(void) 329static void kretprobe_trampoline(void)
@@ -389,6 +385,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
389 BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); 385 BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
390 regs->cr_iip = orig_ret_address; 386 regs->cr_iip = orig_ret_address;
391 387
388 reset_current_kprobe();
392 unlock_kprobes(); 389 unlock_kprobes();
393 preempt_enable_no_resched(); 390 preempt_enable_no_resched();
394 391
@@ -606,12 +603,13 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
606 int ret = 0; 603 int ret = 0;
607 struct pt_regs *regs = args->regs; 604 struct pt_regs *regs = args->regs;
608 kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs); 605 kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs);
606 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
609 607
610 /* Handle recursion cases */ 608 /* Handle recursion cases */
611 if (kprobe_running()) { 609 if (kprobe_running()) {
612 p = get_kprobe(addr); 610 p = get_kprobe(addr);
613 if (p) { 611 if (p) {
614 if ( (kprobe_status == KPROBE_HIT_SS) && 612 if ((kcb->kprobe_status == KPROBE_HIT_SS) &&
615 (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) { 613 (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) {
616 ia64_psr(regs)->ss = 0; 614 ia64_psr(regs)->ss = 0;
617 unlock_kprobes(); 615 unlock_kprobes();
@@ -623,17 +621,17 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
623 * just single step on the instruction of the new probe 621 * just single step on the instruction of the new probe
624 * without calling any user handlers. 622 * without calling any user handlers.
625 */ 623 */
626 save_previous_kprobe(); 624 save_previous_kprobe(kcb);
627 set_current_kprobe(p); 625 set_current_kprobe(p, kcb);
628 p->nmissed++; 626 p->nmissed++;
629 prepare_ss(p, regs); 627 prepare_ss(p, regs);
630 kprobe_status = KPROBE_REENTER; 628 kcb->kprobe_status = KPROBE_REENTER;
631 return 1; 629 return 1;
632 } else if (args->err == __IA64_BREAK_JPROBE) { 630 } else if (args->err == __IA64_BREAK_JPROBE) {
633 /* 631 /*
634 * jprobe instrumented function just completed 632 * jprobe instrumented function just completed
635 */ 633 */
636 p = current_kprobe; 634 p = __get_cpu_var(current_kprobe);
637 if (p->break_handler && p->break_handler(p, regs)) { 635 if (p->break_handler && p->break_handler(p, regs)) {
638 goto ss_probe; 636 goto ss_probe;
639 } 637 }
@@ -668,8 +666,8 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
668 * in post_kprobes_handler() 666 * in post_kprobes_handler()
669 */ 667 */
670 preempt_disable(); 668 preempt_disable();
671 kprobe_status = KPROBE_HIT_ACTIVE; 669 set_current_kprobe(p, kcb);
672 set_current_kprobe(p); 670 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
673 671
674 if (p->pre_handler && p->pre_handler(p, regs)) 672 if (p->pre_handler && p->pre_handler(p, regs))
675 /* 673 /*
@@ -681,7 +679,7 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
681 679
682ss_probe: 680ss_probe:
683 prepare_ss(p, regs); 681 prepare_ss(p, regs);
684 kprobe_status = KPROBE_HIT_SS; 682 kcb->kprobe_status = KPROBE_HIT_SS;
685 return 1; 683 return 1;
686 684
687no_kprobe: 685no_kprobe:
@@ -690,22 +688,25 @@ no_kprobe:
690 688
691static int __kprobes post_kprobes_handler(struct pt_regs *regs) 689static int __kprobes post_kprobes_handler(struct pt_regs *regs)
692{ 690{
693 if (!kprobe_running()) 691 struct kprobe *cur = kprobe_running();
692 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
693
694 if (!cur)
694 return 0; 695 return 0;
695 696
696 if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) { 697 if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
697 kprobe_status = KPROBE_HIT_SSDONE; 698 kcb->kprobe_status = KPROBE_HIT_SSDONE;
698 current_kprobe->post_handler(current_kprobe, regs, 0); 699 cur->post_handler(cur, regs, 0);
699 } 700 }
700 701
701 resume_execution(current_kprobe, regs); 702 resume_execution(cur, regs);
702 703
703 /*Restore back the original saved kprobes variables and continue. */ 704 /*Restore back the original saved kprobes variables and continue. */
704 if (kprobe_status == KPROBE_REENTER) { 705 if (kcb->kprobe_status == KPROBE_REENTER) {
705 restore_previous_kprobe(); 706 restore_previous_kprobe(kcb);
706 goto out; 707 goto out;
707 } 708 }
708 709 reset_current_kprobe();
709 unlock_kprobes(); 710 unlock_kprobes();
710 711
711out: 712out:
@@ -715,15 +716,18 @@ out:
715 716
716static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) 717static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
717{ 718{
718 if (!kprobe_running()) 719 struct kprobe *cur = kprobe_running();
720 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
721
722 if (!cur)
719 return 0; 723 return 0;
720 724
721 if (current_kprobe->fault_handler && 725 if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
722 current_kprobe->fault_handler(current_kprobe, regs, trapnr))
723 return 1; 726 return 1;
724 727
725 if (kprobe_status & KPROBE_HIT_SS) { 728 if (kcb->kprobe_status & KPROBE_HIT_SS) {
726 resume_execution(current_kprobe, regs); 729 resume_execution(cur, regs);
730 reset_current_kprobe();
727 unlock_kprobes(); 731 unlock_kprobes();
728 preempt_enable_no_resched(); 732 preempt_enable_no_resched();
729 } 733 }
@@ -761,9 +765,10 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
761{ 765{
762 struct jprobe *jp = container_of(p, struct jprobe, kp); 766 struct jprobe *jp = container_of(p, struct jprobe, kp);
763 unsigned long addr = ((struct fnptr *)(jp->entry))->ip; 767 unsigned long addr = ((struct fnptr *)(jp->entry))->ip;
768 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
764 769
765 /* save architectural state */ 770 /* save architectural state */
766 jprobe_saved_regs = *regs; 771 kcb->jprobe_saved_regs = *regs;
767 772
768 /* after rfi, execute the jprobe instrumented function */ 773 /* after rfi, execute the jprobe instrumented function */
769 regs->cr_iip = addr & ~0xFULL; 774 regs->cr_iip = addr & ~0xFULL;
@@ -781,7 +786,9 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
781 786
782int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) 787int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
783{ 788{
784 *regs = jprobe_saved_regs; 789 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
790
791 *regs = kcb->jprobe_saved_regs;
785 return 1; 792 return 1;
786} 793}
787 794
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index 573a3574a24f..592abb000e29 100644
--- a/include/asm-ia64/kprobes.h
+++ b/include/asm-ia64/kprobes.h
@@ -26,6 +26,7 @@
26 */ 26 */
27#include <linux/types.h> 27#include <linux/types.h>
28#include <linux/ptrace.h> 28#include <linux/ptrace.h>
29#include <linux/percpu.h>
29#include <asm/break.h> 30#include <asm/break.h>
30 31
31#define MAX_INSN_SIZE 16 32#define MAX_INSN_SIZE 16
@@ -62,6 +63,18 @@ typedef struct _bundle {
62 } quad1; 63 } quad1;
63} __attribute__((__aligned__(16))) bundle_t; 64} __attribute__((__aligned__(16))) bundle_t;
64 65
66struct prev_kprobe {
67 struct kprobe *kp;
68 unsigned long status;
69};
70
71/* per-cpu kprobe control block */
72struct kprobe_ctlblk {
73 unsigned long kprobe_status;
74 struct pt_regs jprobe_saved_regs;
75 struct prev_kprobe prev_kprobe;
76};
77
65#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry 78#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
66 79
67#define ARCH_SUPPORTS_KRETPROBES 80#define ARCH_SUPPORTS_KRETPROBES