aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/intel-pt.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/intel-pt.c')
-rw-r--r--tools/perf/util/intel-pt.c176
1 files changed, 167 insertions, 9 deletions
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 551ff6f640be..dc041d4368c8 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -103,6 +103,9 @@ struct intel_pt {
103 unsigned max_non_turbo_ratio; 103 unsigned max_non_turbo_ratio;
104 104
105 unsigned long num_events; 105 unsigned long num_events;
106
107 char *filter;
108 struct addr_filters filts;
106}; 109};
107 110
108enum switch_state { 111enum switch_state {
@@ -241,7 +244,7 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
241 } 244 }
242 245
243 queue = &ptq->pt->queues.queue_array[ptq->queue_nr]; 246 queue = &ptq->pt->queues.queue_array[ptq->queue_nr];
244 247next:
245 buffer = auxtrace_buffer__next(queue, buffer); 248 buffer = auxtrace_buffer__next(queue, buffer);
246 if (!buffer) { 249 if (!buffer) {
247 if (old_buffer) 250 if (old_buffer)
@@ -264,9 +267,6 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
264 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer)) 267 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer))
265 return -ENOMEM; 268 return -ENOMEM;
266 269
267 if (old_buffer)
268 auxtrace_buffer__drop_data(old_buffer);
269
270 if (buffer->use_data) { 270 if (buffer->use_data) {
271 b->len = buffer->use_size; 271 b->len = buffer->use_size;
272 b->buf = buffer->use_data; 272 b->buf = buffer->use_data;
@@ -276,6 +276,16 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
276 } 276 }
277 b->ref_timestamp = buffer->reference; 277 b->ref_timestamp = buffer->reference;
278 278
279 /*
280 * If in snapshot mode and the buffer has no usable data, get next
281 * buffer and again check overlap against old_buffer.
282 */
283 if (ptq->pt->snapshot_mode && !b->len)
284 goto next;
285
286 if (old_buffer)
287 auxtrace_buffer__drop_data(old_buffer);
288
279 if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode && 289 if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode &&
280 !buffer->consecutive)) { 290 !buffer->consecutive)) {
281 b->consecutive = false; 291 b->consecutive = false;
@@ -477,7 +487,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
477 start_ip = *ip; 487 start_ip = *ip;
478 488
479 /* Load maps to ensure dso->is_64_bit has been updated */ 489 /* Load maps to ensure dso->is_64_bit has been updated */
480 map__load(al.map, machine->symbol_filter); 490 map__load(al.map);
481 491
482 x86_64 = al.map->dso->is_64_bit; 492 x86_64 = al.map->dso->is_64_bit;
483 493
@@ -541,6 +551,76 @@ out_no_cache:
541 return 0; 551 return 0;
542} 552}
543 553
554static bool intel_pt_match_pgd_ip(struct intel_pt *pt, uint64_t ip,
555 uint64_t offset, const char *filename)
556{
557 struct addr_filter *filt;
558 bool have_filter = false;
559 bool hit_tracestop = false;
560 bool hit_filter = false;
561
562 list_for_each_entry(filt, &pt->filts.head, list) {
563 if (filt->start)
564 have_filter = true;
565
566 if ((filename && !filt->filename) ||
567 (!filename && filt->filename) ||
568 (filename && strcmp(filename, filt->filename)))
569 continue;
570
571 if (!(offset >= filt->addr && offset < filt->addr + filt->size))
572 continue;
573
574 intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s hit filter: %s offset %#"PRIx64" size %#"PRIx64"\n",
575 ip, offset, filename ? filename : "[kernel]",
576 filt->start ? "filter" : "stop",
577 filt->addr, filt->size);
578
579 if (filt->start)
580 hit_filter = true;
581 else
582 hit_tracestop = true;
583 }
584
585 if (!hit_tracestop && !hit_filter)
586 intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s is not in a filter region\n",
587 ip, offset, filename ? filename : "[kernel]");
588
589 return hit_tracestop || (have_filter && !hit_filter);
590}
591
592static int __intel_pt_pgd_ip(uint64_t ip, void *data)
593{
594 struct intel_pt_queue *ptq = data;
595 struct thread *thread;
596 struct addr_location al;
597 u8 cpumode;
598 u64 offset;
599
600 if (ip >= ptq->pt->kernel_start)
601 return intel_pt_match_pgd_ip(ptq->pt, ip, ip, NULL);
602
603 cpumode = PERF_RECORD_MISC_USER;
604
605 thread = ptq->thread;
606 if (!thread)
607 return -EINVAL;
608
609 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, ip, &al);
610 if (!al.map || !al.map->dso)
611 return -EINVAL;
612
613 offset = al.map->map_ip(al.map, ip);
614
615 return intel_pt_match_pgd_ip(ptq->pt, ip, offset,
616 al.map->dso->long_name);
617}
618
619static bool intel_pt_pgd_ip(uint64_t ip, void *data)
620{
621 return __intel_pt_pgd_ip(ip, data) > 0;
622}
623
544static bool intel_pt_get_config(struct intel_pt *pt, 624static bool intel_pt_get_config(struct intel_pt *pt,
545 struct perf_event_attr *attr, u64 *config) 625 struct perf_event_attr *attr, u64 *config)
546{ 626{
@@ -717,6 +797,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
717 params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n; 797 params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n;
718 params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d; 798 params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d;
719 799
800 if (pt->filts.cnt > 0)
801 params.pgd_ip = intel_pt_pgd_ip;
802
720 if (pt->synth_opts.instructions) { 803 if (pt->synth_opts.instructions) {
721 if (pt->synth_opts.period) { 804 if (pt->synth_opts.period) {
722 switch (pt->synth_opts.period_type) { 805 switch (pt->synth_opts.period_type) {
@@ -1294,7 +1377,7 @@ static u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip)
1294 if (!map) 1377 if (!map)
1295 return 0; 1378 return 0;
1296 1379
1297 if (map__load(map, machine->symbol_filter)) 1380 if (map__load(map))
1298 return 0; 1381 return 0;
1299 1382
1300 start = dso__first_symbol(map->dso, MAP__FUNCTION); 1383 start = dso__first_symbol(map->dso, MAP__FUNCTION);
@@ -1767,6 +1850,8 @@ static void intel_pt_free(struct perf_session *session)
1767 intel_pt_free_events(session); 1850 intel_pt_free_events(session);
1768 session->auxtrace = NULL; 1851 session->auxtrace = NULL;
1769 thread__put(pt->unknown_thread); 1852 thread__put(pt->unknown_thread);
1853 addr_filters__exit(&pt->filts);
1854 zfree(&pt->filter);
1770 free(pt); 1855 free(pt);
1771} 1856}
1772 1857
@@ -2016,6 +2101,8 @@ static const char * const intel_pt_info_fmts[] = {
2016 [INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n", 2101 [INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n",
2017 [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n", 2102 [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n",
2018 [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n", 2103 [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n",
2104 [INTEL_PT_MAX_NONTURBO_RATIO] = " Max non-turbo ratio %"PRIu64"\n",
2105 [INTEL_PT_FILTER_STR_LEN] = " Filter string len. %"PRIu64"\n",
2019}; 2106};
2020 2107
2021static void intel_pt_print_info(u64 *arr, int start, int finish) 2108static void intel_pt_print_info(u64 *arr, int start, int finish)
@@ -2029,12 +2116,28 @@ static void intel_pt_print_info(u64 *arr, int start, int finish)
2029 fprintf(stdout, intel_pt_info_fmts[i], arr[i]); 2116 fprintf(stdout, intel_pt_info_fmts[i], arr[i]);
2030} 2117}
2031 2118
2119static void intel_pt_print_info_str(const char *name, const char *str)
2120{
2121 if (!dump_trace)
2122 return;
2123
2124 fprintf(stdout, " %-20s%s\n", name, str ? str : "");
2125}
2126
2127static bool intel_pt_has(struct auxtrace_info_event *auxtrace_info, int pos)
2128{
2129 return auxtrace_info->header.size >=
2130 sizeof(struct auxtrace_info_event) + (sizeof(u64) * (pos + 1));
2131}
2132
2032int intel_pt_process_auxtrace_info(union perf_event *event, 2133int intel_pt_process_auxtrace_info(union perf_event *event,
2033 struct perf_session *session) 2134 struct perf_session *session)
2034{ 2135{
2035 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info; 2136 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
2036 size_t min_sz = sizeof(u64) * INTEL_PT_PER_CPU_MMAPS; 2137 size_t min_sz = sizeof(u64) * INTEL_PT_PER_CPU_MMAPS;
2037 struct intel_pt *pt; 2138 struct intel_pt *pt;
2139 void *info_end;
2140 u64 *info;
2038 int err; 2141 int err;
2039 2142
2040 if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) + 2143 if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) +
@@ -2045,6 +2148,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2045 if (!pt) 2148 if (!pt)
2046 return -ENOMEM; 2149 return -ENOMEM;
2047 2150
2151 addr_filters__init(&pt->filts);
2152
2048 perf_config(intel_pt_perf_config, pt); 2153 perf_config(intel_pt_perf_config, pt);
2049 2154
2050 err = auxtrace_queues__init(&pt->queues); 2155 err = auxtrace_queues__init(&pt->queues);
@@ -2069,8 +2174,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2069 intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE, 2174 intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE,
2070 INTEL_PT_PER_CPU_MMAPS); 2175 INTEL_PT_PER_CPU_MMAPS);
2071 2176
2072 if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) + 2177 if (intel_pt_has(auxtrace_info, INTEL_PT_CYC_BIT)) {
2073 (sizeof(u64) * INTEL_PT_CYC_BIT)) {
2074 pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT]; 2178 pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT];
2075 pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS]; 2179 pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS];
2076 pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N]; 2180 pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N];
@@ -2080,6 +2184,54 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2080 INTEL_PT_CYC_BIT); 2184 INTEL_PT_CYC_BIT);
2081 } 2185 }
2082 2186
2187 if (intel_pt_has(auxtrace_info, INTEL_PT_MAX_NONTURBO_RATIO)) {
2188 pt->max_non_turbo_ratio =
2189 auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO];
2190 intel_pt_print_info(&auxtrace_info->priv[0],
2191 INTEL_PT_MAX_NONTURBO_RATIO,
2192 INTEL_PT_MAX_NONTURBO_RATIO);
2193 }
2194
2195 info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] + 1;
2196 info_end = (void *)info + auxtrace_info->header.size;
2197
2198 if (intel_pt_has(auxtrace_info, INTEL_PT_FILTER_STR_LEN)) {
2199 size_t len;
2200
2201 len = auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN];
2202 intel_pt_print_info(&auxtrace_info->priv[0],
2203 INTEL_PT_FILTER_STR_LEN,
2204 INTEL_PT_FILTER_STR_LEN);
2205 if (len) {
2206 const char *filter = (const char *)info;
2207
2208 len = roundup(len + 1, 8);
2209 info += len >> 3;
2210 if ((void *)info > info_end) {
2211 pr_err("%s: bad filter string length\n", __func__);
2212 err = -EINVAL;
2213 goto err_free_queues;
2214 }
2215 pt->filter = memdup(filter, len);
2216 if (!pt->filter) {
2217 err = -ENOMEM;
2218 goto err_free_queues;
2219 }
2220 if (session->header.needs_swap)
2221 mem_bswap_64(pt->filter, len);
2222 if (pt->filter[len - 1]) {
2223 pr_err("%s: filter string not null terminated\n", __func__);
2224 err = -EINVAL;
2225 goto err_free_queues;
2226 }
2227 err = addr_filters__parse_bare_filter(&pt->filts,
2228 filter);
2229 if (err)
2230 goto err_free_queues;
2231 }
2232 intel_pt_print_info_str("Filter string", pt->filter);
2233 }
2234
2083 pt->timeless_decoding = intel_pt_timeless_decoding(pt); 2235 pt->timeless_decoding = intel_pt_timeless_decoding(pt);
2084 pt->have_tsc = intel_pt_have_tsc(pt); 2236 pt->have_tsc = intel_pt_have_tsc(pt);
2085 pt->sampling_mode = false; 2237 pt->sampling_mode = false;
@@ -2121,11 +2273,13 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2121 pt->switch_evsel = intel_pt_find_sched_switch(session->evlist); 2273 pt->switch_evsel = intel_pt_find_sched_switch(session->evlist);
2122 if (!pt->switch_evsel) { 2274 if (!pt->switch_evsel) {
2123 pr_err("%s: missing sched_switch event\n", __func__); 2275 pr_err("%s: missing sched_switch event\n", __func__);
2276 err = -EINVAL;
2124 goto err_delete_thread; 2277 goto err_delete_thread;
2125 } 2278 }
2126 } else if (pt->have_sched_switch == 2 && 2279 } else if (pt->have_sched_switch == 2 &&
2127 !intel_pt_find_switch(session->evlist)) { 2280 !intel_pt_find_switch(session->evlist)) {
2128 pr_err("%s: missing context_switch attribute flag\n", __func__); 2281 pr_err("%s: missing context_switch attribute flag\n", __func__);
2282 err = -EINVAL;
2129 goto err_delete_thread; 2283 goto err_delete_thread;
2130 } 2284 }
2131 2285
@@ -2149,7 +2303,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2149 if (pt->tc.time_mult) { 2303 if (pt->tc.time_mult) {
2150 u64 tsc_freq = intel_pt_ns_to_ticks(pt, 1000000000); 2304 u64 tsc_freq = intel_pt_ns_to_ticks(pt, 1000000000);
2151 2305
2152 pt->max_non_turbo_ratio = (tsc_freq + 50000000) / 100000000; 2306 if (!pt->max_non_turbo_ratio)
2307 pt->max_non_turbo_ratio =
2308 (tsc_freq + 50000000) / 100000000;
2153 intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq); 2309 intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq);
2154 intel_pt_log("Maximum non-turbo ratio %u\n", 2310 intel_pt_log("Maximum non-turbo ratio %u\n",
2155 pt->max_non_turbo_ratio); 2311 pt->max_non_turbo_ratio);
@@ -2193,6 +2349,8 @@ err_free_queues:
2193 auxtrace_queues__free(&pt->queues); 2349 auxtrace_queues__free(&pt->queues);
2194 session->auxtrace = NULL; 2350 session->auxtrace = NULL;
2195err_free: 2351err_free:
2352 addr_filters__exit(&pt->filts);
2353 zfree(&pt->filter);
2196 free(pt); 2354 free(pt);
2197 return err; 2355 return err;
2198} 2356}