aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/ptrace.c
diff options
context:
space:
mode:
authorMarkus Metzger <markus.t.metzger@intel.com>2008-11-25 03:01:25 -0500
committerIngo Molnar <mingo@elte.hu>2008-11-25 11:31:11 -0500
commitca0002a179bfa532d009a9272d619732872c49bd (patch)
tree9a9ca02164dfb2c13afaa38ab67f3f15d8dd5ce8 /arch/x86/kernel/ptrace.c
parent7d55718b0c19ba611241c330f688ee824e9bab79 (diff)
x86, bts: base in-kernel ds interface on handles
Impact: generalize the DS code to shared buffers Change the in-kernel ds.h interface to identify the tracer via a handle returned on ds_request_~(). Tracers used to be identified via their task_struct. The changes are required to allow DS to be shared between different tasks, which is needed for perfmon2 and for ftrace. For ptrace, the handle is stored in the traced task's task_struct. This should probably go into a (arch-specific) ptrace context some time. Signed-off-by: Markus Metzger <markus.t.metzger@intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/ptrace.c')
-rw-r--r--arch/x86/kernel/ptrace.c73
1 files changed, 40 insertions, 33 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 06180dff5b2e..76adf5b640ff 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -668,14 +668,14 @@ static int ptrace_bts_read_record(struct task_struct *child, size_t index,
668 size_t bts_index, bts_end; 668 size_t bts_index, bts_end;
669 int error; 669 int error;
670 670
671 error = ds_get_bts_end(child, &bts_end); 671 error = ds_get_bts_end(child->bts, &bts_end);
672 if (error < 0) 672 if (error < 0)
673 return error; 673 return error;
674 674
675 if (bts_end <= index) 675 if (bts_end <= index)
676 return -EINVAL; 676 return -EINVAL;
677 677
678 error = ds_get_bts_index(child, &bts_index); 678 error = ds_get_bts_index(child->bts, &bts_index);
679 if (error < 0) 679 if (error < 0)
680 return error; 680 return error;
681 681
@@ -684,7 +684,7 @@ static int ptrace_bts_read_record(struct task_struct *child, size_t index,
684 if (bts_end <= bts_index) 684 if (bts_end <= bts_index)
685 bts_index -= bts_end; 685 bts_index -= bts_end;
686 686
687 error = ds_access_bts(child, bts_index, &bts_record); 687 error = ds_access_bts(child->bts, bts_index, &bts_record);
688 if (error < 0) 688 if (error < 0)
689 return error; 689 return error;
690 690
@@ -705,14 +705,14 @@ static int ptrace_bts_drain(struct task_struct *child,
705 size_t end, i; 705 size_t end, i;
706 int error; 706 int error;
707 707
708 error = ds_get_bts_index(child, &end); 708 error = ds_get_bts_index(child->bts, &end);
709 if (error < 0) 709 if (error < 0)
710 return error; 710 return error;
711 711
712 if (size < (end * sizeof(struct bts_struct))) 712 if (size < (end * sizeof(struct bts_struct)))
713 return -EIO; 713 return -EIO;
714 714
715 error = ds_access_bts(child, 0, (const void **)&raw); 715 error = ds_access_bts(child->bts, 0, (const void **)&raw);
716 if (error < 0) 716 if (error < 0)
717 return error; 717 return error;
718 718
@@ -723,18 +723,13 @@ static int ptrace_bts_drain(struct task_struct *child,
723 return -EFAULT; 723 return -EFAULT;
724 } 724 }
725 725
726 error = ds_clear_bts(child); 726 error = ds_clear_bts(child->bts);
727 if (error < 0) 727 if (error < 0)
728 return error; 728 return error;
729 729
730 return end; 730 return end;
731} 731}
732 732
733static void ptrace_bts_ovfl(struct task_struct *child)
734{
735 send_sig(child->thread.bts_ovfl_signal, child, 0);
736}
737
738static int ptrace_bts_config(struct task_struct *child, 733static int ptrace_bts_config(struct task_struct *child,
739 long cfg_size, 734 long cfg_size,
740 const struct ptrace_bts_config __user *ucfg) 735 const struct ptrace_bts_config __user *ucfg)
@@ -760,23 +755,29 @@ static int ptrace_bts_config(struct task_struct *child,
760 goto errout; 755 goto errout;
761 756
762 if (cfg.flags & PTRACE_BTS_O_ALLOC) { 757 if (cfg.flags & PTRACE_BTS_O_ALLOC) {
763 ds_ovfl_callback_t ovfl = NULL; 758 bts_ovfl_callback_t ovfl = NULL;
764 unsigned int sig = 0; 759 unsigned int sig = 0;
765 760
766 /* we ignore the error in case we were not tracing child */
767 (void)ds_release_bts(child);
768
769 if (cfg.flags & PTRACE_BTS_O_SIGNAL) { 761 if (cfg.flags & PTRACE_BTS_O_SIGNAL) {
770 if (!cfg.signal) 762 if (!cfg.signal)
771 goto errout; 763 goto errout;
772 764
765 error = -EOPNOTSUPP;
766 goto errout;
767
773 sig = cfg.signal; 768 sig = cfg.signal;
774 ovfl = ptrace_bts_ovfl;
775 } 769 }
776 770
777 error = ds_request_bts(child, /* base = */ NULL, cfg.size, ovfl); 771 if (child->bts)
778 if (error < 0) 772 (void)ds_release_bts(child->bts);
773
774 child->bts = ds_request_bts(child, /* base = */ NULL, cfg.size,
775 ovfl, /* th = */ (size_t)-1);
776 if (IS_ERR(child->bts)) {
777 error = PTR_ERR(child->bts);
778 child->bts = NULL;
779 goto errout; 779 goto errout;
780 }
780 781
781 child->thread.bts_ovfl_signal = sig; 782 child->thread.bts_ovfl_signal = sig;
782 } 783 }
@@ -823,15 +824,15 @@ static int ptrace_bts_status(struct task_struct *child,
823 if (cfg_size < sizeof(cfg)) 824 if (cfg_size < sizeof(cfg))
824 return -EIO; 825 return -EIO;
825 826
826 error = ds_get_bts_end(child, &end); 827 error = ds_get_bts_end(child->bts, &end);
827 if (error < 0) 828 if (error < 0)
828 return error; 829 return error;
829 830
830 error = ds_access_bts(child, /* index = */ 0, &base); 831 error = ds_access_bts(child->bts, /* index = */ 0, &base);
831 if (error < 0) 832 if (error < 0)
832 return error; 833 return error;
833 834
834 error = ds_access_bts(child, /* index = */ end, &max); 835 error = ds_access_bts(child->bts, /* index = */ end, &max);
835 if (error < 0) 836 if (error < 0)
836 return error; 837 return error;
837 838
@@ -884,10 +885,7 @@ static int ptrace_bts_write_record(struct task_struct *child,
884 return -EINVAL; 885 return -EINVAL;
885 } 886 }
886 887
887 /* The writing task will be the switched-to task on a context 888 return ds_write_bts(child->bts, bts_record, bts_cfg.sizeof_bts);
888 * switch. It needs to write into the switched-from task's BTS
889 * buffer. */
890 return ds_unchecked_write_bts(child, bts_record, bts_cfg.sizeof_bts);
891} 889}
892 890
893void ptrace_bts_take_timestamp(struct task_struct *tsk, 891void ptrace_bts_take_timestamp(struct task_struct *tsk,
@@ -972,13 +970,15 @@ void ptrace_disable(struct task_struct *child)
972 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); 970 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
973#endif 971#endif
974#ifdef CONFIG_X86_PTRACE_BTS 972#ifdef CONFIG_X86_PTRACE_BTS
975 (void)ds_release_bts(child); 973 if (child->bts) {
974 (void)ds_release_bts(child->bts);
976 975
977 child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask; 976 child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask;
978 if (!child->thread.debugctlmsr) 977 if (!child->thread.debugctlmsr)
979 clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); 978 clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR);
980 979
981 clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); 980 clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS);
981 }
982#endif /* CONFIG_X86_PTRACE_BTS */ 982#endif /* CONFIG_X86_PTRACE_BTS */
983} 983}
984 984
@@ -1110,9 +1110,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
1110 (child, data, (struct ptrace_bts_config __user *)addr); 1110 (child, data, (struct ptrace_bts_config __user *)addr);
1111 break; 1111 break;
1112 1112
1113 case PTRACE_BTS_SIZE: 1113 case PTRACE_BTS_SIZE: {
1114 ret = ds_get_bts_index(child, /* pos = */ NULL); 1114 size_t size;
1115
1116 ret = ds_get_bts_index(child->bts, &size);
1117 if (ret == 0) {
1118 BUG_ON(size != (int) size);
1119 ret = (int) size;
1120 }
1115 break; 1121 break;
1122 }
1116 1123
1117 case PTRACE_BTS_GET: 1124 case PTRACE_BTS_GET:
1118 ret = ptrace_bts_read_record 1125 ret = ptrace_bts_read_record
@@ -1120,7 +1127,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
1120 break; 1127 break;
1121 1128
1122 case PTRACE_BTS_CLEAR: 1129 case PTRACE_BTS_CLEAR:
1123 ret = ds_clear_bts(child); 1130 ret = ds_clear_bts(child->bts);
1124 break; 1131 break;
1125 1132
1126 case PTRACE_BTS_DRAIN: 1133 case PTRACE_BTS_DRAIN: