diff options
author | mao, bibo <bibo.mao@intel.com> | 2006-06-26 03:25:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-26 12:58:22 -0400 |
commit | 36721656776f177280ccb50477a02e86e6444292 (patch) | |
tree | 20cb06eb08e98636e97703d6e0df77790ede23cf | |
parent | 585deacaca3e7bfc63580623f0344d1fa9c47f11 (diff) |
[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>
-rw-r--r-- | arch/i386/kernel/kprobes.c | 16 | ||||
-rw-r--r-- | kernel/kprobes.c | 32 |
2 files changed, 29 insertions, 19 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index 37f86234bdd7..727e419ad78a 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c | |||
@@ -259,7 +259,9 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
259 | struct kprobe_ctlblk *kcb; | 259 | struct kprobe_ctlblk *kcb; |
260 | #ifdef CONFIG_PREEMPT | 260 | #ifdef CONFIG_PREEMPT |
261 | unsigned pre_preempt_count = preempt_count(); | 261 | unsigned pre_preempt_count = preempt_count(); |
262 | #endif /* CONFIG_PREEMPT */ | 262 | #else |
263 | unsigned pre_preempt_count = 1; | ||
264 | #endif | ||
263 | 265 | ||
264 | addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t)); | 266 | addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t)); |
265 | 267 | ||
@@ -336,22 +338,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
336 | /* handler has already set things up, so skip ss setup */ | 338 | /* handler has already set things up, so skip ss setup */ |
337 | return 1; | 339 | return 1; |
338 | 340 | ||
339 | if (p->ainsn.boostable == 1 && | 341 | ss_probe: |
340 | #ifdef CONFIG_PREEMPT | 342 | if (pre_preempt_count && p->ainsn.boostable == 1 && !p->post_handler){ |
341 | !(pre_preempt_count) && /* | ||
342 | * This enables booster when the direct | ||
343 | * execution path aren't preempted. | ||
344 | */ | ||
345 | #endif /* CONFIG_PREEMPT */ | ||
346 | !p->post_handler && !p->break_handler ) { | ||
347 | /* Boost up -- we can execute copied instructions directly */ | 343 | /* Boost up -- we can execute copied instructions directly */ |
348 | reset_current_kprobe(); | 344 | reset_current_kprobe(); |
349 | regs->eip = (unsigned long)p->ainsn.insn; | 345 | regs->eip = (unsigned long)p->ainsn.insn; |
350 | preempt_enable_no_resched(); | 346 | preempt_enable_no_resched(); |
351 | return 1; | 347 | return 1; |
352 | } | 348 | } |
353 | |||
354 | ss_probe: | ||
355 | prepare_singlestep(p, regs); | 349 | prepare_singlestep(p, regs); |
356 | kcb->kprobe_status = KPROBE_HIT_SS; | 350 | kcb->kprobe_status = KPROBE_HIT_SS; |
357 | return 1; | 351 | return 1; |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 1fbf466a29aa..f095178e48c3 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -368,16 +368,15 @@ static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p) | |||
368 | */ | 368 | */ |
369 | static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p) | 369 | static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p) |
370 | { | 370 | { |
371 | struct kprobe *kp; | ||
372 | |||
373 | if (p->break_handler) { | 371 | if (p->break_handler) { |
374 | list_for_each_entry_rcu(kp, &old_p->list, list) { | 372 | if (old_p->break_handler) |
375 | if (kp->break_handler) | 373 | return -EEXIST; |
376 | return -EEXIST; | ||
377 | } | ||
378 | list_add_tail_rcu(&p->list, &old_p->list); | 374 | list_add_tail_rcu(&p->list, &old_p->list); |
375 | old_p->break_handler = aggr_break_handler; | ||
379 | } else | 376 | } else |
380 | list_add_rcu(&p->list, &old_p->list); | 377 | list_add_rcu(&p->list, &old_p->list); |
378 | if (p->post_handler && !old_p->post_handler) | ||
379 | old_p->post_handler = aggr_post_handler; | ||
381 | return 0; | 380 | return 0; |
382 | } | 381 | } |
383 | 382 | ||
@@ -390,9 +389,11 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p) | |||
390 | copy_kprobe(p, ap); | 389 | copy_kprobe(p, ap); |
391 | ap->addr = p->addr; | 390 | ap->addr = p->addr; |
392 | ap->pre_handler = aggr_pre_handler; | 391 | ap->pre_handler = aggr_pre_handler; |
393 | ap->post_handler = aggr_post_handler; | ||
394 | ap->fault_handler = aggr_fault_handler; | 392 | ap->fault_handler = aggr_fault_handler; |
395 | ap->break_handler = aggr_break_handler; | 393 | if (p->post_handler) |
394 | ap->post_handler = aggr_post_handler; | ||
395 | if (p->break_handler) | ||
396 | ap->break_handler = aggr_break_handler; | ||
396 | 397 | ||
397 | INIT_LIST_HEAD(&ap->list); | 398 | INIT_LIST_HEAD(&ap->list); |
398 | list_add_rcu(&p->list, &ap->list); | 399 | list_add_rcu(&p->list, &ap->list); |
@@ -536,6 +537,21 @@ valid_p: | |||
536 | kfree(old_p); | 537 | kfree(old_p); |
537 | } | 538 | } |
538 | arch_remove_kprobe(p); | 539 | arch_remove_kprobe(p); |
540 | } else { | ||
541 | mutex_lock(&kprobe_mutex); | ||
542 | if (p->break_handler) | ||
543 | old_p->break_handler = NULL; | ||
544 | if (p->post_handler){ | ||
545 | list_for_each_entry_rcu(list_p, &old_p->list, list){ | ||
546 | if (list_p->post_handler){ | ||
547 | cleanup_p = 2; | ||
548 | break; | ||
549 | } | ||
550 | } | ||
551 | if (cleanup_p == 0) | ||
552 | old_p->post_handler = NULL; | ||
553 | } | ||
554 | mutex_unlock(&kprobe_mutex); | ||
539 | } | 555 | } |
540 | } | 556 | } |
541 | 557 | ||