Linux Perf
intel-pt.c
Go to the documentation of this file.
1 /*
2  * intel_pt.c: Intel Processor Trace support
3  * Copyright (c) 2013-2015, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  */
15 
16 #include <errno.h>
17 #include <stdbool.h>
18 #include <linux/kernel.h>
19 #include <linux/types.h>
20 #include <linux/bitops.h>
21 #include <linux/log2.h>
22 #include <cpuid.h>
23 
24 #include "../../perf.h"
25 #include "../../util/session.h"
26 #include "../../util/event.h"
27 #include "../../util/evlist.h"
28 #include "../../util/evsel.h"
29 #include "../../util/cpumap.h"
30 #include <subcmd/parse-options.h>
31 #include "../../util/parse-events.h"
32 #include "../../util/pmu.h"
33 #include "../../util/debug.h"
34 #include "../../util/auxtrace.h"
35 #include "../../util/tsc.h"
36 #include "../../util/intel-pt.h"
37 
38 #define KiB(x) ((x) * 1024)
39 #define MiB(x) ((x) * 1024 * 1024)
40 #define KiB_MASK(x) (KiB(x) - 1)
41 #define MiB_MASK(x) (MiB(x) - 1)
42 
43 #define INTEL_PT_PSB_PERIOD_NEAR 256
44 
46  void *ref_buf;
47  size_t ref_offset;
48  bool wrapped;
49 };
50 
52  struct auxtrace_record itr;
58  size_t snapshot_size;
62  size_t priv_size;
63 };
64 
65 static int intel_pt_parse_terms_with_default(struct list_head *formats,
66  const char *str,
67  u64 *config)
68 {
69  struct list_head *terms;
70  struct perf_event_attr attr = { .size = 0, };
71  int err;
72 
73  terms = malloc(sizeof(struct list_head));
74  if (!terms)
75  return -ENOMEM;
76 
77  INIT_LIST_HEAD(terms);
78 
79  err = parse_events_terms(terms, str);
80  if (err)
81  goto out_free;
82 
83  attr.config = *config;
84  err = perf_pmu__config_terms(formats, &attr, terms, true, NULL);
85  if (err)
86  goto out_free;
87 
88  *config = attr.config;
89 out_free:
91  return err;
92 }
93 
94 static int intel_pt_parse_terms(struct list_head *formats, const char *str,
95  u64 *config)
96 {
97  *config = 0;
98  return intel_pt_parse_terms_with_default(formats, str, config);
99 }
100 
101 static u64 intel_pt_masked_bits(u64 mask, u64 bits)
102 {
103  const u64 top_bit = 1ULL << 63;
104  u64 res = 0;
105  int i;
106 
107  for (i = 0; i < 64; i++) {
108  if (mask & top_bit) {
109  res <<= 1;
110  if (bits & top_bit)
111  res |= 1;
112  }
113  mask <<= 1;
114  bits <<= 1;
115  }
116 
117  return res;
118 }
119 
120 static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str,
121  struct perf_evlist *evlist, u64 *res)
122 {
123  struct perf_evsel *evsel;
124  u64 mask;
125 
126  *res = 0;
127 
128  mask = perf_pmu__format_bits(&intel_pt_pmu->format, str);
129  if (!mask)
130  return -EINVAL;
131 
132  evlist__for_each_entry(evlist, evsel) {
133  if (evsel->attr.type == intel_pt_pmu->type) {
134  *res = intel_pt_masked_bits(mask, evsel->attr.config);
135  return 0;
136  }
137  }
138 
139  return -EINVAL;
140 }
141 
142 static size_t intel_pt_psb_period(struct perf_pmu *intel_pt_pmu,
143  struct perf_evlist *evlist)
144 {
145  u64 val;
146  int err, topa_multiple_entries;
147  size_t psb_period;
148 
149  if (perf_pmu__scan_file(intel_pt_pmu, "caps/topa_multiple_entries",
150  "%d", &topa_multiple_entries) != 1)
151  topa_multiple_entries = 0;
152 
153  /*
154  * Use caps/topa_multiple_entries to indicate early hardware that had
155  * extra frequent PSBs.
156  */
157  if (!topa_multiple_entries) {
158  psb_period = 256;
159  goto out;
160  }
161 
162  err = intel_pt_read_config(intel_pt_pmu, "psb_period", evlist, &val);
163  if (err)
164  val = 0;
165 
166  psb_period = 1 << (val + 11);
167 out:
168  pr_debug2("%s psb_period %zu\n", intel_pt_pmu->name, psb_period);
169  return psb_period;
170 }
171 
172 static int intel_pt_pick_bit(int bits, int target)
173 {
174  int pos, pick = -1;
175 
176  for (pos = 0; bits; bits >>= 1, pos++) {
177  if (bits & 1) {
178  if (pos <= target || pick < 0)
179  pick = pos;
180  if (pos >= target)
181  break;
182  }
183  }
184 
185  return pick;
186 }
187 
188 static u64 intel_pt_default_config(struct perf_pmu *intel_pt_pmu)
189 {
190  char buf[256];
191  int mtc, mtc_periods = 0, mtc_period;
192  int psb_cyc, psb_periods, psb_period;
193  int pos = 0;
194  u64 config;
195  char c;
196 
197  pos += scnprintf(buf + pos, sizeof(buf) - pos, "tsc");
198 
199  if (perf_pmu__scan_file(intel_pt_pmu, "caps/mtc", "%d",
200  &mtc) != 1)
201  mtc = 1;
202 
203  if (mtc) {
204  if (perf_pmu__scan_file(intel_pt_pmu, "caps/mtc_periods", "%x",
205  &mtc_periods) != 1)
206  mtc_periods = 0;
207  if (mtc_periods) {
208  mtc_period = intel_pt_pick_bit(mtc_periods, 3);
209  pos += scnprintf(buf + pos, sizeof(buf) - pos,
210  ",mtc,mtc_period=%d", mtc_period);
211  }
212  }
213 
214  if (perf_pmu__scan_file(intel_pt_pmu, "caps/psb_cyc", "%d",
215  &psb_cyc) != 1)
216  psb_cyc = 1;
217 
218  if (psb_cyc && mtc_periods) {
219  if (perf_pmu__scan_file(intel_pt_pmu, "caps/psb_periods", "%x",
220  &psb_periods) != 1)
221  psb_periods = 0;
222  if (psb_periods) {
223  psb_period = intel_pt_pick_bit(psb_periods, 3);
224  pos += scnprintf(buf + pos, sizeof(buf) - pos,
225  ",psb_period=%d", psb_period);
226  }
227  }
228 
229  if (perf_pmu__scan_file(intel_pt_pmu, "format/pt", "%c", &c) == 1 &&
230  perf_pmu__scan_file(intel_pt_pmu, "format/branch", "%c", &c) == 1)
231  pos += scnprintf(buf + pos, sizeof(buf) - pos, ",pt,branch");
232 
233  pr_debug2("%s default config: %s\n", intel_pt_pmu->name, buf);
234 
235  intel_pt_parse_terms(&intel_pt_pmu->format, buf, &config);
236 
237  return config;
238 }
239 
241  struct record_opts *opts,
242  const char *str)
243 {
244  struct intel_pt_recording *ptr =
245  container_of(itr, struct intel_pt_recording, itr);
246  unsigned long long snapshot_size = 0;
247  char *endptr;
248 
249  if (str) {
250  snapshot_size = strtoull(str, &endptr, 0);
251  if (*endptr || snapshot_size > SIZE_MAX)
252  return -1;
253  }
254 
255  opts->auxtrace_snapshot_mode = true;
257 
259 
260  return 0;
261 }
262 
263 struct perf_event_attr *
265 {
266  struct perf_event_attr *attr;
267 
268  attr = zalloc(sizeof(struct perf_event_attr));
269  if (!attr)
270  return NULL;
271 
272  attr->config = intel_pt_default_config(intel_pt_pmu);
273 
274  intel_pt_pmu->selectable = true;
275 
276  return attr;
277 }
278 
279 static const char *intel_pt_find_filter(struct perf_evlist *evlist,
280  struct perf_pmu *intel_pt_pmu)
281 {
282  struct perf_evsel *evsel;
283 
284  evlist__for_each_entry(evlist, evsel) {
285  if (evsel->attr.type == intel_pt_pmu->type)
286  return evsel->filter;
287  }
288 
289  return NULL;
290 }
291 
292 static size_t intel_pt_filter_bytes(const char *filter)
293 {
294  size_t len = filter ? strlen(filter) : 0;
295 
296  return len ? roundup(len + 1, 8) : 0;
297 }
298 
299 static size_t
301 {
302  struct intel_pt_recording *ptr =
303  container_of(itr, struct intel_pt_recording, itr);
304  const char *filter = intel_pt_find_filter(evlist, ptr->intel_pt_pmu);
305 
306  ptr->priv_size = (INTEL_PT_AUXTRACE_PRIV_MAX * sizeof(u64)) +
307  intel_pt_filter_bytes(filter);
308 
309  return ptr->priv_size;
310 }
311 
312 static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d)
313 {
314  unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
315 
316  __get_cpuid(0x15, &eax, &ebx, &ecx, &edx);
317  *n = ebx;
318  *d = eax;
319 }
320 
322  struct perf_session *session,
323  struct auxtrace_info_event *auxtrace_info,
324  size_t priv_size)
325 {
326  struct intel_pt_recording *ptr =
327  container_of(itr, struct intel_pt_recording, itr);
328  struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu;
329  struct perf_event_mmap_page *pc;
330  struct perf_tsc_conversion tc = { .time_mult = 0, };
331  bool cap_user_time_zero = false, per_cpu_mmaps;
332  u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;
333  u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d;
334  unsigned long max_non_turbo_ratio;
335  size_t filter_str_len;
336  const char *filter;
337  u64 *info;
338  int err;
339 
340  if (priv_size != ptr->priv_size)
341  return -EINVAL;
342 
343  intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit);
344  intel_pt_parse_terms(&intel_pt_pmu->format, "noretcomp",
345  &noretcomp_bit);
346  intel_pt_parse_terms(&intel_pt_pmu->format, "mtc", &mtc_bit);
347  mtc_freq_bits = perf_pmu__format_bits(&intel_pt_pmu->format,
348  "mtc_period");
349  intel_pt_parse_terms(&intel_pt_pmu->format, "cyc", &cyc_bit);
350 
351  intel_pt_tsc_ctc_ratio(&tsc_ctc_ratio_n, &tsc_ctc_ratio_d);
352 
353  if (perf_pmu__scan_file(intel_pt_pmu, "max_nonturbo_ratio",
354  "%lu", &max_non_turbo_ratio) != 1)
355  max_non_turbo_ratio = 0;
356 
357  filter = intel_pt_find_filter(session->evlist, ptr->intel_pt_pmu);
358  filter_str_len = filter ? strlen(filter) : 0;
359 
360  if (!session->evlist->nr_mmaps)
361  return -EINVAL;
362 
363  pc = session->evlist->mmap[0].base;
364  if (pc) {
365  err = perf_read_tsc_conversion(pc, &tc);
366  if (err) {
367  if (err != -EOPNOTSUPP)
368  return err;
369  } else {
370  cap_user_time_zero = tc.time_mult != 0;
371  }
372  if (!cap_user_time_zero)
373  ui__warning("Intel Processor Trace: TSC not available\n");
374  }
375 
376  per_cpu_mmaps = !cpu_map__empty(session->evlist->cpus);
377 
378  auxtrace_info->type = PERF_AUXTRACE_INTEL_PT;
379  auxtrace_info->priv[INTEL_PT_PMU_TYPE] = intel_pt_pmu->type;
380  auxtrace_info->priv[INTEL_PT_TIME_SHIFT] = tc.time_shift;
381  auxtrace_info->priv[INTEL_PT_TIME_MULT] = tc.time_mult;
382  auxtrace_info->priv[INTEL_PT_TIME_ZERO] = tc.time_zero;
383  auxtrace_info->priv[INTEL_PT_CAP_USER_TIME_ZERO] = cap_user_time_zero;
384  auxtrace_info->priv[INTEL_PT_TSC_BIT] = tsc_bit;
385  auxtrace_info->priv[INTEL_PT_NORETCOMP_BIT] = noretcomp_bit;
386  auxtrace_info->priv[INTEL_PT_HAVE_SCHED_SWITCH] = ptr->have_sched_switch;
387  auxtrace_info->priv[INTEL_PT_SNAPSHOT_MODE] = ptr->snapshot_mode;
388  auxtrace_info->priv[INTEL_PT_PER_CPU_MMAPS] = per_cpu_mmaps;
389  auxtrace_info->priv[INTEL_PT_MTC_BIT] = mtc_bit;
390  auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS] = mtc_freq_bits;
391  auxtrace_info->priv[INTEL_PT_TSC_CTC_N] = tsc_ctc_ratio_n;
392  auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d;
393  auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit;
394  auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO] = max_non_turbo_ratio;
395  auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] = filter_str_len;
396 
397  info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] + 1;
398 
399  if (filter_str_len) {
400  size_t len = intel_pt_filter_bytes(filter);
401 
402  strncpy((char *)info, filter, len);
403  info += len >> 3;
404  }
405 
406  return 0;
407 }
408 
409 static int intel_pt_track_switches(struct perf_evlist *evlist)
410 {
411  const char *sched_switch = "sched:sched_switch";
412  struct perf_evsel *evsel;
413  int err;
414 
415  if (!perf_evlist__can_select_event(evlist, sched_switch))
416  return -EPERM;
417 
418  err = parse_events(evlist, sched_switch, NULL);
419  if (err) {
420  pr_debug2("%s: failed to parse %s, error %d\n",
421  __func__, sched_switch, err);
422  return err;
423  }
424 
425  evsel = perf_evlist__last(evlist);
426 
428  perf_evsel__set_sample_bit(evsel, TIME);
429 
430  evsel->system_wide = true;
431  evsel->no_aux_samples = true;
432  evsel->immediate = true;
433 
434  return 0;
435 }
436 
437 static void intel_pt_valid_str(char *str, size_t len, u64 valid)
438 {
439  unsigned int val, last = 0, state = 1;
440  int p = 0;
441 
442  str[0] = '\0';
443 
444  for (val = 0; val <= 64; val++, valid >>= 1) {
445  if (valid & 1) {
446  last = val;
447  switch (state) {
448  case 0:
449  p += scnprintf(str + p, len - p, ",");
450  /* Fall through */
451  case 1:
452  p += scnprintf(str + p, len - p, "%u", val);
453  state = 2;
454  break;
455  case 2:
456  state = 3;
457  break;
458  case 3:
459  state = 4;
460  break;
461  default:
462  break;
463  }
464  } else {
465  switch (state) {
466  case 3:
467  p += scnprintf(str + p, len - p, ",%u", last);
468  state = 0;
469  break;
470  case 4:
471  p += scnprintf(str + p, len - p, "-%u", last);
472  state = 0;
473  break;
474  default:
475  break;
476  }
477  if (state != 1)
478  state = 0;
479  }
480  }
481 }
482 
483 static int intel_pt_val_config_term(struct perf_pmu *intel_pt_pmu,
484  const char *caps, const char *name,
485  const char *supported, u64 config)
486 {
487  char valid_str[256];
488  unsigned int shift;
489  unsigned long long valid;
490  u64 bits;
491  int ok;
492 
493  if (perf_pmu__scan_file(intel_pt_pmu, caps, "%llx", &valid) != 1)
494  valid = 0;
495 
496  if (supported &&
497  perf_pmu__scan_file(intel_pt_pmu, supported, "%d", &ok) == 1 && !ok)
498  valid = 0;
499 
500  valid |= 1;
501 
502  bits = perf_pmu__format_bits(&intel_pt_pmu->format, name);
503 
504  config &= bits;
505 
506  for (shift = 0; bits && !(bits & 1); shift++)
507  bits >>= 1;
508 
509  config >>= shift;
510 
511  if (config > 63)
512  goto out_err;
513 
514  if (valid & (1 << config))
515  return 0;
516 out_err:
517  intel_pt_valid_str(valid_str, sizeof(valid_str), valid);
518  pr_err("Invalid %s for %s. Valid values are: %s\n",
519  name, INTEL_PT_PMU_NAME, valid_str);
520  return -EINVAL;
521 }
522 
523 static int intel_pt_validate_config(struct perf_pmu *intel_pt_pmu,
524  struct perf_evsel *evsel)
525 {
526  int err;
527 
528  if (!evsel)
529  return 0;
530 
531  err = intel_pt_val_config_term(intel_pt_pmu, "caps/cycle_thresholds",
532  "cyc_thresh", "caps/psb_cyc",
533  evsel->attr.config);
534  if (err)
535  return err;
536 
537  err = intel_pt_val_config_term(intel_pt_pmu, "caps/mtc_periods",
538  "mtc_period", "caps/mtc",
539  evsel->attr.config);
540  if (err)
541  return err;
542 
543  return intel_pt_val_config_term(intel_pt_pmu, "caps/psb_periods",
544  "psb_period", "caps/psb_cyc",
545  evsel->attr.config);
546 }
547 
549  struct perf_evlist *evlist,
550  struct record_opts *opts)
551 {
552  struct intel_pt_recording *ptr =
553  container_of(itr, struct intel_pt_recording, itr);
554  struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu;
555  bool have_timing_info, need_immediate = false;
556  struct perf_evsel *evsel, *intel_pt_evsel = NULL;
557  const struct cpu_map *cpus = evlist->cpus;
558  bool privileged = geteuid() == 0 || perf_event_paranoid() < 0;
559  u64 tsc_bit;
560  int err;
561 
562  ptr->evlist = evlist;
564 
565  evlist__for_each_entry(evlist, evsel) {
566  if (evsel->attr.type == intel_pt_pmu->type) {
567  if (intel_pt_evsel) {
568  pr_err("There may be only one " INTEL_PT_PMU_NAME " event\n");
569  return -EINVAL;
570  }
571  evsel->attr.freq = 0;
572  evsel->attr.sample_period = 1;
573  intel_pt_evsel = evsel;
574  opts->full_auxtrace = true;
575  }
576  }
577 
578  if (opts->auxtrace_snapshot_mode && !opts->full_auxtrace) {
579  pr_err("Snapshot mode (-S option) requires " INTEL_PT_PMU_NAME " PMU event (-e " INTEL_PT_PMU_NAME ")\n");
580  return -EINVAL;
581  }
582 
583  if (opts->use_clockid) {
584  pr_err("Cannot use clockid (-k option) with " INTEL_PT_PMU_NAME "\n");
585  return -EINVAL;
586  }
587 
588  if (!opts->full_auxtrace)
589  return 0;
590 
591  err = intel_pt_validate_config(intel_pt_pmu, intel_pt_evsel);
592  if (err)
593  return err;
594 
595  /* Set default sizes for snapshot mode */
596  if (opts->auxtrace_snapshot_mode) {
597  size_t psb_period = intel_pt_psb_period(intel_pt_pmu, evlist);
598 
599  if (!opts->auxtrace_snapshot_size && !opts->auxtrace_mmap_pages) {
600  if (privileged) {
601  opts->auxtrace_mmap_pages = MiB(4) / page_size;
602  } else {
603  opts->auxtrace_mmap_pages = KiB(128) / page_size;
604  if (opts->mmap_pages == UINT_MAX)
605  opts->mmap_pages = KiB(256) / page_size;
606  }
607  } else if (!opts->auxtrace_mmap_pages && !privileged &&
608  opts->mmap_pages == UINT_MAX) {
609  opts->mmap_pages = KiB(256) / page_size;
610  }
611  if (!opts->auxtrace_snapshot_size)
612  opts->auxtrace_snapshot_size =
613  opts->auxtrace_mmap_pages * (size_t)page_size;
614  if (!opts->auxtrace_mmap_pages) {
615  size_t sz = opts->auxtrace_snapshot_size;
616 
617  sz = round_up(sz, page_size) / page_size;
618  opts->auxtrace_mmap_pages = roundup_pow_of_two(sz);
619  }
620  if (opts->auxtrace_snapshot_size >
621  opts->auxtrace_mmap_pages * (size_t)page_size) {
622  pr_err("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n",
624  opts->auxtrace_mmap_pages * (size_t)page_size);
625  return -EINVAL;
626  }
627  if (!opts->auxtrace_snapshot_size || !opts->auxtrace_mmap_pages) {
628  pr_err("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n");
629  return -EINVAL;
630  }
631  pr_debug2("Intel PT snapshot size: %zu\n",
632  opts->auxtrace_snapshot_size);
633  if (psb_period &&
634  opts->auxtrace_snapshot_size <= psb_period +
636  ui__warning("Intel PT snapshot size (%zu) may be too small for PSB period (%zu)\n",
637  opts->auxtrace_snapshot_size, psb_period);
638  }
639 
640  /* Set default sizes for full trace mode */
641  if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) {
642  if (privileged) {
643  opts->auxtrace_mmap_pages = MiB(4) / page_size;
644  } else {
645  opts->auxtrace_mmap_pages = KiB(128) / page_size;
646  if (opts->mmap_pages == UINT_MAX)
647  opts->mmap_pages = KiB(256) / page_size;
648  }
649  }
650 
651  /* Validate auxtrace_mmap_pages */
652  if (opts->auxtrace_mmap_pages) {
653  size_t sz = opts->auxtrace_mmap_pages * (size_t)page_size;
654  size_t min_sz;
655 
656  if (opts->auxtrace_snapshot_mode)
657  min_sz = KiB(4);
658  else
659  min_sz = KiB(8);
660 
661  if (sz < min_sz || !is_power_of_2(sz)) {
662  pr_err("Invalid mmap size for Intel Processor Trace: must be at least %zuKiB and a power of 2\n",
663  min_sz / 1024);
664  return -EINVAL;
665  }
666  }
667 
668  intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit);
669 
670  if (opts->full_auxtrace && (intel_pt_evsel->attr.config & tsc_bit))
671  have_timing_info = true;
672  else
673  have_timing_info = false;
674 
675  /*
676  * Per-cpu recording needs sched_switch events to distinguish different
677  * threads.
678  */
679  if (have_timing_info && !cpu_map__empty(cpus)) {
681  bool cpu_wide = !target__none(&opts->target) &&
682  !target__has_task(&opts->target);
683 
684  if (!cpu_wide && perf_can_record_cpu_wide()) {
685  struct perf_evsel *switch_evsel;
686 
687  err = parse_events(evlist, "dummy:u", NULL);
688  if (err)
689  return err;
690 
691  switch_evsel = perf_evlist__last(evlist);
692 
693  switch_evsel->attr.freq = 0;
694  switch_evsel->attr.sample_period = 1;
695  switch_evsel->attr.context_switch = 1;
696 
697  switch_evsel->system_wide = true;
698  switch_evsel->no_aux_samples = true;
699  switch_evsel->immediate = true;
700 
701  perf_evsel__set_sample_bit(switch_evsel, TID);
702  perf_evsel__set_sample_bit(switch_evsel, TIME);
703  perf_evsel__set_sample_bit(switch_evsel, CPU);
704  perf_evsel__reset_sample_bit(switch_evsel, BRANCH_STACK);
705 
706  opts->record_switch_events = false;
707  ptr->have_sched_switch = 3;
708  } else {
709  opts->record_switch_events = true;
710  need_immediate = true;
711  if (cpu_wide)
712  ptr->have_sched_switch = 3;
713  else
714  ptr->have_sched_switch = 2;
715  }
716  } else {
717  err = intel_pt_track_switches(evlist);
718  if (err == -EPERM)
719  pr_debug2("Unable to select sched:sched_switch\n");
720  else if (err)
721  return err;
722  else
723  ptr->have_sched_switch = 1;
724  }
725  }
726 
727  if (intel_pt_evsel) {
728  /*
729  * To obtain the auxtrace buffer file descriptor, the auxtrace
730  * event must come first.
731  */
732  perf_evlist__to_front(evlist, intel_pt_evsel);
733  /*
734  * In the case of per-cpu mmaps, we need the CPU on the
735  * AUX event.
736  */
737  if (!cpu_map__empty(cpus))
738  perf_evsel__set_sample_bit(intel_pt_evsel, CPU);
739  }
740 
741  /* Add dummy event to keep tracking */
742  if (opts->full_auxtrace) {
743  struct perf_evsel *tracking_evsel;
744 
745  err = parse_events(evlist, "dummy:u", NULL);
746  if (err)
747  return err;
748 
749  tracking_evsel = perf_evlist__last(evlist);
750 
751  perf_evlist__set_tracking_event(evlist, tracking_evsel);
752 
753  tracking_evsel->attr.freq = 0;
754  tracking_evsel->attr.sample_period = 1;
755 
756  tracking_evsel->no_aux_samples = true;
757  if (need_immediate)
758  tracking_evsel->immediate = true;
759 
760  /* In per-cpu case, always need the time of mmap events etc */
761  if (!cpu_map__empty(cpus)) {
762  perf_evsel__set_sample_bit(tracking_evsel, TIME);
763  /* And the CPU for switch events */
764  perf_evsel__set_sample_bit(tracking_evsel, CPU);
765  }
766  perf_evsel__reset_sample_bit(tracking_evsel, BRANCH_STACK);
767  }
768 
769  /*
770  * Warn the user when we do not have enough information to decode i.e.
771  * per-cpu with no sched_switch (except workload-only).
772  */
773  if (!ptr->have_sched_switch && !cpu_map__empty(cpus) &&
774  !target__none(&opts->target))
775  ui__warning("Intel Processor Trace decoding will not be possible except for kernel tracing!\n");
776 
777  return 0;
778 }
779 
781 {
782  struct intel_pt_recording *ptr =
783  container_of(itr, struct intel_pt_recording, itr);
784  struct perf_evsel *evsel;
785 
786  evlist__for_each_entry(ptr->evlist, evsel) {
787  if (evsel->attr.type == ptr->intel_pt_pmu->type)
788  return perf_evsel__disable(evsel);
789  }
790  return -EINVAL;
791 }
792 
794 {
795  struct intel_pt_recording *ptr =
796  container_of(itr, struct intel_pt_recording, itr);
797  struct perf_evsel *evsel;
798 
799  evlist__for_each_entry(ptr->evlist, evsel) {
800  if (evsel->attr.type == ptr->intel_pt_pmu->type)
801  return perf_evsel__enable(evsel);
802  }
803  return -EINVAL;
804 }
805 
807 {
808  const size_t sz = sizeof(struct intel_pt_snapshot_ref);
809  int cnt = ptr->snapshot_ref_cnt, new_cnt = cnt * 2;
810  struct intel_pt_snapshot_ref *refs;
811 
812  if (!new_cnt)
813  new_cnt = 16;
814 
815  while (new_cnt <= idx)
816  new_cnt *= 2;
817 
818  refs = calloc(new_cnt, sz);
819  if (!refs)
820  return -ENOMEM;
821 
822  memcpy(refs, ptr->snapshot_refs, cnt * sz);
823 
824  ptr->snapshot_refs = refs;
825  ptr->snapshot_ref_cnt = new_cnt;
826 
827  return 0;
828 }
829 
831 {
832  int i;
833 
834  for (i = 0; i < ptr->snapshot_ref_cnt; i++)
835  zfree(&ptr->snapshot_refs[i].ref_buf);
836  zfree(&ptr->snapshot_refs);
837 }
838 
839 static void intel_pt_recording_free(struct auxtrace_record *itr)
840 {
841  struct intel_pt_recording *ptr =
842  container_of(itr, struct intel_pt_recording, itr);
843 
845  free(ptr);
846 }
847 
848 static int intel_pt_alloc_snapshot_ref(struct intel_pt_recording *ptr, int idx,
849  size_t snapshot_buf_size)
850 {
851  size_t ref_buf_size = ptr->snapshot_ref_buf_size;
852  void *ref_buf;
853 
854  ref_buf = zalloc(ref_buf_size);
855  if (!ref_buf)
856  return -ENOMEM;
857 
858  ptr->snapshot_refs[idx].ref_buf = ref_buf;
859  ptr->snapshot_refs[idx].ref_offset = snapshot_buf_size - ref_buf_size;
860 
861  return 0;
862 }
863 
865  size_t snapshot_buf_size)
866 {
867  const size_t max_size = 256 * 1024;
868  size_t buf_size = 0, psb_period;
869 
870  if (ptr->snapshot_size <= 64 * 1024)
871  return 0;
872 
873  psb_period = intel_pt_psb_period(ptr->intel_pt_pmu, ptr->evlist);
874  if (psb_period)
875  buf_size = psb_period * 2;
876 
877  if (!buf_size || buf_size > max_size)
878  buf_size = max_size;
879 
880  if (buf_size >= snapshot_buf_size)
881  return 0;
882 
883  if (buf_size >= ptr->snapshot_size / 2)
884  return 0;
885 
886  return buf_size;
887 }
888 
890  size_t snapshot_buf_size)
891 {
892  if (ptr->snapshot_init_done)
893  return 0;
894 
895  ptr->snapshot_init_done = true;
896 
898  snapshot_buf_size);
899 
900  return 0;
901 }
902 
916 static bool intel_pt_compare_buffers(void *buf1, size_t compare_size,
917  void *buf2, size_t offs2, size_t buf2_size)
918 {
919  size_t end2 = offs2 + compare_size, part_size;
920 
921  if (end2 <= buf2_size)
922  return memcmp(buf1, buf2 + offs2, compare_size);
923 
924  part_size = end2 - buf2_size;
925  if (memcmp(buf1, buf2 + offs2, part_size))
926  return true;
927 
928  compare_size -= part_size;
929 
930  return memcmp(buf1 + part_size, buf2, compare_size);
931 }
932 
933 static bool intel_pt_compare_ref(void *ref_buf, size_t ref_offset,
934  size_t ref_size, size_t buf_size,
935  void *data, size_t head)
936 {
937  size_t ref_end = ref_offset + ref_size;
938 
939  if (ref_end > buf_size) {
940  if (head > ref_offset || head < ref_end - buf_size)
941  return true;
942  } else if (head > ref_offset && head < ref_end) {
943  return true;
944  }
945 
946  return intel_pt_compare_buffers(ref_buf, ref_size, data, ref_offset,
947  buf_size);
948 }
949 
950 static void intel_pt_copy_ref(void *ref_buf, size_t ref_size, size_t buf_size,
951  void *data, size_t head)
952 {
953  if (head >= ref_size) {
954  memcpy(ref_buf, data + head - ref_size, ref_size);
955  } else {
956  memcpy(ref_buf, data, head);
957  ref_size -= head;
958  memcpy(ref_buf + head, data + buf_size - ref_size, ref_size);
959  }
960 }
961 
962 static bool intel_pt_wrapped(struct intel_pt_recording *ptr, int idx,
963  struct auxtrace_mmap *mm, unsigned char *data,
964  u64 head)
965 {
966  struct intel_pt_snapshot_ref *ref = &ptr->snapshot_refs[idx];
967  bool wrapped;
968 
969  wrapped = intel_pt_compare_ref(ref->ref_buf, ref->ref_offset,
970  ptr->snapshot_ref_buf_size, mm->len,
971  data, head);
972 
974  data, head);
975 
976  return wrapped;
977 }
978 
979 static bool intel_pt_first_wrap(u64 *data, size_t buf_size)
980 {
981  int i, a, b;
982 
983  b = buf_size >> 3;
984  a = b - 512;
985  if (a < 0)
986  a = 0;
987 
988  for (i = a; i < b; i++) {
989  if (data[i])
990  return true;
991  }
992 
993  return false;
994 }
995 
996 static int intel_pt_find_snapshot(struct auxtrace_record *itr, int idx,
997  struct auxtrace_mmap *mm, unsigned char *data,
998  u64 *head, u64 *old)
999 {
1000  struct intel_pt_recording *ptr =
1001  container_of(itr, struct intel_pt_recording, itr);
1002  bool wrapped;
1003  int err;
1004 
1005  pr_debug3("%s: mmap index %d old head %zu new head %zu\n",
1006  __func__, idx, (size_t)*old, (size_t)*head);
1007 
1008  err = intel_pt_snapshot_init(ptr, mm->len);
1009  if (err)
1010  goto out_err;
1011 
1012  if (idx >= ptr->snapshot_ref_cnt) {
1013  err = intel_pt_alloc_snapshot_refs(ptr, idx);
1014  if (err)
1015  goto out_err;
1016  }
1017 
1018  if (ptr->snapshot_ref_buf_size) {
1019  if (!ptr->snapshot_refs[idx].ref_buf) {
1020  err = intel_pt_alloc_snapshot_ref(ptr, idx, mm->len);
1021  if (err)
1022  goto out_err;
1023  }
1024  wrapped = intel_pt_wrapped(ptr, idx, mm, data, *head);
1025  } else {
1026  wrapped = ptr->snapshot_refs[idx].wrapped;
1027  if (!wrapped && intel_pt_first_wrap((u64 *)data, mm->len)) {
1028  ptr->snapshot_refs[idx].wrapped = true;
1029  wrapped = true;
1030  }
1031  }
1032 
1033  /*
1034  * In full trace mode 'head' continually increases. However in snapshot
1035  * mode 'head' is an offset within the buffer. Here 'old' and 'head'
1036  * are adjusted to match the full trace case which expects that 'old' is
1037  * always less than 'head'.
1038  */
1039  if (wrapped) {
1040  *old = *head;
1041  *head += mm->len;
1042  } else {
1043  if (mm->mask)
1044  *old &= mm->mask;
1045  else
1046  *old %= mm->len;
1047  if (*old > *head)
1048  *head += mm->len;
1049  }
1050 
1051  pr_debug3("%s: wrap-around %sdetected, adjusted old head %zu adjusted new head %zu\n",
1052  __func__, wrapped ? "" : "not ", (size_t)*old, (size_t)*head);
1053 
1054  return 0;
1055 
1056 out_err:
1057  pr_err("%s: failed, error %d\n", __func__, err);
1058  return err;
1059 }
1060 
1061 static u64 intel_pt_reference(struct auxtrace_record *itr __maybe_unused)
1062 {
1063  return rdtsc();
1064 }
1065 
1066 static int intel_pt_read_finish(struct auxtrace_record *itr, int idx)
1067 {
1068  struct intel_pt_recording *ptr =
1069  container_of(itr, struct intel_pt_recording, itr);
1070  struct perf_evsel *evsel;
1071 
1072  evlist__for_each_entry(ptr->evlist, evsel) {
1073  if (evsel->attr.type == ptr->intel_pt_pmu->type)
1074  return perf_evlist__enable_event_idx(ptr->evlist, evsel,
1075  idx);
1076  }
1077  return -EINVAL;
1078 }
1079 
1081 {
1082  struct perf_pmu *intel_pt_pmu = perf_pmu__find(INTEL_PT_PMU_NAME);
1083  struct intel_pt_recording *ptr;
1084 
1085  if (!intel_pt_pmu)
1086  return NULL;
1087 
1088  if (setenv("JITDUMP_USE_ARCH_TIMESTAMP", "1", 1)) {
1089  *err = -errno;
1090  return NULL;
1091  }
1092 
1093  ptr = zalloc(sizeof(struct intel_pt_recording));
1094  if (!ptr) {
1095  *err = -ENOMEM;
1096  return NULL;
1097  }
1098 
1099  ptr->intel_pt_pmu = intel_pt_pmu;
1110  return &ptr->itr;
1111 }
bool perf_can_record_switch_events(void)
Definition: record.c:106
size_t auxtrace_snapshot_size
Definition: perf.h:75
static bool intel_pt_compare_buffers(void *buf1, size_t compare_size, void *buf2, size_t offs2, size_t buf2_size)
Definition: intel-pt.c:916
static int intel_pt_pick_bit(int bits, int target)
Definition: intel-pt.c:172
static int intel_pt_snapshot_init(struct intel_pt_recording *ptr, size_t snapshot_buf_size)
Definition: intel-pt.c:889
struct perf_evlist * evlist
Definition: session.h:25
int(* snapshot_start)(struct auxtrace_record *itr)
Definition: auxtrace.h:318
static void sched_switch(struct timechart *tchart, int cpu, u64 timestamp, int prev_pid, int next_pid, u64 prev_state, const char *backtrace)
static size_t intel_pt_snapshot_ref_buf_size(struct intel_pt_recording *ptr, size_t snapshot_buf_size)
Definition: intel-pt.c:864
int parse_events_terms(struct list_head *terms, const char *str)
struct perf_mmap * mmap
Definition: evlist.h:45
size_t len
Definition: auxtrace.h:265
void parse_events_terms__delete(struct list_head *terms)
unsigned int page_size
Definition: util.c:40
static void intel_pt_valid_str(char *str, size_t len, u64 valid)
Definition: intel-pt.c:437
static void intel_pt_copy_ref(void *ref_buf, size_t ref_size, size_t buf_size, void *data, size_t head)
Definition: intel-pt.c:950
static u64 intel_pt_masked_bits(u64 mask, u64 bits)
Definition: intel-pt.c:101
static int intel_pt_alloc_snapshot_ref(struct intel_pt_recording *ptr, int idx, size_t snapshot_buf_size)
Definition: intel-pt.c:848
dictionary data
Definition: stat-cpi.py:4
int ui__warning(const char *format,...)
Definition: util.c:44
bool full_auxtrace
Definition: perf.h:55
int int err
Definition: 5sec.c:44
static int intel_pt_validate_config(struct perf_pmu *intel_pt_pmu, struct perf_evsel *evsel)
Definition: intel-pt.c:523
static bool target__has_task(struct target *target)
Definition: target.h:52
bool system_wide
Definition: evsel.h:124
static int intel_pt_info_fill(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info, size_t priv_size)
Definition: intel-pt.c:321
static u64 rdtsc(void)
Definition: rdpmc.c:26
int(* snapshot_finish)(struct auxtrace_record *itr)
Definition: auxtrace.h:319
static int intel_pt_read_finish(struct auxtrace_record *itr, int idx)
Definition: intel-pt.c:1066
int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,...)
Definition: pmu.c:1431
#define config
#define pr_debug2(fmt,...)
Definition: debug.h:33
size_t(* info_priv_size)(struct auxtrace_record *itr, struct perf_evlist *evlist)
Definition: auxtrace.h:311
static int intel_pt_recording_options(struct auxtrace_record *itr, struct perf_evlist *evlist, struct record_opts *opts)
Definition: intel-pt.c:548
#define perf_evsel__set_sample_bit(evsel, bit)
Definition: evsel.h:260
static bool intel_pt_wrapped(struct intel_pt_recording *ptr, int idx, struct auxtrace_mmap *mm, unsigned char *data, u64 head)
Definition: intel-pt.c:962
Definition: cpumap.h:12
static bool intel_pt_compare_ref(void *ref_buf, size_t ref_offset, size_t ref_size, size_t buf_size, void *data, size_t head)
Definition: intel-pt.c:933
#define KiB(x)
Definition: intel-pt.c:38
struct perf_pmu * intel_pt_pmu
Definition: intel-pt.c:53
int idx
Definition: evsel.h:100
int perf_evsel__disable(struct perf_evsel *evsel)
Definition: evsel.c:1182
static bool target__none(struct target *target)
Definition: target.h:62
u16 time_shift
Definition: tsc.h:10
size_t snapshot_ref_buf_size
Definition: intel-pt.c:59
Definition: pmu.h:22
#define pr_err(fmt,...)
Definition: json.h:21
bool snapshot_init_done
Definition: intel-pt.c:57
bool use_clockid
Definition: perf.h:79
bool supported
Definition: evsel.h:120
int parse_events(struct perf_evlist *evlist, const char *str, struct parse_events_error *err)
struct target target
Definition: perf.h:38
bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
Definition: record.c:259
void * malloc(YYSIZE_T)
static int intel_pt_track_switches(struct perf_evlist *evlist)
Definition: intel-pt.c:409
static size_t intel_pt_filter_bytes(const char *filter)
Definition: intel-pt.c:292
void perf_evlist__set_tracking_event(struct perf_evlist *evlist, struct perf_evsel *tracking_evsel)
Definition: evlist.c:1697
#define roundup(x, y)
Definition: json.h:31
int(* read_finish)(struct auxtrace_record *itr, int idx)
Definition: auxtrace.h:327
const char * name
u64(* reference)(struct auxtrace_record *itr)
Definition: auxtrace.h:326
struct perf_evlist * evlist
Definition: evsel.h:92
static struct perf_session * session
Definition: builtin-lock.c:34
#define INTEL_PT_PSB_PERIOD_NEAR
Definition: intel-pt.c:43
#define evlist__for_each_entry(evlist, evsel)
Definition: evlist.h:247
static bool cpu_map__empty(const struct cpu_map *map)
Definition: cpumap.h:58
void(* free)(struct auxtrace_record *itr)
Definition: auxtrace.h:317
#define INTEL_PT_PMU_NAME
Definition: intel-pt.h:19
static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d)
Definition: intel-pt.c:312
char * filter
Definition: evsel.h:94
struct list_head format
Definition: pmu.h:29
int(* recording_options)(struct auxtrace_record *itr, struct perf_evlist *evlist, struct record_opts *opts)
Definition: auxtrace.h:308
bool perf_can_record_cpu_wide(void)
Definition: record.c:111
static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str, struct perf_evlist *evlist, u64 *res)
Definition: intel-pt.c:120
bool immediate
Definition: evsel.h:123
static int str(yyscan_t scanner, int token)
list cpus
Definition: stat-cpi.py:7
unsigned int mmap_pages
Definition: perf.h:67
static int intel_pt_alloc_snapshot_refs(struct intel_pt_recording *ptr, int idx)
Definition: intel-pt.c:806
static int intel_pt_find_snapshot(struct auxtrace_record *itr, int idx, struct auxtrace_mmap *mm, unsigned char *data, u64 *head, u64 *old)
Definition: intel-pt.c:996
#define CPU(he)
static const char * intel_pt_find_filter(struct perf_evlist *evlist, struct perf_pmu *intel_pt_pmu)
Definition: intel-pt.c:279
void perf_evlist__to_front(struct perf_evlist *evlist, struct perf_evsel *move_evsel)
Definition: evlist.c:1680
struct perf_event_attr * intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)
Definition: intel-pt.c:264
size_t mask
Definition: auxtrace.h:264
x86 movsq based memcpy() in arch/x86/lib/memcpy_64.S") MEMCPY_FN(memcpy_erms
char * name
Definition: pmu.h:23
int(* parse_snapshot_options)(struct auxtrace_record *itr, struct record_opts *opts, const char *str)
Definition: auxtrace.h:323
int perf_event_paranoid(void)
Definition: util.c:388
int nr_mmaps
Definition: evlist.h:32
static int intel_pt_val_config_term(struct perf_pmu *intel_pt_pmu, const char *caps, const char *name, const char *supported, u64 config)
Definition: intel-pt.c:483
#define zfree(ptr)
Definition: util.h:25
int(* find_snapshot)(struct auxtrace_record *itr, int idx, struct auxtrace_mmap *mm, unsigned char *data, u64 *head, u64 *old)
Definition: auxtrace.h:320
bool auxtrace_snapshot_mode
Definition: perf.h:56
int perf_pmu__config_terms(struct list_head *formats, struct perf_event_attr *attr, struct list_head *head_terms, bool zero, struct parse_events_error *err)
Definition: pmu.c:1014
static int intel_pt_snapshot_start(struct auxtrace_record *itr)
Definition: intel-pt.c:780
struct auxtrace_record * intel_pt_recording_init(int *err)
Definition: intel-pt.c:1080
static int intel_pt_parse_terms(struct list_head *formats, const char *str, u64 *config)
Definition: intel-pt.c:94
struct perf_pmu * perf_pmu__find(const char *name)
Definition: pmu.c:778
static bool intel_pt_first_wrap(u64 *data, size_t buf_size)
Definition: intel-pt.c:979
static size_t intel_pt_info_priv_size(struct auxtrace_record *itr, struct perf_evlist *evlist)
Definition: intel-pt.c:300
struct strfilter * filter
Definition: builtin-probe.c:60
static int __get_cpuid(char *buffer, size_t sz, const char *fmt)
Definition: header.c:24
static u64 intel_pt_default_config(struct perf_pmu *intel_pt_pmu)
Definition: intel-pt.c:188
struct intel_pt_snapshot_ref * snapshot_refs
Definition: intel-pt.c:61
struct perf_evlist * evlist
Definition: intel-pt.c:55
int perf_evsel__enable(struct perf_evsel *evsel)
Definition: evsel.c:1175
static int intel_pt_parse_snapshot_options(struct auxtrace_record *itr, struct record_opts *opts, const char *str)
Definition: intel-pt.c:240
bool selectable
Definition: pmu.h:25
void free(void *)
static void intel_pt_recording_free(struct auxtrace_record *itr)
Definition: intel-pt.c:839
static struct perf_evsel * intel_pt_evsel(struct intel_pt *pt, struct perf_evlist *evlist)
Definition: intel-pt.c:2153
static int intel_pt_parse_terms_with_default(struct list_head *formats, const char *str, u64 *config)
Definition: intel-pt.c:65
struct auxtrace_record itr
Definition: intel-pt.c:52
static int intel_pt_snapshot_finish(struct auxtrace_record *itr)
Definition: intel-pt.c:793
#define perf_evsel__reset_sample_bit(evsel, bit)
Definition: evsel.h:263
struct cpu_map * cpus
Definition: evlist.h:48
Definition: attr.py:1
__u32 type
Definition: pmu.h:24
static struct perf_evsel * perf_evlist__last(struct perf_evlist *evlist)
Definition: evlist.h:220
void * base
Definition: mmap.h:18
static void intel_pt_free_snapshot_refs(struct intel_pt_recording *ptr)
Definition: intel-pt.c:830
static u64 intel_pt_reference(struct auxtrace_record *itr __maybe_unused)
Definition: intel-pt.c:1061
bool no_aux_samples
Definition: evsel.h:122
size_t priv_size
Definition: intel-pt.c:62
static size_t intel_pt_psb_period(struct perf_pmu *intel_pt_pmu, struct perf_evlist *evlist)
Definition: intel-pt.c:142
unsigned int auxtrace_mmap_pages
Definition: perf.h:68
int(* info_fill)(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info, size_t priv_size)
Definition: auxtrace.h:313
#define pr_debug3(fmt,...)
Definition: debug.h:34
int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, struct perf_tsc_conversion *tc)
Definition: tsc.c:12
struct perf_event_attr attr
Definition: evsel.h:93
bool record_switch_events
Definition: perf.h:58
Definition: target.h:8
__u64 perf_pmu__format_bits(struct list_head *formats, const char *name)
Definition: pmu.c:806
size_t snapshot_size
Definition: intel-pt.c:58
int perf_evlist__enable_event_idx(struct perf_evlist *evlist, struct perf_evsel *evsel, int idx)
Definition: evlist.c:422
#define MiB(x)
Definition: intel-pt.c:39
void static void * zalloc(size_t size)
Definition: util.h:20