Commit 9afe33ada275f2413dfeae27cc58fbb27474ac72

Authored by Oleg Nesterov
Committed by Linus Torvalds
1 parent 29a5551341

ptrace/x86: introduce ptrace_register_breakpoint()

No functional changes, preparation.

Extract the "register breakpoint" code from ptrace_get_debugreg() into
the new/generic helper, ptrace_register_breakpoint().  It will have more
users.

The patch also adds another simple helper, ptrace_fill_bp_fields(), to
factor out the arch_bp_generic_fields() logic in register/modify.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jan Kratochvil <jan.kratochvil@redhat.com>
Cc: Michael Neuling <mikey@neuling.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Prasad <prasad@linux.vnet.ibm.com>
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 50 additions and 36 deletions Side-by-side Diff

arch/x86/kernel/ptrace.c
... ... @@ -601,23 +601,49 @@
601 601 return dr7;
602 602 }
603 603  
604   -static int
605   -ptrace_modify_breakpoint(struct perf_event *bp, int len, int type,
606   - struct task_struct *tsk, int disabled)
  604 +static int ptrace_fill_bp_fields(struct perf_event_attr *attr,
  605 + int len, int type, bool disabled)
607 606 {
608   - int err;
609   - int gen_len, gen_type;
  607 + int err, bp_len, bp_type;
  608 +
  609 + err = arch_bp_generic_fields(len, type, &bp_len, &bp_type);
  610 + if (!err) {
  611 + attr->bp_len = bp_len;
  612 + attr->bp_type = bp_type;
  613 + attr->disabled = disabled;
  614 + }
  615 +
  616 + return err;
  617 +}
  618 +
  619 +static struct perf_event *
  620 +ptrace_register_breakpoint(struct task_struct *tsk, int len, int type,
  621 + unsigned long addr, bool disabled)
  622 +{
610 623 struct perf_event_attr attr;
  624 + int err;
611 625  
612   - err = arch_bp_generic_fields(len, type, &gen_len, &gen_type);
  626 + ptrace_breakpoint_init(&attr);
  627 + attr.bp_addr = addr;
  628 +
  629 + err = ptrace_fill_bp_fields(&attr, len, type, disabled);
613 630 if (err)
614   - return err;
  631 + return ERR_PTR(err);
615 632  
616   - attr = bp->attr;
617   - attr.bp_len = gen_len;
618   - attr.bp_type = gen_type;
619   - attr.disabled = disabled;
  633 + return register_user_hw_breakpoint(&attr, ptrace_triggered,
  634 + NULL, tsk);
  635 +}
620 636  
  637 +static int ptrace_modify_breakpoint(struct perf_event *bp, int len, int type,
  638 + int disabled)
  639 +{
  640 + struct perf_event_attr attr = bp->attr;
  641 + int err;
  642 +
  643 + err = ptrace_fill_bp_fields(&attr, len, type, disabled);
  644 + if (err)
  645 + return err;
  646 +
621 647 return modify_user_hw_breakpoint(bp, &attr);
622 648 }
623 649  
... ... @@ -653,7 +679,7 @@
653 679 break;
654 680 }
655 681  
656   - rc = ptrace_modify_breakpoint(bp, len, type, tsk, disabled);
  682 + rc = ptrace_modify_breakpoint(bp, len, type, disabled);
657 683 if (rc)
658 684 break;
659 685 }
660 686  
661 687  
662 688  
... ... @@ -693,26 +719,14 @@
693 719 static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr,
694 720 unsigned long addr)
695 721 {
696   - struct perf_event *bp;
697 722 struct thread_struct *t = &tsk->thread;
698   - struct perf_event_attr attr;
  723 + struct perf_event *bp = t->ptrace_bps[nr];
699 724 int err = 0;
700 725  
701   - if (!t->ptrace_bps[nr]) {
702   - ptrace_breakpoint_init(&attr);
  726 + if (!bp) {
703 727 /*
704   - * Put stub len and type to register (reserve) an inactive but
705   - * correct bp
706   - */
707   - attr.bp_addr = addr;
708   - attr.bp_len = HW_BREAKPOINT_LEN_1;
709   - attr.bp_type = HW_BREAKPOINT_W;
710   - attr.disabled = 1;
711   -
712   - bp = register_user_hw_breakpoint(&attr, ptrace_triggered,
713   - NULL, tsk);
714   -
715   - /*
  728 + * Put stub len and type to create an inactive but correct bp.
  729 + *
716 730 * CHECKME: the previous code returned -EIO if the addr wasn't
717 731 * a valid task virtual addr. The new one will return -EINVAL in
718 732 * this case.
719 733  
720 734  
721 735  
722 736  
... ... @@ -721,20 +735,20 @@
721 735 * writing for the user. And anyway this is the previous
722 736 * behaviour.
723 737 */
724   - if (IS_ERR(bp)) {
  738 + bp = ptrace_register_breakpoint(tsk,
  739 + X86_BREAKPOINT_LEN_1, X86_BREAKPOINT_WRITE,
  740 + addr, true);
  741 + if (IS_ERR(bp))
725 742 err = PTR_ERR(bp);
726   - goto out;
727   - }
728   -
729   - t->ptrace_bps[nr] = bp;
  743 + else
  744 + t->ptrace_bps[nr] = bp;
730 745 } else {
731   - bp = t->ptrace_bps[nr];
  746 + struct perf_event_attr attr = bp->attr;
732 747  
733   - attr = bp->attr;
734 748 attr.bp_addr = addr;
735 749 err = modify_user_hw_breakpoint(bp, &attr);
736 750 }
737   -out:
  751 +
738 752 return err;
739 753 }
740 754