diff options
27 files changed, 1481 insertions, 97 deletions
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index f97479f1ce35..d2f6d0be3503 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c | |||
@@ -601,7 +601,22 @@ static int probes_seq_show(struct seq_file *m, void *v) | |||
601 | 601 | ||
602 | seq_printf(m, "%c:%s/%s", c, tu->tp.call.class->system, | 602 | seq_printf(m, "%c:%s/%s", c, tu->tp.call.class->system, |
603 | trace_event_name(&tu->tp.call)); | 603 | trace_event_name(&tu->tp.call)); |
604 | seq_printf(m, " %s:0x%p", tu->filename, (void *)tu->offset); | 604 | seq_printf(m, " %s:", tu->filename); |
605 | |||
606 | /* Don't print "0x (null)" when offset is 0 */ | ||
607 | if (tu->offset) { | ||
608 | seq_printf(m, "0x%p", (void *)tu->offset); | ||
609 | } else { | ||
610 | switch (sizeof(void *)) { | ||
611 | case 4: | ||
612 | seq_printf(m, "0x00000000"); | ||
613 | break; | ||
614 | case 8: | ||
615 | default: | ||
616 | seq_printf(m, "0x0000000000000000"); | ||
617 | break; | ||
618 | } | ||
619 | } | ||
605 | 620 | ||
606 | for (i = 0; i < tu->tp.nr_args; i++) | 621 | for (i = 0; i < tu->tp.nr_args; i++) |
607 | seq_printf(m, " %s=%s", tu->tp.args[i].name, tu->tp.args[i].comm); | 622 | seq_printf(m, " %s=%s", tu->tp.args[i].name, tu->tp.args[i].comm); |
diff --git a/tools/build/Documentation/Build.txt b/tools/build/Documentation/Build.txt index 00ad2d608727..aa5e092c4352 100644 --- a/tools/build/Documentation/Build.txt +++ b/tools/build/Documentation/Build.txt | |||
@@ -66,6 +66,7 @@ To follow the above example, the user provides following 'Build' files: | |||
66 | ex/Build: | 66 | ex/Build: |
67 | ex-y += a.o | 67 | ex-y += a.o |
68 | ex-y += b.o | 68 | ex-y += b.o |
69 | ex-y += b.o # duplicates in the lists are allowed | ||
69 | 70 | ||
70 | libex-y += c.o | 71 | libex-y += c.o |
71 | libex-y += d.o | 72 | libex-y += d.o |
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build index 8120af9c0341..0c5f485521d6 100644 --- a/tools/build/Makefile.build +++ b/tools/build/Makefile.build | |||
@@ -63,7 +63,7 @@ quiet_cmd_gen = GEN $@ | |||
63 | # If there's nothing to link, create empty $@ object. | 63 | # If there's nothing to link, create empty $@ object. |
64 | quiet_cmd_ld_multi = LD $@ | 64 | quiet_cmd_ld_multi = LD $@ |
65 | cmd_ld_multi = $(if $(strip $(obj-y)),\ | 65 | cmd_ld_multi = $(if $(strip $(obj-y)),\ |
66 | $(LD) -r -o $@ $(obj-y),rm -f $@; $(AR) rcs $@) | 66 | $(LD) -r -o $@ $(filter $(obj-y),$^),rm -f $@; $(AR) rcs $@) |
67 | 67 | ||
68 | # Build rules | 68 | # Build rules |
69 | $(OUTPUT)%.o: %.c FORCE | 69 | $(OUTPUT)%.o: %.c FORCE |
diff --git a/tools/build/tests/ex/Build b/tools/build/tests/ex/Build index 70d876237c57..429c7d452101 100644 --- a/tools/build/tests/ex/Build +++ b/tools/build/tests/ex/Build | |||
@@ -1,6 +1,7 @@ | |||
1 | ex-y += ex.o | 1 | ex-y += ex.o |
2 | ex-y += a.o | 2 | ex-y += a.o |
3 | ex-y += b.o | 3 | ex-y += b.o |
4 | ex-y += b.o | ||
4 | ex-y += empty/ | 5 | ex-y += empty/ |
5 | ex-y += empty2/ | 6 | ex-y += empty2/ |
6 | 7 | ||
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt index 2866b62eb293..4a0501d7a3b4 100644 --- a/tools/perf/Documentation/intel-pt.txt +++ b/tools/perf/Documentation/intel-pt.txt | |||
@@ -142,19 +142,21 @@ which is the same as | |||
142 | 142 | ||
143 | -e intel_pt/tsc=1,noretcomp=0/ | 143 | -e intel_pt/tsc=1,noretcomp=0/ |
144 | 144 | ||
145 | Note there are now new config terms - see section 'config terms' further below. | ||
146 | |||
145 | The config terms are listed in /sys/devices/intel_pt/format. They are bit | 147 | The config terms are listed in /sys/devices/intel_pt/format. They are bit |
146 | fields within the config member of the struct perf_event_attr which is | 148 | fields within the config member of the struct perf_event_attr which is |
147 | passed to the kernel by the perf_event_open system call. They correspond to bit | 149 | passed to the kernel by the perf_event_open system call. They correspond to bit |
148 | fields in the IA32_RTIT_CTL MSR. Here is a list of them and their definitions: | 150 | fields in the IA32_RTIT_CTL MSR. Here is a list of them and their definitions: |
149 | 151 | ||
150 | $ for f in `ls /sys/devices/intel_pt/format`;do | 152 | $ grep -H . /sys/bus/event_source/devices/intel_pt/format/* |
151 | > echo $f | 153 | /sys/bus/event_source/devices/intel_pt/format/cyc:config:1 |
152 | > cat /sys/devices/intel_pt/format/$f | 154 | /sys/bus/event_source/devices/intel_pt/format/cyc_thresh:config:19-22 |
153 | > done | 155 | /sys/bus/event_source/devices/intel_pt/format/mtc:config:9 |
154 | noretcomp | 156 | /sys/bus/event_source/devices/intel_pt/format/mtc_period:config:14-17 |
155 | config:11 | 157 | /sys/bus/event_source/devices/intel_pt/format/noretcomp:config:11 |
156 | tsc | 158 | /sys/bus/event_source/devices/intel_pt/format/psb_period:config:24-27 |
157 | config:10 | 159 | /sys/bus/event_source/devices/intel_pt/format/tsc:config:10 |
158 | 160 | ||
159 | Note that the default config must be overridden for each term i.e. | 161 | Note that the default config must be overridden for each term i.e. |
160 | 162 | ||
@@ -209,9 +211,185 @@ perf_event_attr is displayed if the -vv option is used e.g. | |||
209 | ------------------------------------------------------------ | 211 | ------------------------------------------------------------ |
210 | 212 | ||
211 | 213 | ||
214 | config terms | ||
215 | ------------ | ||
216 | |||
217 | The June 2015 version of Intel 64 and IA-32 Architectures Software Developer | ||
218 | Manuals, Chapter 36 Intel Processor Trace, defined new Intel PT features. | ||
219 | Some of the features are reflect in new config terms. All the config terms are | ||
220 | described below. | ||
221 | |||
222 | tsc Always supported. Produces TSC timestamp packets to provide | ||
223 | timing information. In some cases it is possible to decode | ||
224 | without timing information, for example a per-thread context | ||
225 | that does not overlap executable memory maps. | ||
226 | |||
227 | The default config selects tsc (i.e. tsc=1). | ||
228 | |||
229 | noretcomp Always supported. Disables "return compression" so a TIP packet | ||
230 | is produced when a function returns. Causes more packets to be | ||
231 | produced but might make decoding more reliable. | ||
232 | |||
233 | The default config does not select noretcomp (i.e. noretcomp=0). | ||
234 | |||
235 | psb_period Allows the frequency of PSB packets to be specified. | ||
236 | |||
237 | The PSB packet is a synchronization packet that provides a | ||
238 | starting point for decoding or recovery from errors. | ||
239 | |||
240 | Support for psb_period is indicated by: | ||
241 | |||
242 | /sys/bus/event_source/devices/intel_pt/caps/psb_cyc | ||
243 | |||
244 | which contains "1" if the feature is supported and "0" | ||
245 | otherwise. | ||
246 | |||
247 | Valid values are given by: | ||
248 | |||
249 | /sys/bus/event_source/devices/intel_pt/caps/psb_periods | ||
250 | |||
251 | which contains a hexadecimal value, the bits of which represent | ||
252 | valid values e.g. bit 2 set means value 2 is valid. | ||
253 | |||
254 | The psb_period value is converted to the approximate number of | ||
255 | trace bytes between PSB packets as: | ||
256 | |||
257 | 2 ^ (value + 11) | ||
258 | |||
259 | e.g. value 3 means 16KiB bytes between PSBs | ||
260 | |||
261 | If an invalid value is entered, the error message | ||
262 | will give a list of valid values e.g. | ||
263 | |||
264 | $ perf record -e intel_pt/psb_period=15/u uname | ||
265 | Invalid psb_period for intel_pt. Valid values are: 0-5 | ||
266 | |||
267 | If MTC packets are selected, the default config selects a value | ||
268 | of 3 (i.e. psb_period=3) or the nearest lower value that is | ||
269 | supported (0 is always supported). Otherwise the default is 0. | ||
270 | |||
271 | If decoding is expected to be reliable and the buffer is large | ||
272 | then a large PSB period can be used. | ||
273 | |||
274 | Because a TSC packet is produced with PSB, the PSB period can | ||
275 | also affect the granularity to timing information in the absence | ||
276 | of MTC or CYC. | ||
277 | |||
278 | mtc Produces MTC timing packets. | ||
279 | |||
280 | MTC packets provide finer grain timestamp information than TSC | ||
281 | packets. MTC packets record time using the hardware crystal | ||
282 | clock (CTC) which is related to TSC packets using a TMA packet. | ||
283 | |||
284 | Support for this feature is indicated by: | ||
285 | |||
286 | /sys/bus/event_source/devices/intel_pt/caps/mtc | ||
287 | |||
288 | which contains "1" if the feature is supported and | ||
289 | "0" otherwise. | ||
290 | |||
291 | The frequency of MTC packets can also be specified - see | ||
292 | mtc_period below. | ||
293 | |||
294 | mtc_period Specifies how frequently MTC packets are produced - see mtc | ||
295 | above for how to determine if MTC packets are supported. | ||
296 | |||
297 | Valid values are given by: | ||
298 | |||
299 | /sys/bus/event_source/devices/intel_pt/caps/mtc_periods | ||
300 | |||
301 | which contains a hexadecimal value, the bits of which represent | ||
302 | valid values e.g. bit 2 set means value 2 is valid. | ||
303 | |||
304 | The mtc_period value is converted to the MTC frequency as: | ||
305 | |||
306 | CTC-frequency / (2 ^ value) | ||
307 | |||
308 | e.g. value 3 means one eighth of CTC-frequency | ||
309 | |||
310 | Where CTC is the hardware crystal clock, the frequency of which | ||
311 | can be related to TSC via values provided in cpuid leaf 0x15. | ||
312 | |||
313 | If an invalid value is entered, the error message | ||
314 | will give a list of valid values e.g. | ||
315 | |||
316 | $ perf record -e intel_pt/mtc_period=15/u uname | ||
317 | Invalid mtc_period for intel_pt. Valid values are: 0,3,6,9 | ||
318 | |||
319 | The default value is 3 or the nearest lower value | ||
320 | that is supported (0 is always supported). | ||
321 | |||
322 | cyc Produces CYC timing packets. | ||
323 | |||
324 | CYC packets provide even finer grain timestamp information than | ||
325 | MTC and TSC packets. A CYC packet contains the number of CPU | ||
326 | cycles since the last CYC packet. Unlike MTC and TSC packets, | ||
327 | CYC packets are only sent when another packet is also sent. | ||
328 | |||
329 | Support for this feature is indicated by: | ||
330 | |||
331 | /sys/bus/event_source/devices/intel_pt/caps/psb_cyc | ||
332 | |||
333 | which contains "1" if the feature is supported and | ||
334 | "0" otherwise. | ||
335 | |||
336 | The number of CYC packets produced can be reduced by specifying | ||
337 | a threshold - see cyc_thresh below. | ||
338 | |||
339 | cyc_thresh Specifies how frequently CYC packets are produced - see cyc | ||
340 | above for how to determine if CYC packets are supported. | ||
341 | |||
342 | Valid cyc_thresh values are given by: | ||
343 | |||
344 | /sys/bus/event_source/devices/intel_pt/caps/cycle_thresholds | ||
345 | |||
346 | which contains a hexadecimal value, the bits of which represent | ||
347 | valid values e.g. bit 2 set means value 2 is valid. | ||
348 | |||
349 | The cyc_thresh value represents the minimum number of CPU cycles | ||
350 | that must have passed before a CYC packet can be sent. The | ||
351 | number of CPU cycles is: | ||
352 | |||
353 | 2 ^ (value - 1) | ||
354 | |||
355 | e.g. value 4 means 8 CPU cycles must pass before a CYC packet | ||
356 | can be sent. Note a CYC packet is still only sent when another | ||
357 | packet is sent, not at, e.g. every 8 CPU cycles. | ||
358 | |||
359 | If an invalid value is entered, the error message | ||
360 | will give a list of valid values e.g. | ||
361 | |||
362 | $ perf record -e intel_pt/cyc,cyc_thresh=15/u uname | ||
363 | Invalid cyc_thresh for intel_pt. Valid values are: 0-12 | ||
364 | |||
365 | CYC packets are not requested by default. | ||
366 | |||
367 | no_force_psb This is a driver option and is not in the IA32_RTIT_CTL MSR. | ||
368 | |||
369 | It stops the driver resetting the byte count to zero whenever | ||
370 | enabling the trace (for example on context switches) which in | ||
371 | turn results in no PSB being forced. However some processors | ||
372 | will produce a PSB anyway. | ||
373 | |||
374 | In any case, there is still a PSB when the trace is enabled for | ||
375 | the first time. | ||
376 | |||
377 | no_force_psb can be used to slightly decrease the trace size but | ||
378 | may make it harder for the decoder to recover from errors. | ||
379 | |||
380 | no_force_psb is not selected by default. | ||
381 | |||
382 | |||
212 | new snapshot option | 383 | new snapshot option |
213 | ------------------- | 384 | ------------------- |
214 | 385 | ||
386 | The difference between full trace and snapshot from the kernel's perspective is | ||
387 | that in full trace we don't overwrite trace data that the user hasn't collected | ||
388 | yet (and indicated that by advancing aux_tail), whereas in snapshot mode we let | ||
389 | the trace run and overwrite older data in the buffer so that whenever something | ||
390 | interesting happens, we can stop it and grab a snapshot of what was going on | ||
391 | around that interesting moment. | ||
392 | |||
215 | To select snapshot mode a new option has been added: | 393 | To select snapshot mode a new option has been added: |
216 | 394 | ||
217 | -S | 395 | -S |
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index f31f15a5f873..af009bd6e6b7 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST | |||
@@ -41,7 +41,6 @@ tools/include/asm-generic/bitops.h | |||
41 | tools/include/linux/atomic.h | 41 | tools/include/linux/atomic.h |
42 | tools/include/linux/bitops.h | 42 | tools/include/linux/bitops.h |
43 | tools/include/linux/compiler.h | 43 | tools/include/linux/compiler.h |
44 | tools/include/linux/export.h | ||
45 | tools/include/linux/hash.h | 44 | tools/include/linux/hash.h |
46 | tools/include/linux/kernel.h | 45 | tools/include/linux/kernel.h |
47 | tools/include/linux/list.h | 46 | tools/include/linux/list.h |
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index da7d2c15e611..2ca10d796c0b 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/bitops.h> | 19 | #include <linux/bitops.h> |
20 | #include <linux/log2.h> | 20 | #include <linux/log2.h> |
21 | #include <cpuid.h> | ||
21 | 22 | ||
22 | #include "../../perf.h" | 23 | #include "../../perf.h" |
23 | #include "../../util/session.h" | 24 | #include "../../util/session.h" |
@@ -99,17 +100,137 @@ static int intel_pt_parse_terms(struct list_head *formats, const char *str, | |||
99 | return intel_pt_parse_terms_with_default(formats, str, config); | 100 | return intel_pt_parse_terms_with_default(formats, str, config); |
100 | } | 101 | } |
101 | 102 | ||
102 | static size_t intel_pt_psb_period(struct perf_pmu *intel_pt_pmu __maybe_unused, | 103 | static u64 intel_pt_masked_bits(u64 mask, u64 bits) |
103 | struct perf_evlist *evlist __maybe_unused) | ||
104 | { | 104 | { |
105 | return 256; | 105 | const u64 top_bit = 1ULL << 63; |
106 | u64 res = 0; | ||
107 | int i; | ||
108 | |||
109 | for (i = 0; i < 64; i++) { | ||
110 | if (mask & top_bit) { | ||
111 | res <<= 1; | ||
112 | if (bits & top_bit) | ||
113 | res |= 1; | ||
114 | } | ||
115 | mask <<= 1; | ||
116 | bits <<= 1; | ||
117 | } | ||
118 | |||
119 | return res; | ||
120 | } | ||
121 | |||
122 | static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str, | ||
123 | struct perf_evlist *evlist, u64 *res) | ||
124 | { | ||
125 | struct perf_evsel *evsel; | ||
126 | u64 mask; | ||
127 | |||
128 | *res = 0; | ||
129 | |||
130 | mask = perf_pmu__format_bits(&intel_pt_pmu->format, str); | ||
131 | if (!mask) | ||
132 | return -EINVAL; | ||
133 | |||
134 | evlist__for_each(evlist, evsel) { | ||
135 | if (evsel->attr.type == intel_pt_pmu->type) { | ||
136 | *res = intel_pt_masked_bits(mask, evsel->attr.config); | ||
137 | return 0; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | return -EINVAL; | ||
142 | } | ||
143 | |||
144 | static size_t intel_pt_psb_period(struct perf_pmu *intel_pt_pmu, | ||
145 | struct perf_evlist *evlist) | ||
146 | { | ||
147 | u64 val; | ||
148 | int err, topa_multiple_entries; | ||
149 | size_t psb_period; | ||
150 | |||
151 | if (perf_pmu__scan_file(intel_pt_pmu, "caps/topa_multiple_entries", | ||
152 | "%d", &topa_multiple_entries) != 1) | ||
153 | topa_multiple_entries = 0; | ||
154 | |||
155 | /* | ||
156 | * Use caps/topa_multiple_entries to indicate early hardware that had | ||
157 | * extra frequent PSBs. | ||
158 | */ | ||
159 | if (!topa_multiple_entries) { | ||
160 | psb_period = 256; | ||
161 | goto out; | ||
162 | } | ||
163 | |||
164 | err = intel_pt_read_config(intel_pt_pmu, "psb_period", evlist, &val); | ||
165 | if (err) | ||
166 | val = 0; | ||
167 | |||
168 | psb_period = 1 << (val + 11); | ||
169 | out: | ||
170 | pr_debug2("%s psb_period %zu\n", intel_pt_pmu->name, psb_period); | ||
171 | return psb_period; | ||
172 | } | ||
173 | |||
174 | static int intel_pt_pick_bit(int bits, int target) | ||
175 | { | ||
176 | int pos, pick = -1; | ||
177 | |||
178 | for (pos = 0; bits; bits >>= 1, pos++) { | ||
179 | if (bits & 1) { | ||
180 | if (pos <= target || pick < 0) | ||
181 | pick = pos; | ||
182 | if (pos >= target) | ||
183 | break; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | return pick; | ||
106 | } | 188 | } |
107 | 189 | ||
108 | static u64 intel_pt_default_config(struct perf_pmu *intel_pt_pmu) | 190 | static u64 intel_pt_default_config(struct perf_pmu *intel_pt_pmu) |
109 | { | 191 | { |
192 | char buf[256]; | ||
193 | int mtc, mtc_periods = 0, mtc_period; | ||
194 | int psb_cyc, psb_periods, psb_period; | ||
195 | int pos = 0; | ||
110 | u64 config; | 196 | u64 config; |
111 | 197 | ||
112 | intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &config); | 198 | pos += scnprintf(buf + pos, sizeof(buf) - pos, "tsc"); |
199 | |||
200 | if (perf_pmu__scan_file(intel_pt_pmu, "caps/mtc", "%d", | ||
201 | &mtc) != 1) | ||
202 | mtc = 1; | ||
203 | |||
204 | if (mtc) { | ||
205 | if (perf_pmu__scan_file(intel_pt_pmu, "caps/mtc_periods", "%x", | ||
206 | &mtc_periods) != 1) | ||
207 | mtc_periods = 0; | ||
208 | if (mtc_periods) { | ||
209 | mtc_period = intel_pt_pick_bit(mtc_periods, 3); | ||
210 | pos += scnprintf(buf + pos, sizeof(buf) - pos, | ||
211 | ",mtc,mtc_period=%d", mtc_period); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | if (perf_pmu__scan_file(intel_pt_pmu, "caps/psb_cyc", "%d", | ||
216 | &psb_cyc) != 1) | ||
217 | psb_cyc = 1; | ||
218 | |||
219 | if (psb_cyc && mtc_periods) { | ||
220 | if (perf_pmu__scan_file(intel_pt_pmu, "caps/psb_periods", "%x", | ||
221 | &psb_periods) != 1) | ||
222 | psb_periods = 0; | ||
223 | if (psb_periods) { | ||
224 | psb_period = intel_pt_pick_bit(psb_periods, 3); | ||
225 | pos += scnprintf(buf + pos, sizeof(buf) - pos, | ||
226 | ",psb_period=%d", psb_period); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | pr_debug2("%s default config: %s\n", intel_pt_pmu->name, buf); | ||
231 | |||
232 | intel_pt_parse_terms(&intel_pt_pmu->format, buf, &config); | ||
233 | |||
113 | return config; | 234 | return config; |
114 | } | 235 | } |
115 | 236 | ||
@@ -157,6 +278,15 @@ static size_t intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused | |||
157 | return INTEL_PT_AUXTRACE_PRIV_SIZE; | 278 | return INTEL_PT_AUXTRACE_PRIV_SIZE; |
158 | } | 279 | } |
159 | 280 | ||
281 | static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d) | ||
282 | { | ||
283 | unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0; | ||
284 | |||
285 | __get_cpuid(0x15, &eax, &ebx, &ecx, &edx); | ||
286 | *n = ebx; | ||
287 | *d = eax; | ||
288 | } | ||
289 | |||
160 | static int intel_pt_info_fill(struct auxtrace_record *itr, | 290 | static int intel_pt_info_fill(struct auxtrace_record *itr, |
161 | struct perf_session *session, | 291 | struct perf_session *session, |
162 | struct auxtrace_info_event *auxtrace_info, | 292 | struct auxtrace_info_event *auxtrace_info, |
@@ -168,7 +298,8 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, | |||
168 | struct perf_event_mmap_page *pc; | 298 | struct perf_event_mmap_page *pc; |
169 | struct perf_tsc_conversion tc = { .time_mult = 0, }; | 299 | struct perf_tsc_conversion tc = { .time_mult = 0, }; |
170 | bool cap_user_time_zero = false, per_cpu_mmaps; | 300 | bool cap_user_time_zero = false, per_cpu_mmaps; |
171 | u64 tsc_bit, noretcomp_bit; | 301 | u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit; |
302 | u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d; | ||
172 | int err; | 303 | int err; |
173 | 304 | ||
174 | if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE) | 305 | if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE) |
@@ -177,6 +308,12 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, | |||
177 | intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit); | 308 | intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit); |
178 | intel_pt_parse_terms(&intel_pt_pmu->format, "noretcomp", | 309 | intel_pt_parse_terms(&intel_pt_pmu->format, "noretcomp", |
179 | &noretcomp_bit); | 310 | &noretcomp_bit); |
311 | intel_pt_parse_terms(&intel_pt_pmu->format, "mtc", &mtc_bit); | ||
312 | mtc_freq_bits = perf_pmu__format_bits(&intel_pt_pmu->format, | ||
313 | "mtc_period"); | ||
314 | intel_pt_parse_terms(&intel_pt_pmu->format, "cyc", &cyc_bit); | ||
315 | |||
316 | intel_pt_tsc_ctc_ratio(&tsc_ctc_ratio_n, &tsc_ctc_ratio_d); | ||
180 | 317 | ||
181 | if (!session->evlist->nr_mmaps) | 318 | if (!session->evlist->nr_mmaps) |
182 | return -EINVAL; | 319 | return -EINVAL; |
@@ -207,6 +344,11 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, | |||
207 | auxtrace_info->priv[INTEL_PT_HAVE_SCHED_SWITCH] = ptr->have_sched_switch; | 344 | auxtrace_info->priv[INTEL_PT_HAVE_SCHED_SWITCH] = ptr->have_sched_switch; |
208 | auxtrace_info->priv[INTEL_PT_SNAPSHOT_MODE] = ptr->snapshot_mode; | 345 | auxtrace_info->priv[INTEL_PT_SNAPSHOT_MODE] = ptr->snapshot_mode; |
209 | auxtrace_info->priv[INTEL_PT_PER_CPU_MMAPS] = per_cpu_mmaps; | 346 | auxtrace_info->priv[INTEL_PT_PER_CPU_MMAPS] = per_cpu_mmaps; |
347 | auxtrace_info->priv[INTEL_PT_MTC_BIT] = mtc_bit; | ||
348 | auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS] = mtc_freq_bits; | ||
349 | auxtrace_info->priv[INTEL_PT_TSC_CTC_N] = tsc_ctc_ratio_n; | ||
350 | auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d; | ||
351 | auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit; | ||
210 | 352 | ||
211 | return 0; | 353 | return 0; |
212 | } | 354 | } |
@@ -239,6 +381,117 @@ static int intel_pt_track_switches(struct perf_evlist *evlist) | |||
239 | return 0; | 381 | return 0; |
240 | } | 382 | } |
241 | 383 | ||
384 | static void intel_pt_valid_str(char *str, size_t len, u64 valid) | ||
385 | { | ||
386 | unsigned int val, last = 0, state = 1; | ||
387 | int p = 0; | ||
388 | |||
389 | str[0] = '\0'; | ||
390 | |||
391 | for (val = 0; val <= 64; val++, valid >>= 1) { | ||
392 | if (valid & 1) { | ||
393 | last = val; | ||
394 | switch (state) { | ||
395 | case 0: | ||
396 | p += scnprintf(str + p, len - p, ","); | ||
397 | /* Fall through */ | ||
398 | case 1: | ||
399 | p += scnprintf(str + p, len - p, "%u", val); | ||
400 | state = 2; | ||
401 | break; | ||
402 | case 2: | ||
403 | state = 3; | ||
404 | break; | ||
405 | case 3: | ||
406 | state = 4; | ||
407 | break; | ||
408 | default: | ||
409 | break; | ||
410 | } | ||
411 | } else { | ||
412 | switch (state) { | ||
413 | case 3: | ||
414 | p += scnprintf(str + p, len - p, ",%u", last); | ||
415 | state = 0; | ||
416 | break; | ||
417 | case 4: | ||
418 | p += scnprintf(str + p, len - p, "-%u", last); | ||
419 | state = 0; | ||
420 | break; | ||
421 | default: | ||
422 | break; | ||
423 | } | ||
424 | if (state != 1) | ||
425 | state = 0; | ||
426 | } | ||
427 | } | ||
428 | } | ||
429 | |||
430 | static int intel_pt_val_config_term(struct perf_pmu *intel_pt_pmu, | ||
431 | const char *caps, const char *name, | ||
432 | const char *supported, u64 config) | ||
433 | { | ||
434 | char valid_str[256]; | ||
435 | unsigned int shift; | ||
436 | unsigned long long valid; | ||
437 | u64 bits; | ||
438 | int ok; | ||
439 | |||
440 | if (perf_pmu__scan_file(intel_pt_pmu, caps, "%llx", &valid) != 1) | ||
441 | valid = 0; | ||
442 | |||
443 | if (supported && | ||
444 | perf_pmu__scan_file(intel_pt_pmu, supported, "%d", &ok) == 1 && !ok) | ||
445 | valid = 0; | ||
446 | |||
447 | valid |= 1; | ||
448 | |||
449 | bits = perf_pmu__format_bits(&intel_pt_pmu->format, name); | ||
450 | |||
451 | config &= bits; | ||
452 | |||
453 | for (shift = 0; bits && !(bits & 1); shift++) | ||
454 | bits >>= 1; | ||
455 | |||
456 | config >>= shift; | ||
457 | |||
458 | if (config > 63) | ||
459 | goto out_err; | ||
460 | |||
461 | if (valid & (1 << config)) | ||
462 | return 0; | ||
463 | out_err: | ||
464 | intel_pt_valid_str(valid_str, sizeof(valid_str), valid); | ||
465 | pr_err("Invalid %s for %s. Valid values are: %s\n", | ||
466 | name, INTEL_PT_PMU_NAME, valid_str); | ||
467 | return -EINVAL; | ||
468 | } | ||
469 | |||
470 | static int intel_pt_validate_config(struct perf_pmu *intel_pt_pmu, | ||
471 | struct perf_evsel *evsel) | ||
472 | { | ||
473 | int err; | ||
474 | |||
475 | if (!evsel) | ||
476 | return 0; | ||
477 | |||
478 | err = intel_pt_val_config_term(intel_pt_pmu, "caps/cycle_thresholds", | ||
479 | "cyc_thresh", "caps/psb_cyc", | ||
480 | evsel->attr.config); | ||
481 | if (err) | ||
482 | return err; | ||
483 | |||
484 | err = intel_pt_val_config_term(intel_pt_pmu, "caps/mtc_periods", | ||
485 | "mtc_period", "caps/mtc", | ||
486 | evsel->attr.config); | ||
487 | if (err) | ||
488 | return err; | ||
489 | |||
490 | return intel_pt_val_config_term(intel_pt_pmu, "caps/psb_periods", | ||
491 | "psb_period", "caps/psb_cyc", | ||
492 | evsel->attr.config); | ||
493 | } | ||
494 | |||
242 | static int intel_pt_recording_options(struct auxtrace_record *itr, | 495 | static int intel_pt_recording_options(struct auxtrace_record *itr, |
243 | struct perf_evlist *evlist, | 496 | struct perf_evlist *evlist, |
244 | struct record_opts *opts) | 497 | struct record_opts *opts) |
@@ -251,6 +504,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, | |||
251 | const struct cpu_map *cpus = evlist->cpus; | 504 | const struct cpu_map *cpus = evlist->cpus; |
252 | bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; | 505 | bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; |
253 | u64 tsc_bit; | 506 | u64 tsc_bit; |
507 | int err; | ||
254 | 508 | ||
255 | ptr->evlist = evlist; | 509 | ptr->evlist = evlist; |
256 | ptr->snapshot_mode = opts->auxtrace_snapshot_mode; | 510 | ptr->snapshot_mode = opts->auxtrace_snapshot_mode; |
@@ -281,6 +535,10 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, | |||
281 | if (!opts->full_auxtrace) | 535 | if (!opts->full_auxtrace) |
282 | return 0; | 536 | return 0; |
283 | 537 | ||
538 | err = intel_pt_validate_config(intel_pt_pmu, intel_pt_evsel); | ||
539 | if (err) | ||
540 | return err; | ||
541 | |||
284 | /* Set default sizes for snapshot mode */ | 542 | /* Set default sizes for snapshot mode */ |
285 | if (opts->auxtrace_snapshot_mode) { | 543 | if (opts->auxtrace_snapshot_mode) { |
286 | size_t psb_period = intel_pt_psb_period(intel_pt_pmu, evlist); | 544 | size_t psb_period = intel_pt_psb_period(intel_pt_pmu, evlist); |
@@ -366,8 +624,6 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, | |||
366 | * threads. | 624 | * threads. |
367 | */ | 625 | */ |
368 | if (have_timing_info && !cpu_map__empty(cpus)) { | 626 | if (have_timing_info && !cpu_map__empty(cpus)) { |
369 | int err; | ||
370 | |||
371 | err = intel_pt_track_switches(evlist); | 627 | err = intel_pt_track_switches(evlist); |
372 | if (err == -EPERM) | 628 | if (err == -EPERM) |
373 | pr_debug2("Unable to select sched:sched_switch\n"); | 629 | pr_debug2("Unable to select sched:sched_switch\n"); |
@@ -394,7 +650,6 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, | |||
394 | /* Add dummy event to keep tracking */ | 650 | /* Add dummy event to keep tracking */ |
395 | if (opts->full_auxtrace) { | 651 | if (opts->full_auxtrace) { |
396 | struct perf_evsel *tracking_evsel; | 652 | struct perf_evsel *tracking_evsel; |
397 | int err; | ||
398 | 653 | ||
399 | err = parse_events(evlist, "dummy:u", NULL); | 654 | err = parse_events(evlist, "dummy:u", NULL); |
400 | if (err) | 655 | if (err) |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index a32a64ef08e2..8edc205ff9a7 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -67,6 +67,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, | |||
67 | rb_erase(&al->sym->rb_node, | 67 | rb_erase(&al->sym->rb_node, |
68 | &al->map->dso->symbols[al->map->type]); | 68 | &al->map->dso->symbols[al->map->type]); |
69 | symbol__delete(al->sym); | 69 | symbol__delete(al->sym); |
70 | dso__reset_find_symbol_cache(al->map->dso); | ||
70 | } | 71 | } |
71 | return 0; | 72 | return 0; |
72 | } | 73 | } |
diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c index c61d14b101e0..c4b99008e2c9 100644 --- a/tools/perf/ui/tui/progress.c +++ b/tools/perf/ui/tui/progress.c | |||
@@ -33,9 +33,26 @@ static void tui_progress__update(struct ui_progress *p) | |||
33 | pthread_mutex_unlock(&ui__lock); | 33 | pthread_mutex_unlock(&ui__lock); |
34 | } | 34 | } |
35 | 35 | ||
36 | static void tui_progress__finish(void) | ||
37 | { | ||
38 | int y; | ||
39 | |||
40 | if (use_browser <= 0) | ||
41 | return; | ||
42 | |||
43 | ui__refresh_dimensions(false); | ||
44 | pthread_mutex_lock(&ui__lock); | ||
45 | y = SLtt_Screen_Rows / 2 - 2; | ||
46 | SLsmg_set_color(0); | ||
47 | SLsmg_fill_region(y, 0, 3, SLtt_Screen_Cols, ' '); | ||
48 | SLsmg_refresh(); | ||
49 | pthread_mutex_unlock(&ui__lock); | ||
50 | } | ||
51 | |||
36 | static struct ui_progress_ops tui_progress__ops = | 52 | static struct ui_progress_ops tui_progress__ops = |
37 | { | 53 | { |
38 | .update = tui_progress__update, | 54 | .update = tui_progress__update, |
55 | .finish = tui_progress__finish, | ||
39 | }; | 56 | }; |
40 | 57 | ||
41 | void tui_progress__init(void) | 58 | void tui_progress__init(void) |
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index c73276db6d6f..fc8db9c764ac 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h | |||
@@ -324,6 +324,8 @@ struct dso *__dsos__findnew(struct dsos *dsos, const char *name); | |||
324 | struct dso *dsos__findnew(struct dsos *dsos, const char *name); | 324 | struct dso *dsos__findnew(struct dsos *dsos, const char *name); |
325 | bool __dsos__read_build_ids(struct list_head *head, bool with_hits); | 325 | bool __dsos__read_build_ids(struct list_head *head, bool with_hits); |
326 | 326 | ||
327 | void dso__reset_find_symbol_cache(struct dso *dso); | ||
328 | |||
327 | size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, | 329 | size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, |
328 | bool (skip)(struct dso *dso, int parm), int parm); | 330 | bool (skip)(struct dso *dso, int parm), int parm); |
329 | size_t __dsos__fprintf(struct list_head *head, FILE *fp); | 331 | size_t __dsos__fprintf(struct list_head *head, FILE *fp); |
diff --git a/tools/perf/util/intel-pt-decoder/inat.c b/tools/perf/util/intel-pt-decoder/inat.c index feeaa509dfe4..906d94aa0a24 100644 --- a/tools/perf/util/intel-pt-decoder/inat.c +++ b/tools/perf/util/intel-pt-decoder/inat.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | #include <asm/insn.h> | 21 | #include "insn.h" |
22 | 22 | ||
23 | /* Attribute tables are generated from opcode map */ | 23 | /* Attribute tables are generated from opcode map */ |
24 | #include "inat-tables.c" | 24 | #include "inat-tables.c" |
diff --git a/tools/perf/util/intel-pt-decoder/inat.h b/tools/perf/util/intel-pt-decoder/inat.h index 74a2e312e8a2..611645e903a8 100644 --- a/tools/perf/util/intel-pt-decoder/inat.h +++ b/tools/perf/util/intel-pt-decoder/inat.h | |||
@@ -20,7 +20,7 @@ | |||
20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | #include <asm/inat_types.h> | 23 | #include "inat_types.h" |
24 | 24 | ||
25 | /* | 25 | /* |
26 | * Internal bits. Don't use bitmasks directly, because these bits are | 26 | * Internal bits. Don't use bitmasks directly, because these bits are |
diff --git a/tools/perf/util/intel-pt-decoder/inat_types.h b/tools/perf/util/intel-pt-decoder/inat_types.h new file mode 100644 index 000000000000..cb3c20ce39cf --- /dev/null +++ b/tools/perf/util/intel-pt-decoder/inat_types.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef _ASM_X86_INAT_TYPES_H | ||
2 | #define _ASM_X86_INAT_TYPES_H | ||
3 | /* | ||
4 | * x86 instruction attributes | ||
5 | * | ||
6 | * Written by Masami Hiramatsu <mhiramat@redhat.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | /* Instruction attributes */ | ||
25 | typedef unsigned int insn_attr_t; | ||
26 | typedef unsigned char insn_byte_t; | ||
27 | typedef signed int insn_value_t; | ||
28 | |||
29 | #endif | ||
diff --git a/tools/perf/util/intel-pt-decoder/insn.c b/tools/perf/util/intel-pt-decoder/insn.c index 8f72b334aea0..47314a64399c 100644 --- a/tools/perf/util/intel-pt-decoder/insn.c +++ b/tools/perf/util/intel-pt-decoder/insn.c | |||
@@ -23,8 +23,8 @@ | |||
23 | #else | 23 | #else |
24 | #include <string.h> | 24 | #include <string.h> |
25 | #endif | 25 | #endif |
26 | #include <asm/inat.h> | 26 | #include "inat.h" |
27 | #include <asm/insn.h> | 27 | #include "insn.h" |
28 | 28 | ||
29 | /* Verify next sizeof(t) bytes can be on the same instruction */ | 29 | /* Verify next sizeof(t) bytes can be on the same instruction */ |
30 | #define validate_next(t, insn, n) \ | 30 | #define validate_next(t, insn, n) \ |
diff --git a/tools/perf/util/intel-pt-decoder/insn.h b/tools/perf/util/intel-pt-decoder/insn.h index e7814b74caf8..dd12da0f4593 100644 --- a/tools/perf/util/intel-pt-decoder/insn.h +++ b/tools/perf/util/intel-pt-decoder/insn.h | |||
@@ -21,7 +21,7 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | /* insn_attr_t is defined in inat.h */ | 23 | /* insn_attr_t is defined in inat.h */ |
24 | #include <asm/inat.h> | 24 | #include "inat.h" |
25 | 25 | ||
26 | struct insn_field { | 26 | struct insn_field { |
27 | union { | 27 | union { |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index f8ac462fec1a..22ba50224319 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | |||
@@ -85,7 +85,10 @@ struct intel_pt_decoder { | |||
85 | const unsigned char *buf; | 85 | const unsigned char *buf; |
86 | size_t len; | 86 | size_t len; |
87 | bool return_compression; | 87 | bool return_compression; |
88 | bool mtc_insn; | ||
88 | bool pge; | 89 | bool pge; |
90 | bool have_tma; | ||
91 | bool have_cyc; | ||
89 | uint64_t pos; | 92 | uint64_t pos; |
90 | uint64_t last_ip; | 93 | uint64_t last_ip; |
91 | uint64_t ip; | 94 | uint64_t ip; |
@@ -94,20 +97,37 @@ struct intel_pt_decoder { | |||
94 | uint64_t tsc_timestamp; | 97 | uint64_t tsc_timestamp; |
95 | uint64_t ref_timestamp; | 98 | uint64_t ref_timestamp; |
96 | uint64_t ret_addr; | 99 | uint64_t ret_addr; |
100 | uint64_t ctc_timestamp; | ||
101 | uint64_t ctc_delta; | ||
102 | uint64_t cycle_cnt; | ||
103 | uint64_t cyc_ref_timestamp; | ||
104 | uint32_t last_mtc; | ||
105 | uint32_t tsc_ctc_ratio_n; | ||
106 | uint32_t tsc_ctc_ratio_d; | ||
107 | uint32_t tsc_ctc_mult; | ||
108 | uint32_t tsc_slip; | ||
109 | uint32_t ctc_rem_mask; | ||
110 | int mtc_shift; | ||
97 | struct intel_pt_stack stack; | 111 | struct intel_pt_stack stack; |
98 | enum intel_pt_pkt_state pkt_state; | 112 | enum intel_pt_pkt_state pkt_state; |
99 | struct intel_pt_pkt packet; | 113 | struct intel_pt_pkt packet; |
100 | struct intel_pt_pkt tnt; | 114 | struct intel_pt_pkt tnt; |
101 | int pkt_step; | 115 | int pkt_step; |
102 | int pkt_len; | 116 | int pkt_len; |
117 | int last_packet_type; | ||
103 | unsigned int cbr; | 118 | unsigned int cbr; |
104 | unsigned int max_non_turbo_ratio; | 119 | unsigned int max_non_turbo_ratio; |
120 | double max_non_turbo_ratio_fp; | ||
121 | double cbr_cyc_to_tsc; | ||
122 | double calc_cyc_to_tsc; | ||
123 | bool have_calc_cyc_to_tsc; | ||
105 | int exec_mode; | 124 | int exec_mode; |
106 | unsigned int insn_bytes; | 125 | unsigned int insn_bytes; |
107 | uint64_t sign_bit; | 126 | uint64_t sign_bit; |
108 | uint64_t sign_bits; | 127 | uint64_t sign_bits; |
109 | uint64_t period; | 128 | uint64_t period; |
110 | enum intel_pt_period_type period_type; | 129 | enum intel_pt_period_type period_type; |
130 | uint64_t tot_insn_cnt; | ||
111 | uint64_t period_insn_cnt; | 131 | uint64_t period_insn_cnt; |
112 | uint64_t period_mask; | 132 | uint64_t period_mask; |
113 | uint64_t period_ticks; | 133 | uint64_t period_ticks; |
@@ -148,6 +168,13 @@ static void intel_pt_setup_period(struct intel_pt_decoder *decoder) | |||
148 | } | 168 | } |
149 | } | 169 | } |
150 | 170 | ||
171 | static uint64_t multdiv(uint64_t t, uint32_t n, uint32_t d) | ||
172 | { | ||
173 | if (!d) | ||
174 | return 0; | ||
175 | return (t / d) * n + ((t % d) * n) / d; | ||
176 | } | ||
177 | |||
151 | struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) | 178 | struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) |
152 | { | 179 | { |
153 | struct intel_pt_decoder *decoder; | 180 | struct intel_pt_decoder *decoder; |
@@ -170,10 +197,44 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) | |||
170 | decoder->period = params->period; | 197 | decoder->period = params->period; |
171 | decoder->period_type = params->period_type; | 198 | decoder->period_type = params->period_type; |
172 | 199 | ||
173 | decoder->max_non_turbo_ratio = params->max_non_turbo_ratio; | 200 | decoder->max_non_turbo_ratio = params->max_non_turbo_ratio; |
201 | decoder->max_non_turbo_ratio_fp = params->max_non_turbo_ratio; | ||
174 | 202 | ||
175 | intel_pt_setup_period(decoder); | 203 | intel_pt_setup_period(decoder); |
176 | 204 | ||
205 | decoder->mtc_shift = params->mtc_period; | ||
206 | decoder->ctc_rem_mask = (1 << decoder->mtc_shift) - 1; | ||
207 | |||
208 | decoder->tsc_ctc_ratio_n = params->tsc_ctc_ratio_n; | ||
209 | decoder->tsc_ctc_ratio_d = params->tsc_ctc_ratio_d; | ||
210 | |||
211 | if (!decoder->tsc_ctc_ratio_n) | ||
212 | decoder->tsc_ctc_ratio_d = 0; | ||
213 | |||
214 | if (decoder->tsc_ctc_ratio_d) { | ||
215 | if (!(decoder->tsc_ctc_ratio_n % decoder->tsc_ctc_ratio_d)) | ||
216 | decoder->tsc_ctc_mult = decoder->tsc_ctc_ratio_n / | ||
217 | decoder->tsc_ctc_ratio_d; | ||
218 | |||
219 | /* | ||
220 | * Allow for timestamps appearing to backwards because a TSC | ||
221 | * packet has slipped past a MTC packet, so allow 2 MTC ticks | ||
222 | * or ... | ||
223 | */ | ||
224 | decoder->tsc_slip = multdiv(2 << decoder->mtc_shift, | ||
225 | decoder->tsc_ctc_ratio_n, | ||
226 | decoder->tsc_ctc_ratio_d); | ||
227 | } | ||
228 | /* ... or 0x100 paranoia */ | ||
229 | if (decoder->tsc_slip < 0x100) | ||
230 | decoder->tsc_slip = 0x100; | ||
231 | |||
232 | intel_pt_log("timestamp: mtc_shift %u\n", decoder->mtc_shift); | ||
233 | intel_pt_log("timestamp: tsc_ctc_ratio_n %u\n", decoder->tsc_ctc_ratio_n); | ||
234 | intel_pt_log("timestamp: tsc_ctc_ratio_d %u\n", decoder->tsc_ctc_ratio_d); | ||
235 | intel_pt_log("timestamp: tsc_ctc_mult %u\n", decoder->tsc_ctc_mult); | ||
236 | intel_pt_log("timestamp: tsc_slip %#x\n", decoder->tsc_slip); | ||
237 | |||
177 | return decoder; | 238 | return decoder; |
178 | } | 239 | } |
179 | 240 | ||
@@ -367,6 +428,7 @@ static inline void intel_pt_update_in_tx(struct intel_pt_decoder *decoder) | |||
367 | static int intel_pt_bad_packet(struct intel_pt_decoder *decoder) | 428 | static int intel_pt_bad_packet(struct intel_pt_decoder *decoder) |
368 | { | 429 | { |
369 | intel_pt_clear_tx_flags(decoder); | 430 | intel_pt_clear_tx_flags(decoder); |
431 | decoder->have_tma = false; | ||
370 | decoder->pkt_len = 1; | 432 | decoder->pkt_len = 1; |
371 | decoder->pkt_step = 1; | 433 | decoder->pkt_step = 1; |
372 | intel_pt_decoder_log_packet(decoder); | 434 | intel_pt_decoder_log_packet(decoder); |
@@ -399,6 +461,7 @@ static int intel_pt_get_data(struct intel_pt_decoder *decoder) | |||
399 | decoder->pkt_state = INTEL_PT_STATE_NO_PSB; | 461 | decoder->pkt_state = INTEL_PT_STATE_NO_PSB; |
400 | decoder->ref_timestamp = buffer.ref_timestamp; | 462 | decoder->ref_timestamp = buffer.ref_timestamp; |
401 | decoder->timestamp = 0; | 463 | decoder->timestamp = 0; |
464 | decoder->have_tma = false; | ||
402 | decoder->state.trace_nr = buffer.trace_nr; | 465 | decoder->state.trace_nr = buffer.trace_nr; |
403 | intel_pt_log("Reference timestamp 0x%" PRIx64 "\n", | 466 | intel_pt_log("Reference timestamp 0x%" PRIx64 "\n", |
404 | decoder->ref_timestamp); | 467 | decoder->ref_timestamp); |
@@ -460,10 +523,247 @@ static int intel_pt_get_split_packet(struct intel_pt_decoder *decoder) | |||
460 | return ret; | 523 | return ret; |
461 | } | 524 | } |
462 | 525 | ||
526 | struct intel_pt_pkt_info { | ||
527 | struct intel_pt_decoder *decoder; | ||
528 | struct intel_pt_pkt packet; | ||
529 | uint64_t pos; | ||
530 | int pkt_len; | ||
531 | int last_packet_type; | ||
532 | void *data; | ||
533 | }; | ||
534 | |||
535 | typedef int (*intel_pt_pkt_cb_t)(struct intel_pt_pkt_info *pkt_info); | ||
536 | |||
537 | /* Lookahead packets in current buffer */ | ||
538 | static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder, | ||
539 | intel_pt_pkt_cb_t cb, void *data) | ||
540 | { | ||
541 | struct intel_pt_pkt_info pkt_info; | ||
542 | const unsigned char *buf = decoder->buf; | ||
543 | size_t len = decoder->len; | ||
544 | int ret; | ||
545 | |||
546 | pkt_info.decoder = decoder; | ||
547 | pkt_info.pos = decoder->pos; | ||
548 | pkt_info.pkt_len = decoder->pkt_step; | ||
549 | pkt_info.last_packet_type = decoder->last_packet_type; | ||
550 | pkt_info.data = data; | ||
551 | |||
552 | while (1) { | ||
553 | do { | ||
554 | pkt_info.pos += pkt_info.pkt_len; | ||
555 | buf += pkt_info.pkt_len; | ||
556 | len -= pkt_info.pkt_len; | ||
557 | |||
558 | if (!len) | ||
559 | return INTEL_PT_NEED_MORE_BYTES; | ||
560 | |||
561 | ret = intel_pt_get_packet(buf, len, &pkt_info.packet); | ||
562 | if (!ret) | ||
563 | return INTEL_PT_NEED_MORE_BYTES; | ||
564 | if (ret < 0) | ||
565 | return ret; | ||
566 | |||
567 | pkt_info.pkt_len = ret; | ||
568 | } while (pkt_info.packet.type == INTEL_PT_PAD); | ||
569 | |||
570 | ret = cb(&pkt_info); | ||
571 | if (ret) | ||
572 | return 0; | ||
573 | |||
574 | pkt_info.last_packet_type = pkt_info.packet.type; | ||
575 | } | ||
576 | } | ||
577 | |||
578 | struct intel_pt_calc_cyc_to_tsc_info { | ||
579 | uint64_t cycle_cnt; | ||
580 | unsigned int cbr; | ||
581 | uint32_t last_mtc; | ||
582 | uint64_t ctc_timestamp; | ||
583 | uint64_t ctc_delta; | ||
584 | uint64_t tsc_timestamp; | ||
585 | uint64_t timestamp; | ||
586 | bool have_tma; | ||
587 | bool from_mtc; | ||
588 | double cbr_cyc_to_tsc; | ||
589 | }; | ||
590 | |||
591 | static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info) | ||
592 | { | ||
593 | struct intel_pt_decoder *decoder = pkt_info->decoder; | ||
594 | struct intel_pt_calc_cyc_to_tsc_info *data = pkt_info->data; | ||
595 | uint64_t timestamp; | ||
596 | double cyc_to_tsc; | ||
597 | unsigned int cbr; | ||
598 | uint32_t mtc, mtc_delta, ctc, fc, ctc_rem; | ||
599 | |||
600 | switch (pkt_info->packet.type) { | ||
601 | case INTEL_PT_TNT: | ||
602 | case INTEL_PT_TIP_PGE: | ||
603 | case INTEL_PT_TIP: | ||
604 | case INTEL_PT_FUP: | ||
605 | case INTEL_PT_PSB: | ||
606 | case INTEL_PT_PIP: | ||
607 | case INTEL_PT_MODE_EXEC: | ||
608 | case INTEL_PT_MODE_TSX: | ||
609 | case INTEL_PT_PSBEND: | ||
610 | case INTEL_PT_PAD: | ||
611 | case INTEL_PT_VMCS: | ||
612 | case INTEL_PT_MNT: | ||
613 | return 0; | ||
614 | |||
615 | case INTEL_PT_MTC: | ||
616 | if (!data->have_tma) | ||
617 | return 0; | ||
618 | |||
619 | mtc = pkt_info->packet.payload; | ||
620 | if (mtc > data->last_mtc) | ||
621 | mtc_delta = mtc - data->last_mtc; | ||
622 | else | ||
623 | mtc_delta = mtc + 256 - data->last_mtc; | ||
624 | data->ctc_delta += mtc_delta << decoder->mtc_shift; | ||
625 | data->last_mtc = mtc; | ||
626 | |||
627 | if (decoder->tsc_ctc_mult) { | ||
628 | timestamp = data->ctc_timestamp + | ||
629 | data->ctc_delta * decoder->tsc_ctc_mult; | ||
630 | } else { | ||
631 | timestamp = data->ctc_timestamp + | ||
632 | multdiv(data->ctc_delta, | ||
633 | decoder->tsc_ctc_ratio_n, | ||
634 | decoder->tsc_ctc_ratio_d); | ||
635 | } | ||
636 | |||
637 | if (timestamp < data->timestamp) | ||
638 | return 1; | ||
639 | |||
640 | if (pkt_info->last_packet_type != INTEL_PT_CYC) { | ||
641 | data->timestamp = timestamp; | ||
642 | return 0; | ||
643 | } | ||
644 | |||
645 | break; | ||
646 | |||
647 | case INTEL_PT_TSC: | ||
648 | timestamp = pkt_info->packet.payload | | ||
649 | (data->timestamp & (0xffULL << 56)); | ||
650 | if (data->from_mtc && timestamp < data->timestamp && | ||
651 | data->timestamp - timestamp < decoder->tsc_slip) | ||
652 | return 1; | ||
653 | while (timestamp < data->timestamp) | ||
654 | timestamp += (1ULL << 56); | ||
655 | if (pkt_info->last_packet_type != INTEL_PT_CYC) { | ||
656 | if (data->from_mtc) | ||
657 | return 1; | ||
658 | data->tsc_timestamp = timestamp; | ||
659 | data->timestamp = timestamp; | ||
660 | return 0; | ||
661 | } | ||
662 | break; | ||
663 | |||
664 | case INTEL_PT_TMA: | ||
665 | if (data->from_mtc) | ||
666 | return 1; | ||
667 | |||
668 | if (!decoder->tsc_ctc_ratio_d) | ||
669 | return 0; | ||
670 | |||
671 | ctc = pkt_info->packet.payload; | ||
672 | fc = pkt_info->packet.count; | ||
673 | ctc_rem = ctc & decoder->ctc_rem_mask; | ||
674 | |||
675 | data->last_mtc = (ctc >> decoder->mtc_shift) & 0xff; | ||
676 | |||
677 | data->ctc_timestamp = data->tsc_timestamp - fc; | ||
678 | if (decoder->tsc_ctc_mult) { | ||
679 | data->ctc_timestamp -= ctc_rem * decoder->tsc_ctc_mult; | ||
680 | } else { | ||
681 | data->ctc_timestamp -= | ||
682 | multdiv(ctc_rem, decoder->tsc_ctc_ratio_n, | ||
683 | decoder->tsc_ctc_ratio_d); | ||
684 | } | ||
685 | |||
686 | data->ctc_delta = 0; | ||
687 | data->have_tma = true; | ||
688 | |||
689 | return 0; | ||
690 | |||
691 | case INTEL_PT_CYC: | ||
692 | data->cycle_cnt += pkt_info->packet.payload; | ||
693 | return 0; | ||
694 | |||
695 | case INTEL_PT_CBR: | ||
696 | cbr = pkt_info->packet.payload; | ||
697 | if (data->cbr && data->cbr != cbr) | ||
698 | return 1; | ||
699 | data->cbr = cbr; | ||
700 | data->cbr_cyc_to_tsc = decoder->max_non_turbo_ratio_fp / cbr; | ||
701 | return 0; | ||
702 | |||
703 | case INTEL_PT_TIP_PGD: | ||
704 | case INTEL_PT_TRACESTOP: | ||
705 | case INTEL_PT_OVF: | ||
706 | case INTEL_PT_BAD: /* Does not happen */ | ||
707 | default: | ||
708 | return 1; | ||
709 | } | ||
710 | |||
711 | if (!data->cbr && decoder->cbr) { | ||
712 | data->cbr = decoder->cbr; | ||
713 | data->cbr_cyc_to_tsc = decoder->cbr_cyc_to_tsc; | ||
714 | } | ||
715 | |||
716 | if (!data->cycle_cnt) | ||
717 | return 1; | ||
718 | |||
719 | cyc_to_tsc = (double)(timestamp - decoder->timestamp) / data->cycle_cnt; | ||
720 | |||
721 | if (data->cbr && cyc_to_tsc > data->cbr_cyc_to_tsc && | ||
722 | cyc_to_tsc / data->cbr_cyc_to_tsc > 1.25) { | ||
723 | intel_pt_log("Timestamp: calculated %g TSC ticks per cycle too big (c.f. CBR-based value %g), pos " x64_fmt "\n", | ||
724 | cyc_to_tsc, data->cbr_cyc_to_tsc, pkt_info->pos); | ||
725 | return 1; | ||
726 | } | ||
727 | |||
728 | decoder->calc_cyc_to_tsc = cyc_to_tsc; | ||
729 | decoder->have_calc_cyc_to_tsc = true; | ||
730 | |||
731 | if (data->cbr) { | ||
732 | intel_pt_log("Timestamp: calculated %g TSC ticks per cycle c.f. CBR-based value %g, pos " x64_fmt "\n", | ||
733 | cyc_to_tsc, data->cbr_cyc_to_tsc, pkt_info->pos); | ||
734 | } else { | ||
735 | intel_pt_log("Timestamp: calculated %g TSC ticks per cycle c.f. unknown CBR-based value, pos " x64_fmt "\n", | ||
736 | cyc_to_tsc, pkt_info->pos); | ||
737 | } | ||
738 | |||
739 | return 1; | ||
740 | } | ||
741 | |||
742 | static void intel_pt_calc_cyc_to_tsc(struct intel_pt_decoder *decoder, | ||
743 | bool from_mtc) | ||
744 | { | ||
745 | struct intel_pt_calc_cyc_to_tsc_info data = { | ||
746 | .cycle_cnt = 0, | ||
747 | .cbr = 0, | ||
748 | .last_mtc = decoder->last_mtc, | ||
749 | .ctc_timestamp = decoder->ctc_timestamp, | ||
750 | .ctc_delta = decoder->ctc_delta, | ||
751 | .tsc_timestamp = decoder->tsc_timestamp, | ||
752 | .timestamp = decoder->timestamp, | ||
753 | .have_tma = decoder->have_tma, | ||
754 | .from_mtc = from_mtc, | ||
755 | .cbr_cyc_to_tsc = 0, | ||
756 | }; | ||
757 | |||
758 | intel_pt_pkt_lookahead(decoder, intel_pt_calc_cyc_cb, &data); | ||
759 | } | ||
760 | |||
463 | static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder) | 761 | static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder) |
464 | { | 762 | { |
465 | int ret; | 763 | int ret; |
466 | 764 | ||
765 | decoder->last_packet_type = decoder->packet.type; | ||
766 | |||
467 | do { | 767 | do { |
468 | decoder->pos += decoder->pkt_step; | 768 | decoder->pos += decoder->pkt_step; |
469 | decoder->buf += decoder->pkt_step; | 769 | decoder->buf += decoder->pkt_step; |
@@ -522,6 +822,7 @@ static uint64_t intel_pt_next_sample(struct intel_pt_decoder *decoder) | |||
522 | case INTEL_PT_PERIOD_TICKS: | 822 | case INTEL_PT_PERIOD_TICKS: |
523 | return intel_pt_next_period(decoder); | 823 | return intel_pt_next_period(decoder); |
524 | case INTEL_PT_PERIOD_NONE: | 824 | case INTEL_PT_PERIOD_NONE: |
825 | case INTEL_PT_PERIOD_MTC: | ||
525 | default: | 826 | default: |
526 | return 0; | 827 | return 0; |
527 | } | 828 | } |
@@ -541,6 +842,7 @@ static void intel_pt_sample_insn(struct intel_pt_decoder *decoder) | |||
541 | decoder->last_masked_timestamp = masked_timestamp; | 842 | decoder->last_masked_timestamp = masked_timestamp; |
542 | break; | 843 | break; |
543 | case INTEL_PT_PERIOD_NONE: | 844 | case INTEL_PT_PERIOD_NONE: |
845 | case INTEL_PT_PERIOD_MTC: | ||
544 | default: | 846 | default: |
545 | break; | 847 | break; |
546 | } | 848 | } |
@@ -554,11 +856,15 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder, | |||
554 | uint64_t max_insn_cnt, insn_cnt = 0; | 856 | uint64_t max_insn_cnt, insn_cnt = 0; |
555 | int err; | 857 | int err; |
556 | 858 | ||
859 | if (!decoder->mtc_insn) | ||
860 | decoder->mtc_insn = true; | ||
861 | |||
557 | max_insn_cnt = intel_pt_next_sample(decoder); | 862 | max_insn_cnt = intel_pt_next_sample(decoder); |
558 | 863 | ||
559 | err = decoder->walk_insn(intel_pt_insn, &insn_cnt, &decoder->ip, ip, | 864 | err = decoder->walk_insn(intel_pt_insn, &insn_cnt, &decoder->ip, ip, |
560 | max_insn_cnt, decoder->data); | 865 | max_insn_cnt, decoder->data); |
561 | 866 | ||
867 | decoder->tot_insn_cnt += insn_cnt; | ||
562 | decoder->timestamp_insn_cnt += insn_cnt; | 868 | decoder->timestamp_insn_cnt += insn_cnt; |
563 | decoder->period_insn_cnt += insn_cnt; | 869 | decoder->period_insn_cnt += insn_cnt; |
564 | 870 | ||
@@ -859,6 +1165,8 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder) | |||
859 | { | 1165 | { |
860 | uint64_t timestamp; | 1166 | uint64_t timestamp; |
861 | 1167 | ||
1168 | decoder->have_tma = false; | ||
1169 | |||
862 | if (decoder->ref_timestamp) { | 1170 | if (decoder->ref_timestamp) { |
863 | timestamp = decoder->packet.payload | | 1171 | timestamp = decoder->packet.payload | |
864 | (decoder->ref_timestamp & (0xffULL << 56)); | 1172 | (decoder->ref_timestamp & (0xffULL << 56)); |
@@ -876,21 +1184,29 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder) | |||
876 | } else if (decoder->timestamp) { | 1184 | } else if (decoder->timestamp) { |
877 | timestamp = decoder->packet.payload | | 1185 | timestamp = decoder->packet.payload | |
878 | (decoder->timestamp & (0xffULL << 56)); | 1186 | (decoder->timestamp & (0xffULL << 56)); |
1187 | decoder->tsc_timestamp = timestamp; | ||
879 | if (timestamp < decoder->timestamp && | 1188 | if (timestamp < decoder->timestamp && |
880 | decoder->timestamp - timestamp < 0x100) { | 1189 | decoder->timestamp - timestamp < decoder->tsc_slip) { |
881 | intel_pt_log_to("ERROR: Suppressing backwards timestamp", | 1190 | intel_pt_log_to("Suppressing backwards timestamp", |
882 | timestamp); | 1191 | timestamp); |
883 | timestamp = decoder->timestamp; | 1192 | timestamp = decoder->timestamp; |
884 | } | 1193 | } |
885 | while (timestamp < decoder->timestamp) { | 1194 | while (timestamp < decoder->timestamp) { |
886 | intel_pt_log_to("Wraparound timestamp", timestamp); | 1195 | intel_pt_log_to("Wraparound timestamp", timestamp); |
887 | timestamp += (1ULL << 56); | 1196 | timestamp += (1ULL << 56); |
1197 | decoder->tsc_timestamp = timestamp; | ||
888 | } | 1198 | } |
889 | decoder->tsc_timestamp = timestamp; | ||
890 | decoder->timestamp = timestamp; | 1199 | decoder->timestamp = timestamp; |
891 | decoder->timestamp_insn_cnt = 0; | 1200 | decoder->timestamp_insn_cnt = 0; |
892 | } | 1201 | } |
893 | 1202 | ||
1203 | if (decoder->last_packet_type == INTEL_PT_CYC) { | ||
1204 | decoder->cyc_ref_timestamp = decoder->timestamp; | ||
1205 | decoder->cycle_cnt = 0; | ||
1206 | decoder->have_calc_cyc_to_tsc = false; | ||
1207 | intel_pt_calc_cyc_to_tsc(decoder, false); | ||
1208 | } | ||
1209 | |||
894 | intel_pt_log_to("Setting timestamp", decoder->timestamp); | 1210 | intel_pt_log_to("Setting timestamp", decoder->timestamp); |
895 | } | 1211 | } |
896 | 1212 | ||
@@ -898,11 +1214,117 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder) | |||
898 | { | 1214 | { |
899 | intel_pt_log("ERROR: Buffer overflow\n"); | 1215 | intel_pt_log("ERROR: Buffer overflow\n"); |
900 | intel_pt_clear_tx_flags(decoder); | 1216 | intel_pt_clear_tx_flags(decoder); |
1217 | decoder->have_tma = false; | ||
1218 | decoder->cbr = 0; | ||
901 | decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; | 1219 | decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; |
902 | decoder->overflow = true; | 1220 | decoder->overflow = true; |
903 | return -EOVERFLOW; | 1221 | return -EOVERFLOW; |
904 | } | 1222 | } |
905 | 1223 | ||
1224 | static void intel_pt_calc_tma(struct intel_pt_decoder *decoder) | ||
1225 | { | ||
1226 | uint32_t ctc = decoder->packet.payload; | ||
1227 | uint32_t fc = decoder->packet.count; | ||
1228 | uint32_t ctc_rem = ctc & decoder->ctc_rem_mask; | ||
1229 | |||
1230 | if (!decoder->tsc_ctc_ratio_d) | ||
1231 | return; | ||
1232 | |||
1233 | decoder->last_mtc = (ctc >> decoder->mtc_shift) & 0xff; | ||
1234 | decoder->ctc_timestamp = decoder->tsc_timestamp - fc; | ||
1235 | if (decoder->tsc_ctc_mult) { | ||
1236 | decoder->ctc_timestamp -= ctc_rem * decoder->tsc_ctc_mult; | ||
1237 | } else { | ||
1238 | decoder->ctc_timestamp -= multdiv(ctc_rem, | ||
1239 | decoder->tsc_ctc_ratio_n, | ||
1240 | decoder->tsc_ctc_ratio_d); | ||
1241 | } | ||
1242 | decoder->ctc_delta = 0; | ||
1243 | decoder->have_tma = true; | ||
1244 | intel_pt_log("CTC timestamp " x64_fmt " last MTC %#x CTC rem %#x\n", | ||
1245 | decoder->ctc_timestamp, decoder->last_mtc, ctc_rem); | ||
1246 | } | ||
1247 | |||
1248 | static void intel_pt_calc_mtc_timestamp(struct intel_pt_decoder *decoder) | ||
1249 | { | ||
1250 | uint64_t timestamp; | ||
1251 | uint32_t mtc, mtc_delta; | ||
1252 | |||
1253 | if (!decoder->have_tma) | ||
1254 | return; | ||
1255 | |||
1256 | mtc = decoder->packet.payload; | ||
1257 | |||
1258 | if (mtc > decoder->last_mtc) | ||
1259 | mtc_delta = mtc - decoder->last_mtc; | ||
1260 | else | ||
1261 | mtc_delta = mtc + 256 - decoder->last_mtc; | ||
1262 | |||
1263 | decoder->ctc_delta += mtc_delta << decoder->mtc_shift; | ||
1264 | |||
1265 | if (decoder->tsc_ctc_mult) { | ||
1266 | timestamp = decoder->ctc_timestamp + | ||
1267 | decoder->ctc_delta * decoder->tsc_ctc_mult; | ||
1268 | } else { | ||
1269 | timestamp = decoder->ctc_timestamp + | ||
1270 | multdiv(decoder->ctc_delta, | ||
1271 | decoder->tsc_ctc_ratio_n, | ||
1272 | decoder->tsc_ctc_ratio_d); | ||
1273 | } | ||
1274 | |||
1275 | if (timestamp < decoder->timestamp) | ||
1276 | intel_pt_log("Suppressing MTC timestamp " x64_fmt " less than current timestamp " x64_fmt "\n", | ||
1277 | timestamp, decoder->timestamp); | ||
1278 | else | ||
1279 | decoder->timestamp = timestamp; | ||
1280 | |||
1281 | decoder->timestamp_insn_cnt = 0; | ||
1282 | decoder->last_mtc = mtc; | ||
1283 | |||
1284 | if (decoder->last_packet_type == INTEL_PT_CYC) { | ||
1285 | decoder->cyc_ref_timestamp = decoder->timestamp; | ||
1286 | decoder->cycle_cnt = 0; | ||
1287 | decoder->have_calc_cyc_to_tsc = false; | ||
1288 | intel_pt_calc_cyc_to_tsc(decoder, true); | ||
1289 | } | ||
1290 | } | ||
1291 | |||
1292 | static void intel_pt_calc_cbr(struct intel_pt_decoder *decoder) | ||
1293 | { | ||
1294 | unsigned int cbr = decoder->packet.payload; | ||
1295 | |||
1296 | if (decoder->cbr == cbr) | ||
1297 | return; | ||
1298 | |||
1299 | decoder->cbr = cbr; | ||
1300 | decoder->cbr_cyc_to_tsc = decoder->max_non_turbo_ratio_fp / cbr; | ||
1301 | } | ||
1302 | |||
1303 | static void intel_pt_calc_cyc_timestamp(struct intel_pt_decoder *decoder) | ||
1304 | { | ||
1305 | uint64_t timestamp = decoder->cyc_ref_timestamp; | ||
1306 | |||
1307 | decoder->have_cyc = true; | ||
1308 | |||
1309 | decoder->cycle_cnt += decoder->packet.payload; | ||
1310 | |||
1311 | if (!decoder->cyc_ref_timestamp) | ||
1312 | return; | ||
1313 | |||
1314 | if (decoder->have_calc_cyc_to_tsc) | ||
1315 | timestamp += decoder->cycle_cnt * decoder->calc_cyc_to_tsc; | ||
1316 | else if (decoder->cbr) | ||
1317 | timestamp += decoder->cycle_cnt * decoder->cbr_cyc_to_tsc; | ||
1318 | else | ||
1319 | return; | ||
1320 | |||
1321 | if (timestamp < decoder->timestamp) | ||
1322 | intel_pt_log("Suppressing CYC timestamp " x64_fmt " less than current timestamp " x64_fmt "\n", | ||
1323 | timestamp, decoder->timestamp); | ||
1324 | else | ||
1325 | decoder->timestamp = timestamp; | ||
1326 | } | ||
1327 | |||
906 | /* Walk PSB+ packets when already in sync. */ | 1328 | /* Walk PSB+ packets when already in sync. */ |
907 | static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | 1329 | static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) |
908 | { | 1330 | { |
@@ -921,8 +1343,10 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | |||
921 | case INTEL_PT_TIP_PGE: | 1343 | case INTEL_PT_TIP_PGE: |
922 | case INTEL_PT_TIP: | 1344 | case INTEL_PT_TIP: |
923 | case INTEL_PT_TNT: | 1345 | case INTEL_PT_TNT: |
1346 | case INTEL_PT_TRACESTOP: | ||
924 | case INTEL_PT_BAD: | 1347 | case INTEL_PT_BAD: |
925 | case INTEL_PT_PSB: | 1348 | case INTEL_PT_PSB: |
1349 | decoder->have_tma = false; | ||
926 | intel_pt_log("ERROR: Unexpected packet\n"); | 1350 | intel_pt_log("ERROR: Unexpected packet\n"); |
927 | return -EAGAIN; | 1351 | return -EAGAIN; |
928 | 1352 | ||
@@ -933,8 +1357,12 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | |||
933 | intel_pt_calc_tsc_timestamp(decoder); | 1357 | intel_pt_calc_tsc_timestamp(decoder); |
934 | break; | 1358 | break; |
935 | 1359 | ||
1360 | case INTEL_PT_TMA: | ||
1361 | intel_pt_calc_tma(decoder); | ||
1362 | break; | ||
1363 | |||
936 | case INTEL_PT_CBR: | 1364 | case INTEL_PT_CBR: |
937 | decoder->cbr = decoder->packet.payload; | 1365 | intel_pt_calc_cbr(decoder); |
938 | break; | 1366 | break; |
939 | 1367 | ||
940 | case INTEL_PT_MODE_EXEC: | 1368 | case INTEL_PT_MODE_EXEC: |
@@ -942,7 +1370,7 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | |||
942 | break; | 1370 | break; |
943 | 1371 | ||
944 | case INTEL_PT_PIP: | 1372 | case INTEL_PT_PIP: |
945 | decoder->cr3 = decoder->packet.payload; | 1373 | decoder->cr3 = decoder->packet.payload & (BIT63 - 1); |
946 | break; | 1374 | break; |
947 | 1375 | ||
948 | case INTEL_PT_FUP: | 1376 | case INTEL_PT_FUP: |
@@ -954,6 +1382,15 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | |||
954 | intel_pt_update_in_tx(decoder); | 1382 | intel_pt_update_in_tx(decoder); |
955 | break; | 1383 | break; |
956 | 1384 | ||
1385 | case INTEL_PT_MTC: | ||
1386 | intel_pt_calc_mtc_timestamp(decoder); | ||
1387 | if (decoder->period_type == INTEL_PT_PERIOD_MTC) | ||
1388 | decoder->state.type |= INTEL_PT_INSTRUCTION; | ||
1389 | break; | ||
1390 | |||
1391 | case INTEL_PT_CYC: | ||
1392 | case INTEL_PT_VMCS: | ||
1393 | case INTEL_PT_MNT: | ||
957 | case INTEL_PT_PAD: | 1394 | case INTEL_PT_PAD: |
958 | default: | 1395 | default: |
959 | break; | 1396 | break; |
@@ -981,8 +1418,10 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder) | |||
981 | switch (decoder->packet.type) { | 1418 | switch (decoder->packet.type) { |
982 | case INTEL_PT_TNT: | 1419 | case INTEL_PT_TNT: |
983 | case INTEL_PT_FUP: | 1420 | case INTEL_PT_FUP: |
1421 | case INTEL_PT_TRACESTOP: | ||
984 | case INTEL_PT_PSB: | 1422 | case INTEL_PT_PSB: |
985 | case INTEL_PT_TSC: | 1423 | case INTEL_PT_TSC: |
1424 | case INTEL_PT_TMA: | ||
986 | case INTEL_PT_CBR: | 1425 | case INTEL_PT_CBR: |
987 | case INTEL_PT_MODE_TSX: | 1426 | case INTEL_PT_MODE_TSX: |
988 | case INTEL_PT_BAD: | 1427 | case INTEL_PT_BAD: |
@@ -1030,13 +1469,25 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder) | |||
1030 | return 0; | 1469 | return 0; |
1031 | 1470 | ||
1032 | case INTEL_PT_PIP: | 1471 | case INTEL_PT_PIP: |
1033 | decoder->cr3 = decoder->packet.payload; | 1472 | decoder->cr3 = decoder->packet.payload & (BIT63 - 1); |
1473 | break; | ||
1474 | |||
1475 | case INTEL_PT_MTC: | ||
1476 | intel_pt_calc_mtc_timestamp(decoder); | ||
1477 | if (decoder->period_type == INTEL_PT_PERIOD_MTC) | ||
1478 | decoder->state.type |= INTEL_PT_INSTRUCTION; | ||
1479 | break; | ||
1480 | |||
1481 | case INTEL_PT_CYC: | ||
1482 | intel_pt_calc_cyc_timestamp(decoder); | ||
1034 | break; | 1483 | break; |
1035 | 1484 | ||
1036 | case INTEL_PT_MODE_EXEC: | 1485 | case INTEL_PT_MODE_EXEC: |
1037 | decoder->exec_mode = decoder->packet.payload; | 1486 | decoder->exec_mode = decoder->packet.payload; |
1038 | break; | 1487 | break; |
1039 | 1488 | ||
1489 | case INTEL_PT_VMCS: | ||
1490 | case INTEL_PT_MNT: | ||
1040 | case INTEL_PT_PAD: | 1491 | case INTEL_PT_PAD: |
1041 | break; | 1492 | break; |
1042 | 1493 | ||
@@ -1120,6 +1571,13 @@ next: | |||
1120 | } | 1571 | } |
1121 | return intel_pt_walk_fup_tip(decoder); | 1572 | return intel_pt_walk_fup_tip(decoder); |
1122 | 1573 | ||
1574 | case INTEL_PT_TRACESTOP: | ||
1575 | decoder->pge = false; | ||
1576 | decoder->continuous_period = false; | ||
1577 | intel_pt_clear_tx_flags(decoder); | ||
1578 | decoder->have_tma = false; | ||
1579 | break; | ||
1580 | |||
1123 | case INTEL_PT_PSB: | 1581 | case INTEL_PT_PSB: |
1124 | intel_pt_clear_stack(&decoder->stack); | 1582 | intel_pt_clear_stack(&decoder->stack); |
1125 | err = intel_pt_walk_psbend(decoder); | 1583 | err = intel_pt_walk_psbend(decoder); |
@@ -1130,15 +1588,43 @@ next: | |||
1130 | break; | 1588 | break; |
1131 | 1589 | ||
1132 | case INTEL_PT_PIP: | 1590 | case INTEL_PT_PIP: |
1133 | decoder->cr3 = decoder->packet.payload; | 1591 | decoder->cr3 = decoder->packet.payload & (BIT63 - 1); |
1134 | break; | 1592 | break; |
1135 | 1593 | ||
1594 | case INTEL_PT_MTC: | ||
1595 | intel_pt_calc_mtc_timestamp(decoder); | ||
1596 | if (decoder->period_type != INTEL_PT_PERIOD_MTC) | ||
1597 | break; | ||
1598 | /* | ||
1599 | * Ensure that there has been an instruction since the | ||
1600 | * last MTC. | ||
1601 | */ | ||
1602 | if (!decoder->mtc_insn) | ||
1603 | break; | ||
1604 | decoder->mtc_insn = false; | ||
1605 | /* Ensure that there is a timestamp */ | ||
1606 | if (!decoder->timestamp) | ||
1607 | break; | ||
1608 | decoder->state.type = INTEL_PT_INSTRUCTION; | ||
1609 | decoder->state.from_ip = decoder->ip; | ||
1610 | decoder->state.to_ip = 0; | ||
1611 | decoder->mtc_insn = false; | ||
1612 | return 0; | ||
1613 | |||
1136 | case INTEL_PT_TSC: | 1614 | case INTEL_PT_TSC: |
1137 | intel_pt_calc_tsc_timestamp(decoder); | 1615 | intel_pt_calc_tsc_timestamp(decoder); |
1138 | break; | 1616 | break; |
1139 | 1617 | ||
1618 | case INTEL_PT_TMA: | ||
1619 | intel_pt_calc_tma(decoder); | ||
1620 | break; | ||
1621 | |||
1622 | case INTEL_PT_CYC: | ||
1623 | intel_pt_calc_cyc_timestamp(decoder); | ||
1624 | break; | ||
1625 | |||
1140 | case INTEL_PT_CBR: | 1626 | case INTEL_PT_CBR: |
1141 | decoder->cbr = decoder->packet.payload; | 1627 | intel_pt_calc_cbr(decoder); |
1142 | break; | 1628 | break; |
1143 | 1629 | ||
1144 | case INTEL_PT_MODE_EXEC: | 1630 | case INTEL_PT_MODE_EXEC: |
@@ -1160,6 +1646,8 @@ next: | |||
1160 | return intel_pt_bug(decoder); | 1646 | return intel_pt_bug(decoder); |
1161 | 1647 | ||
1162 | case INTEL_PT_PSBEND: | 1648 | case INTEL_PT_PSBEND: |
1649 | case INTEL_PT_VMCS: | ||
1650 | case INTEL_PT_MNT: | ||
1163 | case INTEL_PT_PAD: | 1651 | case INTEL_PT_PAD: |
1164 | break; | 1652 | break; |
1165 | 1653 | ||
@@ -1200,16 +1688,28 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) | |||
1200 | } | 1688 | } |
1201 | break; | 1689 | break; |
1202 | 1690 | ||
1691 | case INTEL_PT_MTC: | ||
1692 | intel_pt_calc_mtc_timestamp(decoder); | ||
1693 | break; | ||
1694 | |||
1203 | case INTEL_PT_TSC: | 1695 | case INTEL_PT_TSC: |
1204 | intel_pt_calc_tsc_timestamp(decoder); | 1696 | intel_pt_calc_tsc_timestamp(decoder); |
1205 | break; | 1697 | break; |
1206 | 1698 | ||
1699 | case INTEL_PT_TMA: | ||
1700 | intel_pt_calc_tma(decoder); | ||
1701 | break; | ||
1702 | |||
1703 | case INTEL_PT_CYC: | ||
1704 | intel_pt_calc_cyc_timestamp(decoder); | ||
1705 | break; | ||
1706 | |||
1207 | case INTEL_PT_CBR: | 1707 | case INTEL_PT_CBR: |
1208 | decoder->cbr = decoder->packet.payload; | 1708 | intel_pt_calc_cbr(decoder); |
1209 | break; | 1709 | break; |
1210 | 1710 | ||
1211 | case INTEL_PT_PIP: | 1711 | case INTEL_PT_PIP: |
1212 | decoder->cr3 = decoder->packet.payload; | 1712 | decoder->cr3 = decoder->packet.payload & (BIT63 - 1); |
1213 | break; | 1713 | break; |
1214 | 1714 | ||
1215 | case INTEL_PT_MODE_EXEC: | 1715 | case INTEL_PT_MODE_EXEC: |
@@ -1220,7 +1720,12 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) | |||
1220 | intel_pt_update_in_tx(decoder); | 1720 | intel_pt_update_in_tx(decoder); |
1221 | break; | 1721 | break; |
1222 | 1722 | ||
1723 | case INTEL_PT_TRACESTOP: | ||
1724 | decoder->pge = false; | ||
1725 | decoder->continuous_period = false; | ||
1726 | intel_pt_clear_tx_flags(decoder); | ||
1223 | case INTEL_PT_TNT: | 1727 | case INTEL_PT_TNT: |
1728 | decoder->have_tma = false; | ||
1224 | intel_pt_log("ERROR: Unexpected packet\n"); | 1729 | intel_pt_log("ERROR: Unexpected packet\n"); |
1225 | if (decoder->ip) | 1730 | if (decoder->ip) |
1226 | decoder->pkt_state = INTEL_PT_STATE_ERR4; | 1731 | decoder->pkt_state = INTEL_PT_STATE_ERR4; |
@@ -1238,6 +1743,8 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) | |||
1238 | return 0; | 1743 | return 0; |
1239 | 1744 | ||
1240 | case INTEL_PT_PSB: | 1745 | case INTEL_PT_PSB: |
1746 | case INTEL_PT_VMCS: | ||
1747 | case INTEL_PT_MNT: | ||
1241 | case INTEL_PT_PAD: | 1748 | case INTEL_PT_PAD: |
1242 | default: | 1749 | default: |
1243 | break; | 1750 | break; |
@@ -1280,16 +1787,28 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) | |||
1280 | intel_pt_set_last_ip(decoder); | 1787 | intel_pt_set_last_ip(decoder); |
1281 | break; | 1788 | break; |
1282 | 1789 | ||
1790 | case INTEL_PT_MTC: | ||
1791 | intel_pt_calc_mtc_timestamp(decoder); | ||
1792 | break; | ||
1793 | |||
1283 | case INTEL_PT_TSC: | 1794 | case INTEL_PT_TSC: |
1284 | intel_pt_calc_tsc_timestamp(decoder); | 1795 | intel_pt_calc_tsc_timestamp(decoder); |
1285 | break; | 1796 | break; |
1286 | 1797 | ||
1798 | case INTEL_PT_TMA: | ||
1799 | intel_pt_calc_tma(decoder); | ||
1800 | break; | ||
1801 | |||
1802 | case INTEL_PT_CYC: | ||
1803 | intel_pt_calc_cyc_timestamp(decoder); | ||
1804 | break; | ||
1805 | |||
1287 | case INTEL_PT_CBR: | 1806 | case INTEL_PT_CBR: |
1288 | decoder->cbr = decoder->packet.payload; | 1807 | intel_pt_calc_cbr(decoder); |
1289 | break; | 1808 | break; |
1290 | 1809 | ||
1291 | case INTEL_PT_PIP: | 1810 | case INTEL_PT_PIP: |
1292 | decoder->cr3 = decoder->packet.payload; | 1811 | decoder->cr3 = decoder->packet.payload & (BIT63 - 1); |
1293 | break; | 1812 | break; |
1294 | 1813 | ||
1295 | case INTEL_PT_MODE_EXEC: | 1814 | case INTEL_PT_MODE_EXEC: |
@@ -1306,6 +1825,13 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) | |||
1306 | case INTEL_PT_BAD: /* Does not happen */ | 1825 | case INTEL_PT_BAD: /* Does not happen */ |
1307 | return intel_pt_bug(decoder); | 1826 | return intel_pt_bug(decoder); |
1308 | 1827 | ||
1828 | case INTEL_PT_TRACESTOP: | ||
1829 | decoder->pge = false; | ||
1830 | decoder->continuous_period = false; | ||
1831 | intel_pt_clear_tx_flags(decoder); | ||
1832 | decoder->have_tma = false; | ||
1833 | break; | ||
1834 | |||
1309 | case INTEL_PT_PSB: | 1835 | case INTEL_PT_PSB: |
1310 | err = intel_pt_walk_psb(decoder); | 1836 | err = intel_pt_walk_psb(decoder); |
1311 | if (err) | 1837 | if (err) |
@@ -1319,6 +1845,8 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) | |||
1319 | 1845 | ||
1320 | case INTEL_PT_TNT: | 1846 | case INTEL_PT_TNT: |
1321 | case INTEL_PT_PSBEND: | 1847 | case INTEL_PT_PSBEND: |
1848 | case INTEL_PT_VMCS: | ||
1849 | case INTEL_PT_MNT: | ||
1322 | case INTEL_PT_PAD: | 1850 | case INTEL_PT_PAD: |
1323 | default: | 1851 | default: |
1324 | break; | 1852 | break; |
@@ -1529,6 +2057,7 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) | |||
1529 | decoder->state.timestamp = decoder->timestamp; | 2057 | decoder->state.timestamp = decoder->timestamp; |
1530 | decoder->state.est_timestamp = intel_pt_est_timestamp(decoder); | 2058 | decoder->state.est_timestamp = intel_pt_est_timestamp(decoder); |
1531 | decoder->state.cr3 = decoder->cr3; | 2059 | decoder->state.cr3 = decoder->cr3; |
2060 | decoder->state.tot_insn_cnt = decoder->tot_insn_cnt; | ||
1532 | 2061 | ||
1533 | if (err) | 2062 | if (err) |
1534 | decoder->state.from_ip = decoder->ip; | 2063 | decoder->state.from_ip = decoder->ip; |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h index 4c4880230cc9..02c38fec1c37 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h | |||
@@ -36,6 +36,7 @@ enum intel_pt_period_type { | |||
36 | INTEL_PT_PERIOD_NONE, | 36 | INTEL_PT_PERIOD_NONE, |
37 | INTEL_PT_PERIOD_INSTRUCTIONS, | 37 | INTEL_PT_PERIOD_INSTRUCTIONS, |
38 | INTEL_PT_PERIOD_TICKS, | 38 | INTEL_PT_PERIOD_TICKS, |
39 | INTEL_PT_PERIOD_MTC, | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | enum { | 42 | enum { |
@@ -58,6 +59,7 @@ struct intel_pt_state { | |||
58 | uint64_t from_ip; | 59 | uint64_t from_ip; |
59 | uint64_t to_ip; | 60 | uint64_t to_ip; |
60 | uint64_t cr3; | 61 | uint64_t cr3; |
62 | uint64_t tot_insn_cnt; | ||
61 | uint64_t timestamp; | 63 | uint64_t timestamp; |
62 | uint64_t est_timestamp; | 64 | uint64_t est_timestamp; |
63 | uint64_t trace_nr; | 65 | uint64_t trace_nr; |
@@ -86,6 +88,9 @@ struct intel_pt_params { | |||
86 | uint64_t period; | 88 | uint64_t period; |
87 | enum intel_pt_period_type period_type; | 89 | enum intel_pt_period_type period_type; |
88 | unsigned max_non_turbo_ratio; | 90 | unsigned max_non_turbo_ratio; |
91 | unsigned int mtc_period; | ||
92 | uint32_t tsc_ctc_ratio_n; | ||
93 | uint32_t tsc_ctc_ratio_d; | ||
89 | }; | 94 | }; |
90 | 95 | ||
91 | struct intel_pt_decoder; | 96 | struct intel_pt_decoder; |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c index 46980fc663ac..9e4eb8fcd559 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c | |||
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | #include "event.h" | 21 | #include "event.h" |
22 | 22 | ||
23 | #include <asm/insn.h> | 23 | #include "insn.h" |
24 | 24 | ||
25 | #include "inat.c" | 25 | #include "inat.c" |
26 | #include "insn.c" | 26 | #include "insn.c" |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c index 988c82c6652d..b1257c816310 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c | |||
@@ -24,6 +24,8 @@ | |||
24 | 24 | ||
25 | #define BIT63 ((uint64_t)1 << 63) | 25 | #define BIT63 ((uint64_t)1 << 63) |
26 | 26 | ||
27 | #define NR_FLAG BIT63 | ||
28 | |||
27 | #if __BYTE_ORDER == __BIG_ENDIAN | 29 | #if __BYTE_ORDER == __BIG_ENDIAN |
28 | #define le16_to_cpu bswap_16 | 30 | #define le16_to_cpu bswap_16 |
29 | #define le32_to_cpu bswap_32 | 31 | #define le32_to_cpu bswap_32 |
@@ -46,15 +48,21 @@ static const char * const packet_name[] = { | |||
46 | [INTEL_PT_TIP_PGD] = "TIP.PGD", | 48 | [INTEL_PT_TIP_PGD] = "TIP.PGD", |
47 | [INTEL_PT_TIP_PGE] = "TIP.PGE", | 49 | [INTEL_PT_TIP_PGE] = "TIP.PGE", |
48 | [INTEL_PT_TSC] = "TSC", | 50 | [INTEL_PT_TSC] = "TSC", |
51 | [INTEL_PT_TMA] = "TMA", | ||
49 | [INTEL_PT_MODE_EXEC] = "MODE.Exec", | 52 | [INTEL_PT_MODE_EXEC] = "MODE.Exec", |
50 | [INTEL_PT_MODE_TSX] = "MODE.TSX", | 53 | [INTEL_PT_MODE_TSX] = "MODE.TSX", |
54 | [INTEL_PT_MTC] = "MTC", | ||
51 | [INTEL_PT_TIP] = "TIP", | 55 | [INTEL_PT_TIP] = "TIP", |
52 | [INTEL_PT_FUP] = "FUP", | 56 | [INTEL_PT_FUP] = "FUP", |
57 | [INTEL_PT_CYC] = "CYC", | ||
58 | [INTEL_PT_VMCS] = "VMCS", | ||
53 | [INTEL_PT_PSB] = "PSB", | 59 | [INTEL_PT_PSB] = "PSB", |
54 | [INTEL_PT_PSBEND] = "PSBEND", | 60 | [INTEL_PT_PSBEND] = "PSBEND", |
55 | [INTEL_PT_CBR] = "CBR", | 61 | [INTEL_PT_CBR] = "CBR", |
62 | [INTEL_PT_TRACESTOP] = "TraceSTOP", | ||
56 | [INTEL_PT_PIP] = "PIP", | 63 | [INTEL_PT_PIP] = "PIP", |
57 | [INTEL_PT_OVF] = "OVF", | 64 | [INTEL_PT_OVF] = "OVF", |
65 | [INTEL_PT_MNT] = "MNT", | ||
58 | }; | 66 | }; |
59 | 67 | ||
60 | const char *intel_pt_pkt_name(enum intel_pt_pkt_type type) | 68 | const char *intel_pt_pkt_name(enum intel_pt_pkt_type type) |
@@ -96,10 +104,18 @@ static int intel_pt_get_pip(const unsigned char *buf, size_t len, | |||
96 | packet->type = INTEL_PT_PIP; | 104 | packet->type = INTEL_PT_PIP; |
97 | memcpy_le64(&payload, buf + 2, 6); | 105 | memcpy_le64(&payload, buf + 2, 6); |
98 | packet->payload = payload >> 1; | 106 | packet->payload = payload >> 1; |
107 | if (payload & 1) | ||
108 | packet->payload |= NR_FLAG; | ||
99 | 109 | ||
100 | return 8; | 110 | return 8; |
101 | } | 111 | } |
102 | 112 | ||
113 | static int intel_pt_get_tracestop(struct intel_pt_pkt *packet) | ||
114 | { | ||
115 | packet->type = INTEL_PT_TRACESTOP; | ||
116 | return 2; | ||
117 | } | ||
118 | |||
103 | static int intel_pt_get_cbr(const unsigned char *buf, size_t len, | 119 | static int intel_pt_get_cbr(const unsigned char *buf, size_t len, |
104 | struct intel_pt_pkt *packet) | 120 | struct intel_pt_pkt *packet) |
105 | { | 121 | { |
@@ -110,6 +126,24 @@ static int intel_pt_get_cbr(const unsigned char *buf, size_t len, | |||
110 | return 4; | 126 | return 4; |
111 | } | 127 | } |
112 | 128 | ||
129 | static int intel_pt_get_vmcs(const unsigned char *buf, size_t len, | ||
130 | struct intel_pt_pkt *packet) | ||
131 | { | ||
132 | unsigned int count = (52 - 5) >> 3; | ||
133 | |||
134 | if (count < 1 || count > 7) | ||
135 | return INTEL_PT_BAD_PACKET; | ||
136 | |||
137 | if (len < count + 2) | ||
138 | return INTEL_PT_NEED_MORE_BYTES; | ||
139 | |||
140 | packet->type = INTEL_PT_VMCS; | ||
141 | packet->count = count; | ||
142 | memcpy_le64(&packet->payload, buf + 2, count); | ||
143 | |||
144 | return count + 2; | ||
145 | } | ||
146 | |||
113 | static int intel_pt_get_ovf(struct intel_pt_pkt *packet) | 147 | static int intel_pt_get_ovf(struct intel_pt_pkt *packet) |
114 | { | 148 | { |
115 | packet->type = INTEL_PT_OVF; | 149 | packet->type = INTEL_PT_OVF; |
@@ -139,12 +173,49 @@ static int intel_pt_get_psbend(struct intel_pt_pkt *packet) | |||
139 | return 2; | 173 | return 2; |
140 | } | 174 | } |
141 | 175 | ||
176 | static int intel_pt_get_tma(const unsigned char *buf, size_t len, | ||
177 | struct intel_pt_pkt *packet) | ||
178 | { | ||
179 | if (len < 7) | ||
180 | return INTEL_PT_NEED_MORE_BYTES; | ||
181 | |||
182 | packet->type = INTEL_PT_TMA; | ||
183 | packet->payload = buf[2] | (buf[3] << 8); | ||
184 | packet->count = buf[5] | ((buf[6] & BIT(0)) << 8); | ||
185 | return 7; | ||
186 | } | ||
187 | |||
142 | static int intel_pt_get_pad(struct intel_pt_pkt *packet) | 188 | static int intel_pt_get_pad(struct intel_pt_pkt *packet) |
143 | { | 189 | { |
144 | packet->type = INTEL_PT_PAD; | 190 | packet->type = INTEL_PT_PAD; |
145 | return 1; | 191 | return 1; |
146 | } | 192 | } |
147 | 193 | ||
194 | static int intel_pt_get_mnt(const unsigned char *buf, size_t len, | ||
195 | struct intel_pt_pkt *packet) | ||
196 | { | ||
197 | if (len < 11) | ||
198 | return INTEL_PT_NEED_MORE_BYTES; | ||
199 | packet->type = INTEL_PT_MNT; | ||
200 | memcpy_le64(&packet->payload, buf + 3, 8); | ||
201 | return 11 | ||
202 | ; | ||
203 | } | ||
204 | |||
205 | static int intel_pt_get_3byte(const unsigned char *buf, size_t len, | ||
206 | struct intel_pt_pkt *packet) | ||
207 | { | ||
208 | if (len < 3) | ||
209 | return INTEL_PT_NEED_MORE_BYTES; | ||
210 | |||
211 | switch (buf[2]) { | ||
212 | case 0x88: /* MNT */ | ||
213 | return intel_pt_get_mnt(buf, len, packet); | ||
214 | default: | ||
215 | return INTEL_PT_BAD_PACKET; | ||
216 | } | ||
217 | } | ||
218 | |||
148 | static int intel_pt_get_ext(const unsigned char *buf, size_t len, | 219 | static int intel_pt_get_ext(const unsigned char *buf, size_t len, |
149 | struct intel_pt_pkt *packet) | 220 | struct intel_pt_pkt *packet) |
150 | { | 221 | { |
@@ -156,14 +227,22 @@ static int intel_pt_get_ext(const unsigned char *buf, size_t len, | |||
156 | return intel_pt_get_long_tnt(buf, len, packet); | 227 | return intel_pt_get_long_tnt(buf, len, packet); |
157 | case 0x43: /* PIP */ | 228 | case 0x43: /* PIP */ |
158 | return intel_pt_get_pip(buf, len, packet); | 229 | return intel_pt_get_pip(buf, len, packet); |
230 | case 0x83: /* TraceStop */ | ||
231 | return intel_pt_get_tracestop(packet); | ||
159 | case 0x03: /* CBR */ | 232 | case 0x03: /* CBR */ |
160 | return intel_pt_get_cbr(buf, len, packet); | 233 | return intel_pt_get_cbr(buf, len, packet); |
234 | case 0xc8: /* VMCS */ | ||
235 | return intel_pt_get_vmcs(buf, len, packet); | ||
161 | case 0xf3: /* OVF */ | 236 | case 0xf3: /* OVF */ |
162 | return intel_pt_get_ovf(packet); | 237 | return intel_pt_get_ovf(packet); |
163 | case 0x82: /* PSB */ | 238 | case 0x82: /* PSB */ |
164 | return intel_pt_get_psb(buf, len, packet); | 239 | return intel_pt_get_psb(buf, len, packet); |
165 | case 0x23: /* PSBEND */ | 240 | case 0x23: /* PSBEND */ |
166 | return intel_pt_get_psbend(packet); | 241 | return intel_pt_get_psbend(packet); |
242 | case 0x73: /* TMA */ | ||
243 | return intel_pt_get_tma(buf, len, packet); | ||
244 | case 0xC3: /* 3-byte header */ | ||
245 | return intel_pt_get_3byte(buf, len, packet); | ||
167 | default: | 246 | default: |
168 | return INTEL_PT_BAD_PACKET; | 247 | return INTEL_PT_BAD_PACKET; |
169 | } | 248 | } |
@@ -187,6 +266,28 @@ static int intel_pt_get_short_tnt(unsigned int byte, | |||
187 | return 1; | 266 | return 1; |
188 | } | 267 | } |
189 | 268 | ||
269 | static int intel_pt_get_cyc(unsigned int byte, const unsigned char *buf, | ||
270 | size_t len, struct intel_pt_pkt *packet) | ||
271 | { | ||
272 | unsigned int offs = 1, shift; | ||
273 | uint64_t payload = byte >> 3; | ||
274 | |||
275 | byte >>= 2; | ||
276 | len -= 1; | ||
277 | for (shift = 5; byte & 1; shift += 7) { | ||
278 | if (offs > 9) | ||
279 | return INTEL_PT_BAD_PACKET; | ||
280 | if (len < offs) | ||
281 | return INTEL_PT_NEED_MORE_BYTES; | ||
282 | byte = buf[offs++]; | ||
283 | payload |= (byte >> 1) << shift; | ||
284 | } | ||
285 | |||
286 | packet->type = INTEL_PT_CYC; | ||
287 | packet->payload = payload; | ||
288 | return offs; | ||
289 | } | ||
290 | |||
190 | static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, | 291 | static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, |
191 | const unsigned char *buf, size_t len, | 292 | const unsigned char *buf, size_t len, |
192 | struct intel_pt_pkt *packet) | 293 | struct intel_pt_pkt *packet) |
@@ -269,6 +370,16 @@ static int intel_pt_get_tsc(const unsigned char *buf, size_t len, | |||
269 | return 8; | 370 | return 8; |
270 | } | 371 | } |
271 | 372 | ||
373 | static int intel_pt_get_mtc(const unsigned char *buf, size_t len, | ||
374 | struct intel_pt_pkt *packet) | ||
375 | { | ||
376 | if (len < 2) | ||
377 | return INTEL_PT_NEED_MORE_BYTES; | ||
378 | packet->type = INTEL_PT_MTC; | ||
379 | packet->payload = buf[1]; | ||
380 | return 2; | ||
381 | } | ||
382 | |||
272 | static int intel_pt_do_get_packet(const unsigned char *buf, size_t len, | 383 | static int intel_pt_do_get_packet(const unsigned char *buf, size_t len, |
273 | struct intel_pt_pkt *packet) | 384 | struct intel_pt_pkt *packet) |
274 | { | 385 | { |
@@ -288,6 +399,9 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len, | |||
288 | return intel_pt_get_short_tnt(byte, packet); | 399 | return intel_pt_get_short_tnt(byte, packet); |
289 | } | 400 | } |
290 | 401 | ||
402 | if ((byte & 2)) | ||
403 | return intel_pt_get_cyc(byte, buf, len, packet); | ||
404 | |||
291 | switch (byte & 0x1f) { | 405 | switch (byte & 0x1f) { |
292 | case 0x0D: | 406 | case 0x0D: |
293 | return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet); | 407 | return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet); |
@@ -305,6 +419,8 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len, | |||
305 | return intel_pt_get_mode(buf, len, packet); | 419 | return intel_pt_get_mode(buf, len, packet); |
306 | case 0x19: | 420 | case 0x19: |
307 | return intel_pt_get_tsc(buf, len, packet); | 421 | return intel_pt_get_tsc(buf, len, packet); |
422 | case 0x59: | ||
423 | return intel_pt_get_mtc(buf, len, packet); | ||
308 | default: | 424 | default: |
309 | return INTEL_PT_BAD_PACKET; | 425 | return INTEL_PT_BAD_PACKET; |
310 | } | 426 | } |
@@ -329,7 +445,7 @@ int intel_pt_get_packet(const unsigned char *buf, size_t len, | |||
329 | int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, | 445 | int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, |
330 | size_t buf_len) | 446 | size_t buf_len) |
331 | { | 447 | { |
332 | int ret, i; | 448 | int ret, i, nr; |
333 | unsigned long long payload = packet->payload; | 449 | unsigned long long payload = packet->payload; |
334 | const char *name = intel_pt_pkt_name(packet->type); | 450 | const char *name = intel_pt_pkt_name(packet->type); |
335 | 451 | ||
@@ -338,6 +454,7 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, | |||
338 | case INTEL_PT_PAD: | 454 | case INTEL_PT_PAD: |
339 | case INTEL_PT_PSB: | 455 | case INTEL_PT_PSB: |
340 | case INTEL_PT_PSBEND: | 456 | case INTEL_PT_PSBEND: |
457 | case INTEL_PT_TRACESTOP: | ||
341 | case INTEL_PT_OVF: | 458 | case INTEL_PT_OVF: |
342 | return snprintf(buf, buf_len, "%s", name); | 459 | return snprintf(buf, buf_len, "%s", name); |
343 | case INTEL_PT_TNT: { | 460 | case INTEL_PT_TNT: { |
@@ -371,17 +488,16 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, | |||
371 | case INTEL_PT_FUP: | 488 | case INTEL_PT_FUP: |
372 | if (!(packet->count)) | 489 | if (!(packet->count)) |
373 | return snprintf(buf, buf_len, "%s no ip", name); | 490 | return snprintf(buf, buf_len, "%s no ip", name); |
491 | case INTEL_PT_CYC: | ||
492 | case INTEL_PT_VMCS: | ||
493 | case INTEL_PT_MTC: | ||
494 | case INTEL_PT_MNT: | ||
374 | case INTEL_PT_CBR: | 495 | case INTEL_PT_CBR: |
375 | return snprintf(buf, buf_len, "%s 0x%llx", name, payload); | ||
376 | case INTEL_PT_TSC: | 496 | case INTEL_PT_TSC: |
377 | if (packet->count) | 497 | return snprintf(buf, buf_len, "%s 0x%llx", name, payload); |
378 | return snprintf(buf, buf_len, | 498 | case INTEL_PT_TMA: |
379 | "%s 0x%llx CTC 0x%x FC 0x%x", | 499 | return snprintf(buf, buf_len, "%s CTC 0x%x FC 0x%x", name, |
380 | name, payload, packet->count & 0xffff, | 500 | (unsigned)payload, packet->count); |
381 | (packet->count >> 16) & 0x1ff); | ||
382 | else | ||
383 | return snprintf(buf, buf_len, "%s 0x%llx", | ||
384 | name, payload); | ||
385 | case INTEL_PT_MODE_EXEC: | 501 | case INTEL_PT_MODE_EXEC: |
386 | return snprintf(buf, buf_len, "%s %lld", name, payload); | 502 | return snprintf(buf, buf_len, "%s %lld", name, payload); |
387 | case INTEL_PT_MODE_TSX: | 503 | case INTEL_PT_MODE_TSX: |
@@ -389,8 +505,10 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, | |||
389 | name, (unsigned)(payload >> 1) & 1, | 505 | name, (unsigned)(payload >> 1) & 1, |
390 | (unsigned)payload & 1); | 506 | (unsigned)payload & 1); |
391 | case INTEL_PT_PIP: | 507 | case INTEL_PT_PIP: |
392 | ret = snprintf(buf, buf_len, "%s 0x%llx", | 508 | nr = packet->payload & NR_FLAG ? 1 : 0; |
393 | name, payload); | 509 | payload &= ~NR_FLAG; |
510 | ret = snprintf(buf, buf_len, "%s 0x%llx (NR=%d)", | ||
511 | name, payload, nr); | ||
394 | return ret; | 512 | return ret; |
395 | default: | 513 | default: |
396 | break; | 514 | break; |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h index 53404fa942b3..781bb79883bd 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h | |||
@@ -37,15 +37,21 @@ enum intel_pt_pkt_type { | |||
37 | INTEL_PT_TIP_PGD, | 37 | INTEL_PT_TIP_PGD, |
38 | INTEL_PT_TIP_PGE, | 38 | INTEL_PT_TIP_PGE, |
39 | INTEL_PT_TSC, | 39 | INTEL_PT_TSC, |
40 | INTEL_PT_TMA, | ||
40 | INTEL_PT_MODE_EXEC, | 41 | INTEL_PT_MODE_EXEC, |
41 | INTEL_PT_MODE_TSX, | 42 | INTEL_PT_MODE_TSX, |
43 | INTEL_PT_MTC, | ||
42 | INTEL_PT_TIP, | 44 | INTEL_PT_TIP, |
43 | INTEL_PT_FUP, | 45 | INTEL_PT_FUP, |
46 | INTEL_PT_CYC, | ||
47 | INTEL_PT_VMCS, | ||
44 | INTEL_PT_PSB, | 48 | INTEL_PT_PSB, |
45 | INTEL_PT_PSBEND, | 49 | INTEL_PT_PSBEND, |
46 | INTEL_PT_CBR, | 50 | INTEL_PT_CBR, |
51 | INTEL_PT_TRACESTOP, | ||
47 | INTEL_PT_PIP, | 52 | INTEL_PT_PIP, |
48 | INTEL_PT_OVF, | 53 | INTEL_PT_OVF, |
54 | INTEL_PT_MNT, | ||
49 | }; | 55 | }; |
50 | 56 | ||
51 | struct intel_pt_pkt { | 57 | struct intel_pt_pkt { |
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index a5acd2fe2447..bb41c20e6005 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c | |||
@@ -91,6 +91,11 @@ struct intel_pt { | |||
91 | bool synth_needs_swap; | 91 | bool synth_needs_swap; |
92 | 92 | ||
93 | u64 tsc_bit; | 93 | u64 tsc_bit; |
94 | u64 mtc_bit; | ||
95 | u64 mtc_freq_bits; | ||
96 | u32 tsc_ctc_ratio_n; | ||
97 | u32 tsc_ctc_ratio_d; | ||
98 | u64 cyc_bit; | ||
94 | u64 noretcomp_bit; | 99 | u64 noretcomp_bit; |
95 | unsigned max_non_turbo_ratio; | 100 | unsigned max_non_turbo_ratio; |
96 | }; | 101 | }; |
@@ -126,6 +131,7 @@ struct intel_pt_queue { | |||
126 | u64 timestamp; | 131 | u64 timestamp; |
127 | u32 flags; | 132 | u32 flags; |
128 | u16 insn_len; | 133 | u16 insn_len; |
134 | u64 last_insn_cnt; | ||
129 | }; | 135 | }; |
130 | 136 | ||
131 | static void intel_pt_dump(struct intel_pt *pt __maybe_unused, | 137 | static void intel_pt_dump(struct intel_pt *pt __maybe_unused, |
@@ -567,6 +573,25 @@ static bool intel_pt_return_compression(struct intel_pt *pt) | |||
567 | return true; | 573 | return true; |
568 | } | 574 | } |
569 | 575 | ||
576 | static unsigned int intel_pt_mtc_period(struct intel_pt *pt) | ||
577 | { | ||
578 | struct perf_evsel *evsel; | ||
579 | unsigned int shift; | ||
580 | u64 config; | ||
581 | |||
582 | if (!pt->mtc_freq_bits) | ||
583 | return 0; | ||
584 | |||
585 | for (shift = 0, config = pt->mtc_freq_bits; !(config & 1); shift++) | ||
586 | config >>= 1; | ||
587 | |||
588 | evlist__for_each(pt->session->evlist, evsel) { | ||
589 | if (intel_pt_get_config(pt, &evsel->attr, &config)) | ||
590 | return (config & pt->mtc_freq_bits) >> shift; | ||
591 | } | ||
592 | return 0; | ||
593 | } | ||
594 | |||
570 | static bool intel_pt_timeless_decoding(struct intel_pt *pt) | 595 | static bool intel_pt_timeless_decoding(struct intel_pt *pt) |
571 | { | 596 | { |
572 | struct perf_evsel *evsel; | 597 | struct perf_evsel *evsel; |
@@ -667,6 +692,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt, | |||
667 | params.data = ptq; | 692 | params.data = ptq; |
668 | params.return_compression = intel_pt_return_compression(pt); | 693 | params.return_compression = intel_pt_return_compression(pt); |
669 | params.max_non_turbo_ratio = pt->max_non_turbo_ratio; | 694 | params.max_non_turbo_ratio = pt->max_non_turbo_ratio; |
695 | params.mtc_period = intel_pt_mtc_period(pt); | ||
696 | params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n; | ||
697 | params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d; | ||
670 | 698 | ||
671 | if (pt->synth_opts.instructions) { | 699 | if (pt->synth_opts.instructions) { |
672 | if (pt->synth_opts.period) { | 700 | if (pt->synth_opts.period) { |
@@ -920,11 +948,13 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) | |||
920 | sample.addr = ptq->state->to_ip; | 948 | sample.addr = ptq->state->to_ip; |
921 | sample.id = ptq->pt->instructions_id; | 949 | sample.id = ptq->pt->instructions_id; |
922 | sample.stream_id = ptq->pt->instructions_id; | 950 | sample.stream_id = ptq->pt->instructions_id; |
923 | sample.period = ptq->pt->instructions_sample_period; | 951 | sample.period = ptq->state->tot_insn_cnt - ptq->last_insn_cnt; |
924 | sample.cpu = ptq->cpu; | 952 | sample.cpu = ptq->cpu; |
925 | sample.flags = ptq->flags; | 953 | sample.flags = ptq->flags; |
926 | sample.insn_len = ptq->insn_len; | 954 | sample.insn_len = ptq->insn_len; |
927 | 955 | ||
956 | ptq->last_insn_cnt = ptq->state->tot_insn_cnt; | ||
957 | |||
928 | if (pt->synth_opts.callchain) { | 958 | if (pt->synth_opts.callchain) { |
929 | thread_stack__sample(ptq->thread, ptq->chain, | 959 | thread_stack__sample(ptq->thread, ptq->chain, |
930 | pt->synth_opts.callchain_sz, sample.ip); | 960 | pt->synth_opts.callchain_sz, sample.ip); |
@@ -1748,16 +1778,20 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist) | |||
1748 | } | 1778 | } |
1749 | 1779 | ||
1750 | static const char * const intel_pt_info_fmts[] = { | 1780 | static const char * const intel_pt_info_fmts[] = { |
1751 | [INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n", | 1781 | [INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n", |
1752 | [INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n", | 1782 | [INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n", |
1753 | [INTEL_PT_TIME_MULT] = " Time Muliplier %"PRIu64"\n", | 1783 | [INTEL_PT_TIME_MULT] = " Time Muliplier %"PRIu64"\n", |
1754 | [INTEL_PT_TIME_ZERO] = " Time Zero %"PRIu64"\n", | 1784 | [INTEL_PT_TIME_ZERO] = " Time Zero %"PRIu64"\n", |
1755 | [INTEL_PT_CAP_USER_TIME_ZERO] = " Cap Time Zero %"PRId64"\n", | 1785 | [INTEL_PT_CAP_USER_TIME_ZERO] = " Cap Time Zero %"PRId64"\n", |
1756 | [INTEL_PT_TSC_BIT] = " TSC bit %#"PRIx64"\n", | 1786 | [INTEL_PT_TSC_BIT] = " TSC bit %#"PRIx64"\n", |
1757 | [INTEL_PT_NORETCOMP_BIT] = " NoRETComp bit %#"PRIx64"\n", | 1787 | [INTEL_PT_NORETCOMP_BIT] = " NoRETComp bit %#"PRIx64"\n", |
1758 | [INTEL_PT_HAVE_SCHED_SWITCH] = " Have sched_switch %"PRId64"\n", | 1788 | [INTEL_PT_HAVE_SCHED_SWITCH] = " Have sched_switch %"PRId64"\n", |
1759 | [INTEL_PT_SNAPSHOT_MODE] = " Snapshot mode %"PRId64"\n", | 1789 | [INTEL_PT_SNAPSHOT_MODE] = " Snapshot mode %"PRId64"\n", |
1760 | [INTEL_PT_PER_CPU_MMAPS] = " Per-cpu maps %"PRId64"\n", | 1790 | [INTEL_PT_PER_CPU_MMAPS] = " Per-cpu maps %"PRId64"\n", |
1791 | [INTEL_PT_MTC_BIT] = " MTC bit %#"PRIx64"\n", | ||
1792 | [INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n", | ||
1793 | [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n", | ||
1794 | [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n", | ||
1761 | }; | 1795 | }; |
1762 | 1796 | ||
1763 | static void intel_pt_print_info(u64 *arr, int start, int finish) | 1797 | static void intel_pt_print_info(u64 *arr, int start, int finish) |
@@ -1809,6 +1843,17 @@ int intel_pt_process_auxtrace_info(union perf_event *event, | |||
1809 | intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE, | 1843 | intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE, |
1810 | INTEL_PT_PER_CPU_MMAPS); | 1844 | INTEL_PT_PER_CPU_MMAPS); |
1811 | 1845 | ||
1846 | if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) + | ||
1847 | (sizeof(u64) * INTEL_PT_CYC_BIT)) { | ||
1848 | pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT]; | ||
1849 | pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS]; | ||
1850 | pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N]; | ||
1851 | pt->tsc_ctc_ratio_d = auxtrace_info->priv[INTEL_PT_TSC_CTC_D]; | ||
1852 | pt->cyc_bit = auxtrace_info->priv[INTEL_PT_CYC_BIT]; | ||
1853 | intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_MTC_BIT, | ||
1854 | INTEL_PT_CYC_BIT); | ||
1855 | } | ||
1856 | |||
1812 | pt->timeless_decoding = intel_pt_timeless_decoding(pt); | 1857 | pt->timeless_decoding = intel_pt_timeless_decoding(pt); |
1813 | pt->have_tsc = intel_pt_have_tsc(pt); | 1858 | pt->have_tsc = intel_pt_have_tsc(pt); |
1814 | pt->sampling_mode = false; | 1859 | pt->sampling_mode = false; |
diff --git a/tools/perf/util/intel-pt.h b/tools/perf/util/intel-pt.h index a1bfe93473ba..0065949df693 100644 --- a/tools/perf/util/intel-pt.h +++ b/tools/perf/util/intel-pt.h | |||
@@ -29,6 +29,11 @@ enum { | |||
29 | INTEL_PT_HAVE_SCHED_SWITCH, | 29 | INTEL_PT_HAVE_SCHED_SWITCH, |
30 | INTEL_PT_SNAPSHOT_MODE, | 30 | INTEL_PT_SNAPSHOT_MODE, |
31 | INTEL_PT_PER_CPU_MMAPS, | 31 | INTEL_PT_PER_CPU_MMAPS, |
32 | INTEL_PT_MTC_BIT, | ||
33 | INTEL_PT_MTC_FREQ_BITS, | ||
34 | INTEL_PT_TSC_CTC_N, | ||
35 | INTEL_PT_TSC_CTC_D, | ||
36 | INTEL_PT_CYC_BIT, | ||
32 | INTEL_PT_AUXTRACE_PRIV_MAX, | 37 | INTEL_PT_AUXTRACE_PRIV_MAX, |
33 | }; | 38 | }; |
34 | 39 | ||
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c index 52be201b9b25..b1b9e2385f4b 100644 --- a/tools/perf/util/ordered-events.c +++ b/tools/perf/util/ordered-events.c | |||
@@ -220,6 +220,9 @@ static int __ordered_events__flush(struct ordered_events *oe) | |||
220 | else if (last_ts <= limit) | 220 | else if (last_ts <= limit) |
221 | oe->last = list_entry(head->prev, struct ordered_event, list); | 221 | oe->last = list_entry(head->prev, struct ordered_event, list); |
222 | 222 | ||
223 | if (show_progress) | ||
224 | ui_progress__finish(); | ||
225 | |||
223 | return 0; | 226 | return 0; |
224 | } | 227 | } |
225 | 228 | ||
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index f07374bc9c5a..eb5f18b75402 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -515,7 +515,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp, | |||
515 | if (ret < 0) | 515 | if (ret < 0) |
516 | goto error; | 516 | goto error; |
517 | addr += stext; | 517 | addr += stext; |
518 | } else { | 518 | } else if (tp->symbol) { |
519 | addr = kernel_get_symbol_address_by_name(tp->symbol, false); | 519 | addr = kernel_get_symbol_address_by_name(tp->symbol, false); |
520 | if (addr == 0) | 520 | if (addr == 0) |
521 | goto error; | 521 | goto error; |
@@ -1194,15 +1194,37 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) | |||
1194 | *ptr++ = '\0'; | 1194 | *ptr++ = '\0'; |
1195 | } | 1195 | } |
1196 | 1196 | ||
1197 | tmp = strdup(arg); | 1197 | if (arg[0] == '\0') |
1198 | if (tmp == NULL) | 1198 | tmp = NULL; |
1199 | return -ENOMEM; | 1199 | else { |
1200 | tmp = strdup(arg); | ||
1201 | if (tmp == NULL) | ||
1202 | return -ENOMEM; | ||
1203 | } | ||
1200 | 1204 | ||
1201 | if (file_spec) | 1205 | if (file_spec) |
1202 | pp->file = tmp; | 1206 | pp->file = tmp; |
1203 | else | 1207 | else { |
1204 | pp->function = tmp; | 1208 | pp->function = tmp; |
1205 | 1209 | ||
1210 | /* | ||
1211 | * Keep pp->function even if this is absolute address, | ||
1212 | * so it can mark whether abs_address is valid. | ||
1213 | * Which make 'perf probe lib.bin 0x0' possible. | ||
1214 | * | ||
1215 | * Note that checking length of tmp is not needed | ||
1216 | * because when we access tmp[1] we know tmp[0] is '0', | ||
1217 | * so tmp[1] should always valid (but could be '\0'). | ||
1218 | */ | ||
1219 | if (tmp && !strncmp(tmp, "0x", 2)) { | ||
1220 | pp->abs_address = strtoul(pp->function, &tmp, 0); | ||
1221 | if (*tmp != '\0') { | ||
1222 | semantic_error("Invalid absolute address.\n"); | ||
1223 | return -EINVAL; | ||
1224 | } | ||
1225 | } | ||
1226 | } | ||
1227 | |||
1206 | /* Parse other options */ | 1228 | /* Parse other options */ |
1207 | while (ptr) { | 1229 | while (ptr) { |
1208 | arg = ptr; | 1230 | arg = ptr; |
@@ -1519,9 +1541,31 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev) | |||
1519 | } else | 1541 | } else |
1520 | p = argv[1]; | 1542 | p = argv[1]; |
1521 | fmt1_str = strtok_r(p, "+", &fmt); | 1543 | fmt1_str = strtok_r(p, "+", &fmt); |
1522 | if (fmt1_str[0] == '0') /* only the address started with 0x */ | 1544 | /* only the address started with 0x */ |
1523 | tp->address = strtoul(fmt1_str, NULL, 0); | 1545 | if (fmt1_str[0] == '0') { |
1524 | else { | 1546 | /* |
1547 | * Fix a special case: | ||
1548 | * if address == 0, kernel reports something like: | ||
1549 | * p:probe_libc/abs_0 /lib/libc-2.18.so:0x (null) arg1=%ax | ||
1550 | * Newer kernel may fix that, but we want to | ||
1551 | * support old kernel also. | ||
1552 | */ | ||
1553 | if (strcmp(fmt1_str, "0x") == 0) { | ||
1554 | if (!argv[2] || strcmp(argv[2], "(null)")) { | ||
1555 | ret = -EINVAL; | ||
1556 | goto out; | ||
1557 | } | ||
1558 | tp->address = 0; | ||
1559 | |||
1560 | free(argv[2]); | ||
1561 | for (i = 2; argv[i + 1] != NULL; i++) | ||
1562 | argv[i] = argv[i + 1]; | ||
1563 | |||
1564 | argv[i] = NULL; | ||
1565 | argc -= 1; | ||
1566 | } else | ||
1567 | tp->address = strtoul(fmt1_str, NULL, 0); | ||
1568 | } else { | ||
1525 | /* Only the symbol-based probe has offset */ | 1569 | /* Only the symbol-based probe has offset */ |
1526 | tp->symbol = strdup(fmt1_str); | 1570 | tp->symbol = strdup(fmt1_str); |
1527 | if (tp->symbol == NULL) { | 1571 | if (tp->symbol == NULL) { |
@@ -1778,14 +1822,29 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev) | |||
1778 | if (len <= 0) | 1822 | if (len <= 0) |
1779 | goto error; | 1823 | goto error; |
1780 | 1824 | ||
1781 | /* Uprobes must have tp->address and tp->module */ | 1825 | /* Uprobes must have tp->module */ |
1782 | if (tev->uprobes && (!tp->address || !tp->module)) | 1826 | if (tev->uprobes && !tp->module) |
1783 | goto error; | 1827 | goto error; |
1828 | /* | ||
1829 | * If tp->address == 0, then this point must be a | ||
1830 | * absolute address uprobe. | ||
1831 | * try_to_find_absolute_address() should have made | ||
1832 | * tp->symbol to "0x0". | ||
1833 | */ | ||
1834 | if (tev->uprobes && !tp->address) { | ||
1835 | if (!tp->symbol || strcmp(tp->symbol, "0x0")) | ||
1836 | goto error; | ||
1837 | } | ||
1784 | 1838 | ||
1785 | /* Use the tp->address for uprobes */ | 1839 | /* Use the tp->address for uprobes */ |
1786 | if (tev->uprobes) | 1840 | if (tev->uprobes) |
1787 | ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx", | 1841 | ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx", |
1788 | tp->module, tp->address); | 1842 | tp->module, tp->address); |
1843 | else if (!strncmp(tp->symbol, "0x", 2)) | ||
1844 | /* Absolute address. See try_to_find_absolute_address() */ | ||
1845 | ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s0x%lx", | ||
1846 | tp->module ?: "", tp->module ? ":" : "", | ||
1847 | tp->address); | ||
1789 | else | 1848 | else |
1790 | ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu", | 1849 | ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu", |
1791 | tp->module ?: "", tp->module ? ":" : "", | 1850 | tp->module ?: "", tp->module ? ":" : "", |
@@ -1815,17 +1874,17 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp, | |||
1815 | { | 1874 | { |
1816 | struct symbol *sym = NULL; | 1875 | struct symbol *sym = NULL; |
1817 | struct map *map; | 1876 | struct map *map; |
1818 | u64 addr; | 1877 | u64 addr = tp->address; |
1819 | int ret = -ENOENT; | 1878 | int ret = -ENOENT; |
1820 | 1879 | ||
1821 | if (!is_kprobe) { | 1880 | if (!is_kprobe) { |
1822 | map = dso__new_map(tp->module); | 1881 | map = dso__new_map(tp->module); |
1823 | if (!map) | 1882 | if (!map) |
1824 | goto out; | 1883 | goto out; |
1825 | addr = tp->address; | ||
1826 | sym = map__find_symbol(map, addr, NULL); | 1884 | sym = map__find_symbol(map, addr, NULL); |
1827 | } else { | 1885 | } else { |
1828 | addr = kernel_get_symbol_address_by_name(tp->symbol, true); | 1886 | if (tp->symbol) |
1887 | addr = kernel_get_symbol_address_by_name(tp->symbol, true); | ||
1829 | if (addr) { | 1888 | if (addr) { |
1830 | addr += tp->offset; | 1889 | addr += tp->offset; |
1831 | sym = __find_kernel_function(addr, &map); | 1890 | sym = __find_kernel_function(addr, &map); |
@@ -1848,8 +1907,8 @@ out: | |||
1848 | } | 1907 | } |
1849 | 1908 | ||
1850 | static int convert_to_perf_probe_point(struct probe_trace_point *tp, | 1909 | static int convert_to_perf_probe_point(struct probe_trace_point *tp, |
1851 | struct perf_probe_point *pp, | 1910 | struct perf_probe_point *pp, |
1852 | bool is_kprobe) | 1911 | bool is_kprobe) |
1853 | { | 1912 | { |
1854 | char buf[128]; | 1913 | char buf[128]; |
1855 | int ret; | 1914 | int ret; |
@@ -1866,7 +1925,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp, | |||
1866 | if (tp->symbol) { | 1925 | if (tp->symbol) { |
1867 | pp->function = strdup(tp->symbol); | 1926 | pp->function = strdup(tp->symbol); |
1868 | pp->offset = tp->offset; | 1927 | pp->offset = tp->offset; |
1869 | } else if (!tp->module && !is_kprobe) { | 1928 | } else { |
1870 | ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address); | 1929 | ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address); |
1871 | if (ret < 0) | 1930 | if (ret < 0) |
1872 | return ret; | 1931 | return ret; |
@@ -2305,7 +2364,9 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev, | |||
2305 | if (pev->event) | 2364 | if (pev->event) |
2306 | event = pev->event; | 2365 | event = pev->event; |
2307 | else | 2366 | else |
2308 | if (pev->point.function && !strisglob(pev->point.function)) | 2367 | if (pev->point.function && |
2368 | (strncmp(pev->point.function, "0x", 2) != 0) && | ||
2369 | !strisglob(pev->point.function)) | ||
2309 | event = pev->point.function; | 2370 | event = pev->point.function; |
2310 | else | 2371 | else |
2311 | event = tev->point.realname; | 2372 | event = tev->point.realname; |
@@ -2572,6 +2633,98 @@ err_out: | |||
2572 | goto out; | 2633 | goto out; |
2573 | } | 2634 | } |
2574 | 2635 | ||
2636 | static int try_to_find_absolute_address(struct perf_probe_event *pev, | ||
2637 | struct probe_trace_event **tevs) | ||
2638 | { | ||
2639 | struct perf_probe_point *pp = &pev->point; | ||
2640 | struct probe_trace_event *tev; | ||
2641 | struct probe_trace_point *tp; | ||
2642 | int i, err; | ||
2643 | |||
2644 | if (!(pev->point.function && !strncmp(pev->point.function, "0x", 2))) | ||
2645 | return -EINVAL; | ||
2646 | if (perf_probe_event_need_dwarf(pev)) | ||
2647 | return -EINVAL; | ||
2648 | |||
2649 | /* | ||
2650 | * This is 'perf probe /lib/libc.so 0xabcd'. Try to probe at | ||
2651 | * absolute address. | ||
2652 | * | ||
2653 | * Only one tev can be generated by this. | ||
2654 | */ | ||
2655 | *tevs = zalloc(sizeof(*tev)); | ||
2656 | if (!*tevs) | ||
2657 | return -ENOMEM; | ||
2658 | |||
2659 | tev = *tevs; | ||
2660 | tp = &tev->point; | ||
2661 | |||
2662 | /* | ||
2663 | * Don't use tp->offset, use address directly, because | ||
2664 | * in synthesize_probe_trace_command() address cannot be | ||
2665 | * zero. | ||
2666 | */ | ||
2667 | tp->address = pev->point.abs_address; | ||
2668 | tp->retprobe = pp->retprobe; | ||
2669 | tev->uprobes = pev->uprobes; | ||
2670 | |||
2671 | err = -ENOMEM; | ||
2672 | /* | ||
2673 | * Give it a '0x' leading symbol name. | ||
2674 | * In __add_probe_trace_events, a NULL symbol is interpreted as | ||
2675 | * invalud. | ||
2676 | */ | ||
2677 | if (asprintf(&tp->symbol, "0x%lx", tp->address) < 0) | ||
2678 | goto errout; | ||
2679 | |||
2680 | /* For kprobe, check range */ | ||
2681 | if ((!tev->uprobes) && | ||
2682 | (kprobe_warn_out_range(tev->point.symbol, | ||
2683 | tev->point.address))) { | ||
2684 | err = -EACCES; | ||
2685 | goto errout; | ||
2686 | } | ||
2687 | |||
2688 | if (asprintf(&tp->realname, "abs_%lx", tp->address) < 0) | ||
2689 | goto errout; | ||
2690 | |||
2691 | if (pev->target) { | ||
2692 | tp->module = strdup(pev->target); | ||
2693 | if (!tp->module) | ||
2694 | goto errout; | ||
2695 | } | ||
2696 | |||
2697 | if (tev->group) { | ||
2698 | tev->group = strdup(pev->group); | ||
2699 | if (!tev->group) | ||
2700 | goto errout; | ||
2701 | } | ||
2702 | |||
2703 | if (pev->event) { | ||
2704 | tev->event = strdup(pev->event); | ||
2705 | if (!tev->event) | ||
2706 | goto errout; | ||
2707 | } | ||
2708 | |||
2709 | tev->nargs = pev->nargs; | ||
2710 | tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); | ||
2711 | if (!tev->args) { | ||
2712 | err = -ENOMEM; | ||
2713 | goto errout; | ||
2714 | } | ||
2715 | for (i = 0; i < tev->nargs; i++) | ||
2716 | copy_to_probe_trace_arg(&tev->args[i], &pev->args[i]); | ||
2717 | |||
2718 | return 1; | ||
2719 | |||
2720 | errout: | ||
2721 | if (*tevs) { | ||
2722 | clear_probe_trace_events(*tevs, 1); | ||
2723 | *tevs = NULL; | ||
2724 | } | ||
2725 | return err; | ||
2726 | } | ||
2727 | |||
2575 | bool __weak arch__prefers_symtab(void) { return false; } | 2728 | bool __weak arch__prefers_symtab(void) { return false; } |
2576 | 2729 | ||
2577 | static int convert_to_probe_trace_events(struct perf_probe_event *pev, | 2730 | static int convert_to_probe_trace_events(struct perf_probe_event *pev, |
@@ -2588,6 +2741,10 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, | |||
2588 | } | 2741 | } |
2589 | } | 2742 | } |
2590 | 2743 | ||
2744 | ret = try_to_find_absolute_address(pev, tevs); | ||
2745 | if (ret > 0) | ||
2746 | return ret; | ||
2747 | |||
2591 | if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) { | 2748 | if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) { |
2592 | ret = find_probe_trace_events_from_map(pev, tevs); | 2749 | ret = find_probe_trace_events_from_map(pev, tevs); |
2593 | if (ret > 0) | 2750 | if (ret > 0) |
@@ -2758,3 +2915,22 @@ end: | |||
2758 | return ret; | 2915 | return ret; |
2759 | } | 2916 | } |
2760 | 2917 | ||
2918 | int copy_to_probe_trace_arg(struct probe_trace_arg *tvar, | ||
2919 | struct perf_probe_arg *pvar) | ||
2920 | { | ||
2921 | tvar->value = strdup(pvar->var); | ||
2922 | if (tvar->value == NULL) | ||
2923 | return -ENOMEM; | ||
2924 | if (pvar->type) { | ||
2925 | tvar->type = strdup(pvar->type); | ||
2926 | if (tvar->type == NULL) | ||
2927 | return -ENOMEM; | ||
2928 | } | ||
2929 | if (pvar->name) { | ||
2930 | tvar->name = strdup(pvar->name); | ||
2931 | if (tvar->name == NULL) | ||
2932 | return -ENOMEM; | ||
2933 | } else | ||
2934 | tvar->name = NULL; | ||
2935 | return 0; | ||
2936 | } | ||
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 83ee95e9743b..6e7ec68a4aa8 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
@@ -59,6 +59,7 @@ struct perf_probe_point { | |||
59 | bool retprobe; /* Return probe flag */ | 59 | bool retprobe; /* Return probe flag */ |
60 | char *lazy_line; /* Lazy matching pattern */ | 60 | char *lazy_line; /* Lazy matching pattern */ |
61 | unsigned long offset; /* Offset from function entry */ | 61 | unsigned long offset; /* Offset from function entry */ |
62 | unsigned long abs_address; /* Absolute address of the point */ | ||
62 | }; | 63 | }; |
63 | 64 | ||
64 | /* Perf probe probing argument field chain */ | 65 | /* Perf probe probing argument field chain */ |
@@ -156,4 +157,7 @@ int e_snprintf(char *str, size_t size, const char *format, ...) | |||
156 | /* Maximum index number of event-name postfix */ | 157 | /* Maximum index number of event-name postfix */ |
157 | #define MAX_EVENT_INDEX 1024 | 158 | #define MAX_EVENT_INDEX 1024 |
158 | 159 | ||
160 | int copy_to_probe_trace_arg(struct probe_trace_arg *tvar, | ||
161 | struct perf_probe_arg *pvar); | ||
162 | |||
159 | #endif /*_PROBE_EVENT_H */ | 163 | #endif /*_PROBE_EVENT_H */ |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 7b80f8cb62b9..29c43c0680a8 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -553,24 +553,9 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
553 | char buf[32], *ptr; | 553 | char buf[32], *ptr; |
554 | int ret = 0; | 554 | int ret = 0; |
555 | 555 | ||
556 | if (!is_c_varname(pf->pvar->var)) { | 556 | /* Copy raw parameters */ |
557 | /* Copy raw parameters */ | 557 | if (!is_c_varname(pf->pvar->var)) |
558 | pf->tvar->value = strdup(pf->pvar->var); | 558 | return copy_to_probe_trace_arg(pf->tvar, pf->pvar); |
559 | if (pf->tvar->value == NULL) | ||
560 | return -ENOMEM; | ||
561 | if (pf->pvar->type) { | ||
562 | pf->tvar->type = strdup(pf->pvar->type); | ||
563 | if (pf->tvar->type == NULL) | ||
564 | return -ENOMEM; | ||
565 | } | ||
566 | if (pf->pvar->name) { | ||
567 | pf->tvar->name = strdup(pf->pvar->name); | ||
568 | if (pf->tvar->name == NULL) | ||
569 | return -ENOMEM; | ||
570 | } else | ||
571 | pf->tvar->name = NULL; | ||
572 | return 0; | ||
573 | } | ||
574 | 559 | ||
575 | if (pf->pvar->name) | 560 | if (pf->pvar->name) |
576 | pf->tvar->name = strdup(pf->pvar->name); | 561 | pf->tvar->name = strdup(pf->pvar->name); |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 42e98ab5a9bb..46ae0532a8a6 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -441,6 +441,16 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols, | |||
441 | return &s->sym; | 441 | return &s->sym; |
442 | } | 442 | } |
443 | 443 | ||
444 | void dso__reset_find_symbol_cache(struct dso *dso) | ||
445 | { | ||
446 | enum map_type type; | ||
447 | |||
448 | for (type = MAP__FUNCTION; type <= MAP__VARIABLE; ++type) { | ||
449 | dso->last_find_result[type].addr = 0; | ||
450 | dso->last_find_result[type].symbol = NULL; | ||
451 | } | ||
452 | } | ||
453 | |||
444 | struct symbol *dso__find_symbol(struct dso *dso, | 454 | struct symbol *dso__find_symbol(struct dso *dso, |
445 | enum map_type type, u64 addr) | 455 | enum map_type type, u64 addr) |
446 | { | 456 | { |