]>
Commit | Line | Data |
---|---|---|
e45e7bed GKH |
1 | From 63d8e38f6ae6c36dd5b5ba0e8c112e8861532ea2 Mon Sep 17 00:00:00 2001 |
2 | From: Adrian Hunter <adrian.hunter@intel.com> | |
3 | Date: Wed, 7 Mar 2018 16:02:22 +0200 | |
4 | Subject: perf intel-pt: Fix sync_switch | |
5 | ||
6 | From: Adrian Hunter <adrian.hunter@intel.com> | |
7 | ||
8 | commit 63d8e38f6ae6c36dd5b5ba0e8c112e8861532ea2 upstream. | |
9 | ||
10 | sync_switch is a facility to synchronize decoding more closely with the | |
11 | point in the kernel when the context actually switched. | |
12 | ||
13 | The flag when sync_switch is enabled was global to the decoding, whereas | |
14 | it is really specific to the CPU. | |
15 | ||
16 | The trace data for different CPUs is put on different queues, so add | |
17 | sync_switch to the intel_pt_queue structure and use that in preference | |
18 | to the global setting in the intel_pt structure. | |
19 | ||
20 | That fixes problems decoding one CPU's trace because sync_switch was | |
21 | disabled on a different CPU's queue. | |
22 | ||
23 | Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> | |
24 | Cc: Jiri Olsa <jolsa@redhat.com> | |
25 | Cc: stable@vger.kernel.org | |
26 | Link: http://lkml.kernel.org/r/1520431349-30689-3-git-send-email-adrian.hunter@intel.com | |
27 | Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> | |
28 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
29 | ||
30 | --- | |
31 | tools/perf/util/intel-pt.c | 32 +++++++++++++++++++++++++------- | |
32 | 1 file changed, 25 insertions(+), 7 deletions(-) | |
33 | ||
34 | --- a/tools/perf/util/intel-pt.c | |
35 | +++ b/tools/perf/util/intel-pt.c | |
36 | @@ -125,6 +125,7 @@ struct intel_pt_queue { | |
37 | bool stop; | |
38 | bool step_through_buffers; | |
39 | bool use_buffer_pid_tid; | |
40 | + bool sync_switch; | |
41 | pid_t pid, tid; | |
42 | int cpu; | |
43 | int switch_state; | |
44 | @@ -852,10 +853,12 @@ static int intel_pt_setup_queue(struct i | |
45 | if (pt->timeless_decoding || !pt->have_sched_switch) | |
46 | ptq->use_buffer_pid_tid = true; | |
47 | } | |
48 | + | |
49 | + ptq->sync_switch = pt->sync_switch; | |
50 | } | |
51 | ||
52 | if (!ptq->on_heap && | |
53 | - (!pt->sync_switch || | |
54 | + (!ptq->sync_switch || | |
55 | ptq->switch_state != INTEL_PT_SS_EXPECTING_SWITCH_EVENT)) { | |
56 | const struct intel_pt_state *state; | |
57 | int ret; | |
58 | @@ -1238,7 +1241,7 @@ static int intel_pt_sample(struct intel_ | |
59 | if (pt->synth_opts.last_branch) | |
60 | intel_pt_update_last_branch_rb(ptq); | |
61 | ||
62 | - if (!pt->sync_switch) | |
63 | + if (!ptq->sync_switch) | |
64 | return 0; | |
65 | ||
66 | if (intel_pt_is_switch_ip(ptq, state->to_ip)) { | |
67 | @@ -1319,6 +1322,21 @@ static u64 intel_pt_switch_ip(struct int | |
68 | return switch_ip; | |
69 | } | |
70 | ||
71 | +static void intel_pt_enable_sync_switch(struct intel_pt *pt) | |
72 | +{ | |
73 | + unsigned int i; | |
74 | + | |
75 | + pt->sync_switch = true; | |
76 | + | |
77 | + for (i = 0; i < pt->queues.nr_queues; i++) { | |
78 | + struct auxtrace_queue *queue = &pt->queues.queue_array[i]; | |
79 | + struct intel_pt_queue *ptq = queue->priv; | |
80 | + | |
81 | + if (ptq) | |
82 | + ptq->sync_switch = true; | |
83 | + } | |
84 | +} | |
85 | + | |
86 | static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp) | |
87 | { | |
88 | const struct intel_pt_state *state = ptq->state; | |
89 | @@ -1335,7 +1353,7 @@ static int intel_pt_run_decoder(struct i | |
90 | if (pt->switch_ip) { | |
91 | intel_pt_log("switch_ip: %"PRIx64" ptss_ip: %"PRIx64"\n", | |
92 | pt->switch_ip, pt->ptss_ip); | |
93 | - pt->sync_switch = true; | |
94 | + intel_pt_enable_sync_switch(pt); | |
95 | } | |
96 | } | |
97 | } | |
98 | @@ -1351,9 +1369,9 @@ static int intel_pt_run_decoder(struct i | |
99 | if (state->err) { | |
100 | if (state->err == INTEL_PT_ERR_NODATA) | |
101 | return 1; | |
102 | - if (pt->sync_switch && | |
103 | + if (ptq->sync_switch && | |
104 | state->from_ip >= pt->kernel_start) { | |
105 | - pt->sync_switch = false; | |
106 | + ptq->sync_switch = false; | |
107 | intel_pt_next_tid(pt, ptq); | |
108 | } | |
109 | if (pt->synth_opts.errors) { | |
110 | @@ -1379,7 +1397,7 @@ static int intel_pt_run_decoder(struct i | |
111 | state->timestamp, state->est_timestamp); | |
112 | ptq->timestamp = state->est_timestamp; | |
113 | /* Use estimated TSC in unknown switch state */ | |
114 | - } else if (pt->sync_switch && | |
115 | + } else if (ptq->sync_switch && | |
116 | ptq->switch_state == INTEL_PT_SS_UNKNOWN && | |
117 | intel_pt_is_switch_ip(ptq, state->to_ip) && | |
118 | ptq->next_tid == -1) { | |
119 | @@ -1526,7 +1544,7 @@ static int intel_pt_sync_switch(struct i | |
120 | return 1; | |
121 | ||
122 | ptq = intel_pt_cpu_to_ptq(pt, cpu); | |
123 | - if (!ptq) | |
124 | + if (!ptq || !ptq->sync_switch) | |
125 | return 1; | |
126 | ||
127 | switch (ptq->switch_state) { |