aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/kprobes.c
diff options
context:
space:
mode:
authorHarvey Harrison <harvey.harrison@gmail.com>2008-01-30 07:32:19 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:32:19 -0500
commitb97601563704751162b122c652d7f390b8f480d2 (patch)
tree81b0e2a22fb19ddb27bcb3c0bba769feafdc26e4 /arch/x86/kernel/kprobes.c
parent33cb52438341d6e2d7e06e3b64ed776bc54a2ca4 (diff)
x86: kprobes change kprobe_handler flow
Make the control flow of kprobe_handler more obvious. Collapse the separate if blocks/gotos with if/else blocks this unifies the duplication of the check for a breakpoint instruction race with another cpu. Create two jump targets: preempt_out: re-enables preemption before returning ret out: only returns ret Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/kprobes.c')
-rw-r--r--arch/x86/kernel/kprobes.c60
1 files changed, 28 insertions, 32 deletions
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index 80bcb7635465..a72e02bf1135 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -494,32 +494,28 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
494 preempt_disable(); 494 preempt_disable();
495 kcb = get_kprobe_ctlblk(); 495 kcb = get_kprobe_ctlblk();
496 496
497 /* Check we're not actually recursing */ 497 p = get_kprobe(addr);
498 if (kprobe_running()) { 498 if (p) {
499 p = get_kprobe(addr); 499 /* Check we're not actually recursing */
500 if (p) { 500 if (kprobe_running()) {
501 ret = reenter_kprobe(p, regs, kcb); 501 ret = reenter_kprobe(p, regs, kcb);
502 if (kcb->kprobe_status == KPROBE_REENTER) 502 if (kcb->kprobe_status == KPROBE_REENTER)
503 return 1; 503 {
504 ret = 1;
505 goto out;
506 }
507 goto preempt_out;
504 } else { 508 } else {
505 if (*addr != BREAKPOINT_INSTRUCTION) { 509 set_current_kprobe(p, regs, kcb);
506 /* The breakpoint instruction was removed by 510 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
507 * another cpu right after we hit, no further 511 if (p->pre_handler && p->pre_handler(p, regs))
508 * handling of this interrupt is appropriate 512 {
509 */ 513 /* handler set things up, skip ss setup */
510 regs->ip = (unsigned long)addr;
511 ret = 1; 514 ret = 1;
512 goto no_kprobe; 515 goto out;
513 } 516 }
514 p = __get_cpu_var(current_kprobe);
515 if (p->break_handler && p->break_handler(p, regs))
516 goto ss_probe;
517 } 517 }
518 goto no_kprobe; 518 } else {
519 }
520
521 p = get_kprobe(addr);
522 if (!p) {
523 if (*addr != BREAKPOINT_INSTRUCTION) { 519 if (*addr != BREAKPOINT_INSTRUCTION) {
524 /* 520 /*
525 * The breakpoint instruction was removed right 521 * The breakpoint instruction was removed right
@@ -532,34 +528,34 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
532 */ 528 */
533 regs->ip = (unsigned long)addr; 529 regs->ip = (unsigned long)addr;
534 ret = 1; 530 ret = 1;
531 goto preempt_out;
532 }
533 if (kprobe_running()) {
534 p = __get_cpu_var(current_kprobe);
535 if (p->break_handler && p->break_handler(p, regs))
536 goto ss_probe;
535 } 537 }
536 /* Not one of ours: let kernel handle it */ 538 /* Not one of ours: let kernel handle it */
537 goto no_kprobe; 539 goto preempt_out;
538 } 540 }
539 541
540 set_current_kprobe(p, regs, kcb);
541 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
542
543 if (p->pre_handler && p->pre_handler(p, regs))
544 /* handler has already set things up, so skip ss setup */
545 return 1;
546
547ss_probe: 542ss_probe:
543 ret = 1;
548#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM) 544#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM)
549 if (p->ainsn.boostable == 1 && !p->post_handler) { 545 if (p->ainsn.boostable == 1 && !p->post_handler) {
550 /* Boost up -- we can execute copied instructions directly */ 546 /* Boost up -- we can execute copied instructions directly */
551 reset_current_kprobe(); 547 reset_current_kprobe();
552 regs->ip = (unsigned long)p->ainsn.insn; 548 regs->ip = (unsigned long)p->ainsn.insn;
553 preempt_enable_no_resched(); 549 goto preempt_out;
554 return 1;
555 } 550 }
556#endif 551#endif
557 prepare_singlestep(p, regs); 552 prepare_singlestep(p, regs);
558 kcb->kprobe_status = KPROBE_HIT_SS; 553 kcb->kprobe_status = KPROBE_HIT_SS;
559 return 1; 554 goto out;
560 555
561no_kprobe: 556preempt_out:
562 preempt_enable_no_resched(); 557 preempt_enable_no_resched();
558out:
563 return ret; 559 return ret;
564} 560}
565 561