18 #include <linux/kernel.h> 19 #include <linux/types.h> 20 #include <linux/bitops.h> 21 #include <linux/log2.h> 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" 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) 43 #define INTEL_PT_PSB_PERIOD_NEAR 256 69 struct list_head *terms;
70 struct perf_event_attr attr = { .size = 0, };
73 terms =
malloc(
sizeof(
struct list_head));
77 INIT_LIST_HEAD(terms);
88 *config = attr.config;
103 const u64 top_bit = 1ULL << 63;
107 for (i = 0; i < 64; i++) {
108 if (mask & top_bit) {
133 if (evsel->
attr.type == intel_pt_pmu->
type) {
146 int err, topa_multiple_entries;
150 "%d", &topa_multiple_entries) != 1)
151 topa_multiple_entries = 0;
157 if (!topa_multiple_entries) {
166 psb_period = 1 << (val + 11);
168 pr_debug2(
"%s psb_period %zu\n", intel_pt_pmu->
name, psb_period);
176 for (pos = 0; bits; bits >>= 1, pos++) {
178 if (pos <= target || pick < 0)
191 int mtc, mtc_periods = 0, mtc_period;
192 int psb_cyc, psb_periods, psb_period;
197 pos += scnprintf(buf + pos,
sizeof(buf) - pos,
"tsc");
209 pos += scnprintf(buf + pos,
sizeof(buf) - pos,
210 ",mtc,mtc_period=%d", mtc_period);
218 if (psb_cyc && mtc_periods) {
224 pos += scnprintf(buf + pos,
sizeof(buf) - pos,
225 ",psb_period=%d", psb_period);
231 pos += scnprintf(buf + pos,
sizeof(buf) - pos,
",pt,branch");
233 pr_debug2(
"%s default config: %s\n", intel_pt_pmu->
name, buf);
250 snapshot_size = strtoull(str, &endptr, 0);
251 if (*endptr || snapshot_size > SIZE_MAX)
263 struct perf_event_attr *
266 struct perf_event_attr *
attr;
268 attr =
zalloc(
sizeof(
struct perf_event_attr));
285 if (evsel->
attr.type == intel_pt_pmu->
type)
294 size_t len = filter ? strlen(filter) : 0;
296 return len ?
roundup(len + 1, 8) : 0;
314 unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
329 struct perf_event_mmap_page *pc;
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;
354 "%lu", &max_non_turbo_ratio) != 1)
355 max_non_turbo_ratio = 0;
358 filter_str_len = filter ? strlen(filter) : 0;
367 if (err != -EOPNOTSUPP)
372 if (!cap_user_time_zero)
373 ui__warning(
"Intel Processor Trace: TSC not available\n");
399 if (filter_str_len) {
402 strncpy((
char *)info, filter, len);
420 pr_debug2(
"%s: failed to parse %s, error %d\n",
421 __func__, sched_switch, err);
439 unsigned int val, last = 0,
state = 1;
444 for (val = 0; val <= 64; val++, valid >>= 1) {
449 p += scnprintf(str + p, len - p,
",");
452 p += scnprintf(str + p, len - p,
"%u", val);
467 p += scnprintf(str + p, len - p,
",%u", last);
471 p += scnprintf(str + p, len - p,
"-%u", last);
484 const char *caps,
const char *
name,
489 unsigned long long valid;
506 for (shift = 0; bits && !(bits & 1); shift++)
514 if (valid & (1 << config))
518 pr_err(
"Invalid %s for %s. Valid values are: %s\n",
532 "cyc_thresh",
"caps/psb_cyc",
538 "mtc_period",
"caps/mtc",
544 "psb_period",
"caps/psb_cyc",
555 bool have_timing_info, need_immediate =
false;
566 if (evsel->
attr.type == intel_pt_pmu->
type) {
567 if (intel_pt_evsel) {
571 evsel->
attr.freq = 0;
572 evsel->
attr.sample_period = 1;
573 intel_pt_evsel = evsel;
622 pr_err(
"Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n",
628 pr_err(
"Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n");
631 pr_debug2(
"Intel PT snapshot size: %zu\n",
636 ui__warning(
"Intel PT snapshot size (%zu) may be too small for PSB period (%zu)\n",
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",
671 have_timing_info =
true;
673 have_timing_info =
false;
693 switch_evsel->
attr.freq = 0;
694 switch_evsel->
attr.sample_period = 1;
695 switch_evsel->
attr.context_switch = 1;
710 need_immediate =
true;
719 pr_debug2(
"Unable to select sched:sched_switch\n");
727 if (intel_pt_evsel) {
753 tracking_evsel->
attr.freq = 0;
754 tracking_evsel->
attr.sample_period = 1;
775 ui__warning(
"Intel Processor Trace decoding will not be possible except for kernel tracing!\n");
815 while (new_cnt <= idx)
818 refs = calloc(new_cnt, sz);
849 size_t snapshot_buf_size)
854 ref_buf =
zalloc(ref_buf_size);
865 size_t snapshot_buf_size)
867 const size_t max_size = 256 * 1024;
868 size_t buf_size = 0, psb_period;
875 buf_size = psb_period * 2;
877 if (!buf_size || buf_size > max_size)
880 if (buf_size >= snapshot_buf_size)
890 size_t snapshot_buf_size)
917 void *buf2,
size_t offs2,
size_t buf2_size)
919 size_t end2 = offs2 + compare_size, part_size;
921 if (end2 <= buf2_size)
922 return memcmp(buf1, buf2 + offs2, compare_size);
924 part_size = end2 - buf2_size;
925 if (memcmp(buf1, buf2 + offs2, part_size))
928 compare_size -= part_size;
930 return memcmp(buf1 + part_size, buf2, compare_size);
934 size_t ref_size,
size_t buf_size,
935 void *
data,
size_t head)
937 size_t ref_end = ref_offset + ref_size;
939 if (ref_end > buf_size) {
940 if (head > ref_offset || head < ref_end - buf_size)
942 }
else if (head > ref_offset && head < ref_end) {
951 void *
data,
size_t head)
953 if (head >= ref_size) {
954 memcpy(ref_buf, data + head - ref_size, ref_size);
956 memcpy(ref_buf, data, head);
958 memcpy(ref_buf + head, data + buf_size - ref_size, ref_size);
988 for (i = a; i < b; i++) {
1005 pr_debug3(
"%s: mmap index %d old head %zu new head %zu\n",
1006 __func__, idx, (
size_t)*old, (
size_t)*head);
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);
1057 pr_err(
"%s: failed, error %d\n", __func__, err);
1088 if (setenv(
"JITDUMP_USE_ARCH_TIMESTAMP",
"1", 1)) {
bool perf_can_record_switch_events(void)
size_t auxtrace_snapshot_size
static bool intel_pt_compare_buffers(void *buf1, size_t compare_size, void *buf2, size_t offs2, size_t buf2_size)
static int intel_pt_pick_bit(int bits, int target)
static int intel_pt_snapshot_init(struct intel_pt_recording *ptr, size_t snapshot_buf_size)
struct perf_evlist * evlist
int(* snapshot_start)(struct auxtrace_record *itr)
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)
int parse_events_terms(struct list_head *terms, const char *str)
void parse_events_terms__delete(struct list_head *terms)
static void intel_pt_valid_str(char *str, size_t len, u64 valid)
static void intel_pt_copy_ref(void *ref_buf, size_t ref_size, size_t buf_size, void *data, size_t head)
static u64 intel_pt_masked_bits(u64 mask, u64 bits)
static int intel_pt_alloc_snapshot_ref(struct intel_pt_recording *ptr, int idx, size_t snapshot_buf_size)
int ui__warning(const char *format,...)
static int intel_pt_validate_config(struct perf_pmu *intel_pt_pmu, struct perf_evsel *evsel)
static bool target__has_task(struct target *target)
static int intel_pt_info_fill(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info, size_t priv_size)
int(* snapshot_finish)(struct auxtrace_record *itr)
static int intel_pt_read_finish(struct auxtrace_record *itr, int idx)
int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,...)
#define pr_debug2(fmt,...)
size_t(* info_priv_size)(struct auxtrace_record *itr, struct perf_evlist *evlist)
static int intel_pt_recording_options(struct auxtrace_record *itr, struct perf_evlist *evlist, struct record_opts *opts)
#define perf_evsel__set_sample_bit(evsel, bit)
static bool intel_pt_wrapped(struct intel_pt_recording *ptr, int idx, struct auxtrace_mmap *mm, unsigned char *data, u64 head)
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)
struct perf_pmu * intel_pt_pmu
int perf_evsel__disable(struct perf_evsel *evsel)
static bool target__none(struct target *target)
size_t snapshot_ref_buf_size
int parse_events(struct perf_evlist *evlist, const char *str, struct parse_events_error *err)
bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
static int intel_pt_track_switches(struct perf_evlist *evlist)
static size_t intel_pt_filter_bytes(const char *filter)
void perf_evlist__set_tracking_event(struct perf_evlist *evlist, struct perf_evsel *tracking_evsel)
int(* read_finish)(struct auxtrace_record *itr, int idx)
u64(* reference)(struct auxtrace_record *itr)
struct perf_evlist * evlist
static struct perf_session * session
#define INTEL_PT_PSB_PERIOD_NEAR
#define evlist__for_each_entry(evlist, evsel)
static bool cpu_map__empty(const struct cpu_map *map)
void(* free)(struct auxtrace_record *itr)
#define INTEL_PT_PMU_NAME
static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d)
int(* recording_options)(struct auxtrace_record *itr, struct perf_evlist *evlist, struct record_opts *opts)
bool perf_can_record_cpu_wide(void)
static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str, struct perf_evlist *evlist, u64 *res)
static int str(yyscan_t scanner, int token)
static int intel_pt_alloc_snapshot_refs(struct intel_pt_recording *ptr, int idx)
static int intel_pt_find_snapshot(struct auxtrace_record *itr, int idx, struct auxtrace_mmap *mm, unsigned char *data, u64 *head, u64 *old)
static const char * intel_pt_find_filter(struct perf_evlist *evlist, struct perf_pmu *intel_pt_pmu)
void perf_evlist__to_front(struct perf_evlist *evlist, struct perf_evsel *move_evsel)
struct perf_event_attr * intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)
x86 movsq based memcpy() in arch/x86/lib/memcpy_64.S") MEMCPY_FN(memcpy_erms
int(* parse_snapshot_options)(struct auxtrace_record *itr, struct record_opts *opts, const char *str)
int perf_event_paranoid(void)
static int intel_pt_val_config_term(struct perf_pmu *intel_pt_pmu, const char *caps, const char *name, const char *supported, u64 config)
int(* find_snapshot)(struct auxtrace_record *itr, int idx, struct auxtrace_mmap *mm, unsigned char *data, u64 *head, u64 *old)
bool auxtrace_snapshot_mode
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)
static int intel_pt_snapshot_start(struct auxtrace_record *itr)
struct auxtrace_record * intel_pt_recording_init(int *err)
static int intel_pt_parse_terms(struct list_head *formats, const char *str, u64 *config)
struct perf_pmu * perf_pmu__find(const char *name)
static bool intel_pt_first_wrap(u64 *data, size_t buf_size)
static size_t intel_pt_info_priv_size(struct auxtrace_record *itr, struct perf_evlist *evlist)
struct strfilter * filter
static u64 intel_pt_default_config(struct perf_pmu *intel_pt_pmu)
struct intel_pt_snapshot_ref * snapshot_refs
struct perf_evlist * evlist
int perf_evsel__enable(struct perf_evsel *evsel)
static int intel_pt_parse_snapshot_options(struct auxtrace_record *itr, struct record_opts *opts, const char *str)
static void intel_pt_recording_free(struct auxtrace_record *itr)
static struct perf_evsel * intel_pt_evsel(struct intel_pt *pt, struct perf_evlist *evlist)
static int intel_pt_parse_terms_with_default(struct list_head *formats, const char *str, u64 *config)
struct auxtrace_record itr
static int intel_pt_snapshot_finish(struct auxtrace_record *itr)
#define perf_evsel__reset_sample_bit(evsel, bit)
static struct perf_evsel * perf_evlist__last(struct perf_evlist *evlist)
static void intel_pt_free_snapshot_refs(struct intel_pt_recording *ptr)
static u64 intel_pt_reference(struct auxtrace_record *itr __maybe_unused)
static size_t intel_pt_psb_period(struct perf_pmu *intel_pt_pmu, struct perf_evlist *evlist)
unsigned int auxtrace_mmap_pages
int(* info_fill)(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info, size_t priv_size)
#define pr_debug3(fmt,...)
int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, struct perf_tsc_conversion *tc)
struct perf_event_attr attr
bool record_switch_events
__u64 perf_pmu__format_bits(struct list_head *formats, const char *name)
int perf_evlist__enable_event_idx(struct perf_evlist *evlist, struct perf_evsel *evsel, int idx)
void static void * zalloc(size_t size)