aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/ptrace.c')
-rw-r--r--arch/x86/kernel/ptrace.c398
1 files changed, 109 insertions, 289 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 06180dff5b2e..45e9855da2d2 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -581,158 +581,73 @@ static int ioperm_get(struct task_struct *target,
581} 581}
582 582
583#ifdef CONFIG_X86_PTRACE_BTS 583#ifdef CONFIG_X86_PTRACE_BTS
584/*
585 * The configuration for a particular BTS hardware implementation.
586 */
587struct bts_configuration {
588 /* the size of a BTS record in bytes; at most BTS_MAX_RECORD_SIZE */
589 unsigned char sizeof_bts;
590 /* the size of a field in the BTS record in bytes */
591 unsigned char sizeof_field;
592 /* a bitmask to enable/disable BTS in DEBUGCTL MSR */
593 unsigned long debugctl_mask;
594};
595static struct bts_configuration bts_cfg;
596
597#define BTS_MAX_RECORD_SIZE (8 * 3)
598
599
600/*
601 * Branch Trace Store (BTS) uses the following format. Different
602 * architectures vary in the size of those fields.
603 * - source linear address
604 * - destination linear address
605 * - flags
606 *
607 * Later architectures use 64bit pointers throughout, whereas earlier
608 * architectures use 32bit pointers in 32bit mode.
609 *
610 * We compute the base address for the first 8 fields based on:
611 * - the field size stored in the DS configuration
612 * - the relative field position
613 *
614 * In order to store additional information in the BTS buffer, we use
615 * a special source address to indicate that the record requires
616 * special interpretation.
617 *
618 * Netburst indicated via a bit in the flags field whether the branch
619 * was predicted; this is ignored.
620 */
621
622enum bts_field {
623 bts_from = 0,
624 bts_to,
625 bts_flags,
626
627 bts_escape = (unsigned long)-1,
628 bts_qual = bts_to,
629 bts_jiffies = bts_flags
630};
631
632static inline unsigned long bts_get(const char *base, enum bts_field field)
633{
634 base += (bts_cfg.sizeof_field * field);
635 return *(unsigned long *)base;
636}
637
638static inline void bts_set(char *base, enum bts_field field, unsigned long val)
639{
640 base += (bts_cfg.sizeof_field * field);;
641 (*(unsigned long *)base) = val;
642}
643
644/*
645 * Translate a BTS record from the raw format into the bts_struct format
646 *
647 * out (out): bts_struct interpretation
648 * raw: raw BTS record
649 */
650static void ptrace_bts_translate_record(struct bts_struct *out, const void *raw)
651{
652 memset(out, 0, sizeof(*out));
653 if (bts_get(raw, bts_from) == bts_escape) {
654 out->qualifier = bts_get(raw, bts_qual);
655 out->variant.jiffies = bts_get(raw, bts_jiffies);
656 } else {
657 out->qualifier = BTS_BRANCH;
658 out->variant.lbr.from_ip = bts_get(raw, bts_from);
659 out->variant.lbr.to_ip = bts_get(raw, bts_to);
660 }
661}
662
663static int ptrace_bts_read_record(struct task_struct *child, size_t index, 584static int ptrace_bts_read_record(struct task_struct *child, size_t index,
664 struct bts_struct __user *out) 585 struct bts_struct __user *out)
665{ 586{
666 struct bts_struct ret; 587 const struct bts_trace *trace;
667 const void *bts_record; 588 struct bts_struct bts;
668 size_t bts_index, bts_end; 589 const unsigned char *at;
669 int error; 590 int error;
670 591
671 error = ds_get_bts_end(child, &bts_end); 592 trace = ds_read_bts(child->bts);
672 if (error < 0) 593 if (!trace)
673 return error; 594 return -EPERM;
674 595
675 if (bts_end <= index) 596 at = trace->ds.top - ((index + 1) * trace->ds.size);
676 return -EINVAL; 597 if ((void *)at < trace->ds.begin)
677 598 at += (trace->ds.n * trace->ds.size);
678 error = ds_get_bts_index(child, &bts_index);
679 if (error < 0)
680 return error;
681 599
682 /* translate the ptrace bts index into the ds bts index */ 600 if (!trace->read)
683 bts_index += bts_end - (index + 1); 601 return -EOPNOTSUPP;
684 if (bts_end <= bts_index)
685 bts_index -= bts_end;
686 602
687 error = ds_access_bts(child, bts_index, &bts_record); 603 error = trace->read(child->bts, at, &bts);
688 if (error < 0) 604 if (error < 0)
689 return error; 605 return error;
690 606
691 ptrace_bts_translate_record(&ret, bts_record); 607 if (copy_to_user(out, &bts, sizeof(bts)))
692
693 if (copy_to_user(out, &ret, sizeof(ret)))
694 return -EFAULT; 608 return -EFAULT;
695 609
696 return sizeof(ret); 610 return sizeof(bts);
697} 611}
698 612
699static int ptrace_bts_drain(struct task_struct *child, 613static int ptrace_bts_drain(struct task_struct *child,
700 long size, 614 long size,
701 struct bts_struct __user *out) 615 struct bts_struct __user *out)
702{ 616{
703 struct bts_struct ret; 617 const struct bts_trace *trace;
704 const unsigned char *raw; 618 const unsigned char *at;
705 size_t end, i; 619 int error, drained = 0;
706 int error;
707 620
708 error = ds_get_bts_index(child, &end); 621 trace = ds_read_bts(child->bts);
709 if (error < 0) 622 if (!trace)
710 return error; 623 return -EPERM;
711 624
712 if (size < (end * sizeof(struct bts_struct))) 625 if (!trace->read)
626 return -EOPNOTSUPP;
627
628 if (size < (trace->ds.top - trace->ds.begin))
713 return -EIO; 629 return -EIO;
714 630
715 error = ds_access_bts(child, 0, (const void **)&raw); 631 for (at = trace->ds.begin; (void *)at < trace->ds.top;
716 if (error < 0) 632 out++, drained++, at += trace->ds.size) {
717 return error; 633 struct bts_struct bts;
634 int error;
718 635
719 for (i = 0; i < end; i++, out++, raw += bts_cfg.sizeof_bts) { 636 error = trace->read(child->bts, at, &bts);
720 ptrace_bts_translate_record(&ret, raw); 637 if (error < 0)
638 return error;
721 639
722 if (copy_to_user(out, &ret, sizeof(ret))) 640 if (copy_to_user(out, &bts, sizeof(bts)))
723 return -EFAULT; 641 return -EFAULT;
724 } 642 }
725 643
726 error = ds_clear_bts(child); 644 memset(trace->ds.begin, 0, trace->ds.n * trace->ds.size);
645
646 error = ds_reset_bts(child->bts);
727 if (error < 0) 647 if (error < 0)
728 return error; 648 return error;
729 649
730 return end; 650 return drained;
731}
732
733static void ptrace_bts_ovfl(struct task_struct *child)
734{
735 send_sig(child->thread.bts_ovfl_signal, child, 0);
736} 651}
737 652
738static int ptrace_bts_config(struct task_struct *child, 653static int ptrace_bts_config(struct task_struct *child,
@@ -740,114 +655,89 @@ static int ptrace_bts_config(struct task_struct *child,
740 const struct ptrace_bts_config __user *ucfg) 655 const struct ptrace_bts_config __user *ucfg)
741{ 656{
742 struct ptrace_bts_config cfg; 657 struct ptrace_bts_config cfg;
743 int error = 0; 658 unsigned int flags = 0;
744
745 error = -EOPNOTSUPP;
746 if (!bts_cfg.sizeof_bts)
747 goto errout;
748 659
749 error = -EIO;
750 if (cfg_size < sizeof(cfg)) 660 if (cfg_size < sizeof(cfg))
751 goto errout; 661 return -EIO;
752 662
753 error = -EFAULT;
754 if (copy_from_user(&cfg, ucfg, sizeof(cfg))) 663 if (copy_from_user(&cfg, ucfg, sizeof(cfg)))
755 goto errout; 664 return -EFAULT;
756
757 error = -EINVAL;
758 if ((cfg.flags & PTRACE_BTS_O_SIGNAL) &&
759 !(cfg.flags & PTRACE_BTS_O_ALLOC))
760 goto errout;
761 665
762 if (cfg.flags & PTRACE_BTS_O_ALLOC) { 666 if (child->bts) {
763 ds_ovfl_callback_t ovfl = NULL; 667 ds_release_bts(child->bts);
764 unsigned int sig = 0; 668 child->bts = NULL;
669 }
765 670
766 /* we ignore the error in case we were not tracing child */ 671 if (cfg.flags & PTRACE_BTS_O_SIGNAL) {
767 (void)ds_release_bts(child); 672 if (!cfg.signal)
673 return -EINVAL;
768 674
769 if (cfg.flags & PTRACE_BTS_O_SIGNAL) { 675 return -EOPNOTSUPP;
770 if (!cfg.signal)
771 goto errout;
772 676
773 sig = cfg.signal; 677 child->thread.bts_ovfl_signal = cfg.signal;
774 ovfl = ptrace_bts_ovfl; 678 }
775 }
776 679
777 error = ds_request_bts(child, /* base = */ NULL, cfg.size, ovfl); 680 if ((cfg.flags & PTRACE_BTS_O_ALLOC) &&
778 if (error < 0) 681 (cfg.size != child->bts_size)) {
779 goto errout; 682 kfree(child->bts_buffer);
780 683
781 child->thread.bts_ovfl_signal = sig; 684 child->bts_size = cfg.size;
685 child->bts_buffer = kzalloc(cfg.size, GFP_KERNEL);
686 if (!child->bts_buffer) {
687 child->bts_size = 0;
688 return -ENOMEM;
689 }
782 } 690 }
783 691
784 error = -EINVAL;
785 if (!child->thread.ds_ctx && cfg.flags)
786 goto errout;
787
788 if (cfg.flags & PTRACE_BTS_O_TRACE) 692 if (cfg.flags & PTRACE_BTS_O_TRACE)
789 child->thread.debugctlmsr |= bts_cfg.debugctl_mask; 693 flags |= BTS_USER;
790 else
791 child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask;
792 694
793 if (cfg.flags & PTRACE_BTS_O_SCHED) 695 if (cfg.flags & PTRACE_BTS_O_SCHED)
794 set_tsk_thread_flag(child, TIF_BTS_TRACE_TS); 696 flags |= BTS_TIMESTAMPS;
795 else
796 clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS);
797 697
798 error = sizeof(cfg); 698 child->bts = ds_request_bts(child, child->bts_buffer, child->bts_size,
699 /* ovfl = */ NULL, /* th = */ (size_t)-1,
700 flags);
701 if (IS_ERR(child->bts)) {
702 int error = PTR_ERR(child->bts);
799 703
800out: 704 kfree(child->bts_buffer);
801 if (child->thread.debugctlmsr) 705 child->bts = NULL;
802 set_tsk_thread_flag(child, TIF_DEBUGCTLMSR); 706 child->bts_buffer = NULL;
803 else 707 child->bts_size = 0;
804 clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR);
805 708
806 return error; 709 return error;
710 }
807 711
808errout: 712 return sizeof(cfg);
809 child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask;
810 clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS);
811 goto out;
812} 713}
813 714
814static int ptrace_bts_status(struct task_struct *child, 715static int ptrace_bts_status(struct task_struct *child,
815 long cfg_size, 716 long cfg_size,
816 struct ptrace_bts_config __user *ucfg) 717 struct ptrace_bts_config __user *ucfg)
817{ 718{
719 const struct bts_trace *trace;
818 struct ptrace_bts_config cfg; 720 struct ptrace_bts_config cfg;
819 size_t end;
820 const void *base, *max;
821 int error;
822 721
823 if (cfg_size < sizeof(cfg)) 722 if (cfg_size < sizeof(cfg))
824 return -EIO; 723 return -EIO;
825 724
826 error = ds_get_bts_end(child, &end); 725 trace = ds_read_bts(child->bts);
827 if (error < 0) 726 if (!trace)
828 return error; 727 return -EPERM;
829
830 error = ds_access_bts(child, /* index = */ 0, &base);
831 if (error < 0)
832 return error;
833
834 error = ds_access_bts(child, /* index = */ end, &max);
835 if (error < 0)
836 return error;
837 728
838 memset(&cfg, 0, sizeof(cfg)); 729 memset(&cfg, 0, sizeof(cfg));
839 cfg.size = (max - base); 730 cfg.size = trace->ds.end - trace->ds.begin;
840 cfg.signal = child->thread.bts_ovfl_signal; 731 cfg.signal = child->thread.bts_ovfl_signal;
841 cfg.bts_size = sizeof(struct bts_struct); 732 cfg.bts_size = sizeof(struct bts_struct);
842 733
843 if (cfg.signal) 734 if (cfg.signal)
844 cfg.flags |= PTRACE_BTS_O_SIGNAL; 735 cfg.flags |= PTRACE_BTS_O_SIGNAL;
845 736
846 if (test_tsk_thread_flag(child, TIF_DEBUGCTLMSR) && 737 if (trace->ds.flags & BTS_USER)
847 child->thread.debugctlmsr & bts_cfg.debugctl_mask)
848 cfg.flags |= PTRACE_BTS_O_TRACE; 738 cfg.flags |= PTRACE_BTS_O_TRACE;
849 739
850 if (test_tsk_thread_flag(child, TIF_BTS_TRACE_TS)) 740 if (trace->ds.flags & BTS_TIMESTAMPS)
851 cfg.flags |= PTRACE_BTS_O_SCHED; 741 cfg.flags |= PTRACE_BTS_O_SCHED;
852 742
853 if (copy_to_user(ucfg, &cfg, sizeof(cfg))) 743 if (copy_to_user(ucfg, &cfg, sizeof(cfg)))
@@ -856,107 +746,28 @@ static int ptrace_bts_status(struct task_struct *child,
856 return sizeof(cfg); 746 return sizeof(cfg);
857} 747}
858 748
859static int ptrace_bts_write_record(struct task_struct *child, 749static int ptrace_bts_clear(struct task_struct *child)
860 const struct bts_struct *in)
861{ 750{
862 unsigned char bts_record[BTS_MAX_RECORD_SIZE]; 751 const struct bts_trace *trace;
863 752
864 BUG_ON(BTS_MAX_RECORD_SIZE < bts_cfg.sizeof_bts); 753 trace = ds_read_bts(child->bts);
754 if (!trace)
755 return -EPERM;
865 756
866 memset(bts_record, 0, bts_cfg.sizeof_bts); 757 memset(trace->ds.begin, 0, trace->ds.n * trace->ds.size);
867 switch (in->qualifier) {
868 case BTS_INVALID:
869 break;
870
871 case BTS_BRANCH:
872 bts_set(bts_record, bts_from, in->variant.lbr.from_ip);
873 bts_set(bts_record, bts_to, in->variant.lbr.to_ip);
874 break;
875
876 case BTS_TASK_ARRIVES:
877 case BTS_TASK_DEPARTS:
878 bts_set(bts_record, bts_from, bts_escape);
879 bts_set(bts_record, bts_qual, in->qualifier);
880 bts_set(bts_record, bts_jiffies, in->variant.jiffies);
881 break;
882
883 default:
884 return -EINVAL;
885 }
886 758
887 /* The writing task will be the switched-to task on a context 759 return ds_reset_bts(child->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} 760}
892 761
893void ptrace_bts_take_timestamp(struct task_struct *tsk, 762static int ptrace_bts_size(struct task_struct *child)
894 enum bts_qualifier qualifier)
895{ 763{
896 struct bts_struct rec = { 764 const struct bts_trace *trace;
897 .qualifier = qualifier,
898 .variant.jiffies = jiffies_64
899 };
900
901 ptrace_bts_write_record(tsk, &rec);
902}
903 765
904static const struct bts_configuration bts_cfg_netburst = { 766 trace = ds_read_bts(child->bts);
905 .sizeof_bts = sizeof(long) * 3, 767 if (!trace)
906 .sizeof_field = sizeof(long), 768 return -EPERM;
907 .debugctl_mask = (1<<2)|(1<<3)|(1<<5)
908};
909 769
910static const struct bts_configuration bts_cfg_pentium_m = { 770 return (trace->ds.top - trace->ds.begin) / trace->ds.size;
911 .sizeof_bts = sizeof(long) * 3,
912 .sizeof_field = sizeof(long),
913 .debugctl_mask = (1<<6)|(1<<7)
914};
915
916static const struct bts_configuration bts_cfg_core2 = {
917 .sizeof_bts = 8 * 3,
918 .sizeof_field = 8,
919 .debugctl_mask = (1<<6)|(1<<7)|(1<<9)
920};
921
922static inline void bts_configure(const struct bts_configuration *cfg)
923{
924 bts_cfg = *cfg;
925}
926
927void __cpuinit ptrace_bts_init_intel(struct cpuinfo_x86 *c)
928{
929 switch (c->x86) {
930 case 0x6:
931 switch (c->x86_model) {
932 case 0 ... 0xC:
933 /* sorry, don't know about them */
934 break;
935 case 0xD:
936 case 0xE: /* Pentium M */
937 bts_configure(&bts_cfg_pentium_m);
938 break;
939 default: /* Core2, Atom, ... */
940 bts_configure(&bts_cfg_core2);
941 break;
942 }
943 break;
944 case 0xF:
945 switch (c->x86_model) {
946 case 0x0:
947 case 0x1:
948 case 0x2: /* Netburst */
949 bts_configure(&bts_cfg_netburst);
950 break;
951 default:
952 /* sorry, don't know about them */
953 break;
954 }
955 break;
956 default:
957 /* sorry, don't know about them */
958 break;
959 }
960} 771}
961#endif /* CONFIG_X86_PTRACE_BTS */ 772#endif /* CONFIG_X86_PTRACE_BTS */
962 773
@@ -972,13 +783,14 @@ void ptrace_disable(struct task_struct *child)
972 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); 783 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
973#endif 784#endif
974#ifdef CONFIG_X86_PTRACE_BTS 785#ifdef CONFIG_X86_PTRACE_BTS
975 (void)ds_release_bts(child); 786 if (child->bts) {
976 787 ds_release_bts(child->bts);
977 child->thread.debugctlmsr &= ~bts_cfg.debugctl_mask; 788 child->bts = NULL;
978 if (!child->thread.debugctlmsr)
979 clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR);
980 789
981 clear_tsk_thread_flag(child, TIF_BTS_TRACE_TS); 790 kfree(child->bts_buffer);
791 child->bts_buffer = NULL;
792 child->bts_size = 0;
793 }
982#endif /* CONFIG_X86_PTRACE_BTS */ 794#endif /* CONFIG_X86_PTRACE_BTS */
983} 795}
984 796
@@ -1111,7 +923,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
1111 break; 923 break;
1112 924
1113 case PTRACE_BTS_SIZE: 925 case PTRACE_BTS_SIZE:
1114 ret = ds_get_bts_index(child, /* pos = */ NULL); 926 ret = ptrace_bts_size(child);
1115 break; 927 break;
1116 928
1117 case PTRACE_BTS_GET: 929 case PTRACE_BTS_GET:
@@ -1120,7 +932,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
1120 break; 932 break;
1121 933
1122 case PTRACE_BTS_CLEAR: 934 case PTRACE_BTS_CLEAR:
1123 ret = ds_clear_bts(child); 935 ret = ptrace_bts_clear(child);
1124 break; 936 break;
1125 937
1126 case PTRACE_BTS_DRAIN: 938 case PTRACE_BTS_DRAIN:
@@ -1383,6 +1195,14 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
1383 1195
1384 case PTRACE_GET_THREAD_AREA: 1196 case PTRACE_GET_THREAD_AREA:
1385 case PTRACE_SET_THREAD_AREA: 1197 case PTRACE_SET_THREAD_AREA:
1198#ifdef CONFIG_X86_PTRACE_BTS
1199 case PTRACE_BTS_CONFIG:
1200 case PTRACE_BTS_STATUS:
1201 case PTRACE_BTS_SIZE:
1202 case PTRACE_BTS_GET:
1203 case PTRACE_BTS_CLEAR:
1204 case PTRACE_BTS_DRAIN:
1205#endif /* CONFIG_X86_PTRACE_BTS */
1386 return arch_ptrace(child, request, addr, data); 1206 return arch_ptrace(child, request, addr, data);
1387 1207
1388 default: 1208 default: