[PATCH] Kprobe: multi kprobe posthandler for booster
If there are multi kprobes on the same probepoint, there will be one extra aggr_kprobe on the head of kprobe list. The aggr_kprobe has aggr_post_handler/aggr_break_handler whether the other kprobe post_hander/break_handler is NULL or not. This patch modifies this, only when there is one or more kprobe in the list whose post_handler is not NULL, post_handler of aggr_kprobe will be set as aggr_post_handler. [soshima@redhat.com: !CONFIG_PREEMPT fix] Signed-off-by: bibo, mao <bibo.mao@intel.com> Cc: Masami Hiramatsu <hiramatu@sdl.hitachi.co.jp> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: "Keshavamurthy, Anil S" <anil.s.keshavamurthy@intel.com> Cc: Prasanna S Panchamukhi <prasanna@in.ibm.com> Cc: Jim Keniston <jkenisto@us.ibm.com> Cc: Yumiko Sugita <sugita@sdl.hitachi.co.jp> Cc: Hideo Aoki <haoki@redhat.com> Signed-off-by: Satoshi Oshima <soshima@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
585deacaca
commit
3672165677
|
@ -259,7 +259,9 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||
struct kprobe_ctlblk *kcb;
|
||||
#ifdef CONFIG_PREEMPT
|
||||
unsigned pre_preempt_count = preempt_count();
|
||||
#endif /* CONFIG_PREEMPT */
|
||||
#else
|
||||
unsigned pre_preempt_count = 1;
|
||||
#endif
|
||||
|
||||
addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t));
|
||||
|
||||
|
@ -336,22 +338,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||
/* handler has already set things up, so skip ss setup */
|
||||
return 1;
|
||||
|
||||
if (p->ainsn.boostable == 1 &&
|
||||
#ifdef CONFIG_PREEMPT
|
||||
!(pre_preempt_count) && /*
|
||||
* This enables booster when the direct
|
||||
* execution path aren't preempted.
|
||||
*/
|
||||
#endif /* CONFIG_PREEMPT */
|
||||
!p->post_handler && !p->break_handler ) {
|
||||
ss_probe:
|
||||
if (pre_preempt_count && p->ainsn.boostable == 1 && !p->post_handler){
|
||||
/* Boost up -- we can execute copied instructions directly */
|
||||
reset_current_kprobe();
|
||||
regs->eip = (unsigned long)p->ainsn.insn;
|
||||
preempt_enable_no_resched();
|
||||
return 1;
|
||||
}
|
||||
|
||||
ss_probe:
|
||||
prepare_singlestep(p, regs);
|
||||
kcb->kprobe_status = KPROBE_HIT_SS;
|
||||
return 1;
|
||||
|
|
|
@ -368,16 +368,15 @@ static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
|
|||
*/
|
||||
static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
|
||||
{
|
||||
struct kprobe *kp;
|
||||
|
||||
if (p->break_handler) {
|
||||
list_for_each_entry_rcu(kp, &old_p->list, list) {
|
||||
if (kp->break_handler)
|
||||
return -EEXIST;
|
||||
}
|
||||
if (old_p->break_handler)
|
||||
return -EEXIST;
|
||||
list_add_tail_rcu(&p->list, &old_p->list);
|
||||
old_p->break_handler = aggr_break_handler;
|
||||
} else
|
||||
list_add_rcu(&p->list, &old_p->list);
|
||||
if (p->post_handler && !old_p->post_handler)
|
||||
old_p->post_handler = aggr_post_handler;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -390,9 +389,11 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
|
|||
copy_kprobe(p, ap);
|
||||
ap->addr = p->addr;
|
||||
ap->pre_handler = aggr_pre_handler;
|
||||
ap->post_handler = aggr_post_handler;
|
||||
ap->fault_handler = aggr_fault_handler;
|
||||
ap->break_handler = aggr_break_handler;
|
||||
if (p->post_handler)
|
||||
ap->post_handler = aggr_post_handler;
|
||||
if (p->break_handler)
|
||||
ap->break_handler = aggr_break_handler;
|
||||
|
||||
INIT_LIST_HEAD(&ap->list);
|
||||
list_add_rcu(&p->list, &ap->list);
|
||||
|
@ -536,6 +537,21 @@ valid_p:
|
|||
kfree(old_p);
|
||||
}
|
||||
arch_remove_kprobe(p);
|
||||
} else {
|
||||
mutex_lock(&kprobe_mutex);
|
||||
if (p->break_handler)
|
||||
old_p->break_handler = NULL;
|
||||
if (p->post_handler){
|
||||
list_for_each_entry_rcu(list_p, &old_p->list, list){
|
||||
if (list_p->post_handler){
|
||||
cleanup_p = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cleanup_p == 0)
|
||||
old_p->post_handler = NULL;
|
||||
}
|
||||
mutex_unlock(&kprobe_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue