aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/arch
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2015-08-13 05:40:57 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-09-04 11:01:05 -0400
commit86c2786994bd7c0d4b525bbfbe42ac540d0b8166 (patch)
treed536022cb55f7d0d3d2d98e7b70ad39f84919dee /tools/perf/arch
parent1b29ac59b1d692c06ec543a5f35e0d9ebb98e003 (diff)
perf intel-pt: Add support for PERF_RECORD_SWITCH
Add support for selecting and processing PERF_RECORD_SWITCH events for use by Intel PT. If they are available, they will be used in preference to sched_switch events. This enables an unprivileged user to trace multi-threaded or multi-process workloads with any level of perf_event_paranoid. However it depends on kernel support for PERF_RECORD_SWITCH. Without this patch, tracing a multi-threaded workload will decode without error but all the data will be attributed to the main thread. Without this patch, tracing a multi-process workload will result in decoder errors because the decoder will not know which executable is executing. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: Jiri Olsa <jolsa@redhat.com> Link: http://lkml.kernel.org/r/1439458857-30636-3-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/arch')
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c55
1 files changed, 47 insertions, 8 deletions
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index 2ca10d796c0b..b02af064f0f9 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -624,13 +624,49 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
624 * threads. 624 * threads.
625 */ 625 */
626 if (have_timing_info && !cpu_map__empty(cpus)) { 626 if (have_timing_info && !cpu_map__empty(cpus)) {
627 err = intel_pt_track_switches(evlist); 627 if (perf_can_record_switch_events()) {
628 if (err == -EPERM) 628 bool cpu_wide = !target__none(&opts->target) &&
629 pr_debug2("Unable to select sched:sched_switch\n"); 629 !target__has_task(&opts->target);
630 else if (err) 630
631 return err; 631 if (!cpu_wide && perf_can_record_cpu_wide()) {
632 else 632 struct perf_evsel *switch_evsel;
633 ptr->have_sched_switch = 1; 633
634 err = parse_events(evlist, "dummy:u", NULL);
635 if (err)
636 return err;
637
638 switch_evsel = perf_evlist__last(evlist);
639
640 switch_evsel->attr.freq = 0;
641 switch_evsel->attr.sample_period = 1;
642 switch_evsel->attr.context_switch = 1;
643
644 switch_evsel->system_wide = true;
645 switch_evsel->no_aux_samples = true;
646 switch_evsel->immediate = true;
647
648 perf_evsel__set_sample_bit(switch_evsel, TID);
649 perf_evsel__set_sample_bit(switch_evsel, TIME);
650 perf_evsel__set_sample_bit(switch_evsel, CPU);
651
652 opts->record_switch_events = false;
653 ptr->have_sched_switch = 3;
654 } else {
655 opts->record_switch_events = true;
656 if (cpu_wide)
657 ptr->have_sched_switch = 3;
658 else
659 ptr->have_sched_switch = 2;
660 }
661 } else {
662 err = intel_pt_track_switches(evlist);
663 if (err == -EPERM)
664 pr_debug2("Unable to select sched:sched_switch\n");
665 else if (err)
666 return err;
667 else
668 ptr->have_sched_switch = 1;
669 }
634 } 670 }
635 671
636 if (intel_pt_evsel) { 672 if (intel_pt_evsel) {
@@ -663,8 +699,11 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
663 tracking_evsel->attr.sample_period = 1; 699 tracking_evsel->attr.sample_period = 1;
664 700
665 /* In per-cpu case, always need the time of mmap events etc */ 701 /* In per-cpu case, always need the time of mmap events etc */
666 if (!cpu_map__empty(cpus)) 702 if (!cpu_map__empty(cpus)) {
667 perf_evsel__set_sample_bit(tracking_evsel, TIME); 703 perf_evsel__set_sample_bit(tracking_evsel, TIME);
704 /* And the CPU for switch events */
705 perf_evsel__set_sample_bit(tracking_evsel, CPU);
706 }
668 } 707 }
669 708
670 /* 709 /*