diff options
Diffstat (limited to 'tools/perf/util/intel-pt.c')
| -rw-r--r-- | tools/perf/util/intel-pt.c | 135 | 
1 files changed, 77 insertions, 58 deletions
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index df061599fef4..a1c9eb6d4f40 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -9,10 +9,10 @@  #include <stdbool.h>  #include <errno.h>  #include <linux/kernel.h> +#include <linux/string.h>  #include <linux/types.h>  #include <linux/zalloc.h> -#include "../perf.h"  #include "session.h"  #include "machine.h"  #include "memswap.h" @@ -33,6 +33,7 @@  #include "tsc.h"  #include "intel-pt.h"  #include "config.h" +#include "util/synthetic-events.h"  #include "time-utils.h"  #include "../arch/x86/include/uapi/asm/perf_regs.h" @@ -56,7 +57,7 @@ struct intel_pt {  	u32 auxtrace_type;  	struct perf_session *session;  	struct machine *machine; -	struct perf_evsel *switch_evsel; +	struct evsel *switch_evsel;  	struct thread *unknown_thread;  	bool timeless_decoding;  	bool sampling_mode; @@ -104,7 +105,7 @@ struct intel_pt {  	u64 cbr_id;  	bool sample_pebs; -	struct perf_evsel *pebs_evsel; +	struct evsel *pebs_evsel;  	u64 tsc_bit;  	u64 mtc_bit; @@ -723,11 +724,11 @@ static bool intel_pt_get_config(struct intel_pt *pt,  static bool intel_pt_exclude_kernel(struct intel_pt *pt)  { -	struct perf_evsel *evsel; +	struct evsel *evsel;  	evlist__for_each_entry(pt->session->evlist, evsel) { -		if (intel_pt_get_config(pt, &evsel->attr, NULL) && -		    !evsel->attr.exclude_kernel) +		if (intel_pt_get_config(pt, &evsel->core.attr, NULL) && +		    !evsel->core.attr.exclude_kernel)  			return false;  	}  	return true; @@ -735,14 +736,14 @@ static bool intel_pt_exclude_kernel(struct intel_pt *pt)  static bool intel_pt_return_compression(struct intel_pt *pt)  { -	struct perf_evsel *evsel; +	struct evsel *evsel;  	u64 config;  	if (!pt->noretcomp_bit)  		return true;  	evlist__for_each_entry(pt->session->evlist, evsel) { -		if (intel_pt_get_config(pt, &evsel->attr, &config) && +		if (intel_pt_get_config(pt, &evsel->core.attr, &config) &&  		    (config & pt->noretcomp_bit))  			return false;  	} @@ -751,11 +752,11 @@ static bool intel_pt_return_compression(struct intel_pt *pt)  static bool intel_pt_branch_enable(struct intel_pt *pt)  { -	struct perf_evsel *evsel; +	struct evsel *evsel;  	u64 config;  	evlist__for_each_entry(pt->session->evlist, evsel) { -		if (intel_pt_get_config(pt, &evsel->attr, &config) && +		if (intel_pt_get_config(pt, &evsel->core.attr, &config) &&  		    (config & 1) && !(config & 0x2000))  			return false;  	} @@ -764,7 +765,7 @@ static bool intel_pt_branch_enable(struct intel_pt *pt)  static unsigned int intel_pt_mtc_period(struct intel_pt *pt)  { -	struct perf_evsel *evsel; +	struct evsel *evsel;  	unsigned int shift;  	u64 config; @@ -775,7 +776,7 @@ static unsigned int intel_pt_mtc_period(struct intel_pt *pt)  		config >>= 1;  	evlist__for_each_entry(pt->session->evlist, evsel) { -		if (intel_pt_get_config(pt, &evsel->attr, &config)) +		if (intel_pt_get_config(pt, &evsel->core.attr, &config))  			return (config & pt->mtc_freq_bits) >> shift;  	}  	return 0; @@ -783,7 +784,7 @@ static unsigned int intel_pt_mtc_period(struct intel_pt *pt)  static bool intel_pt_timeless_decoding(struct intel_pt *pt)  { -	struct perf_evsel *evsel; +	struct evsel *evsel;  	bool timeless_decoding = true;  	u64 config; @@ -791,9 +792,9 @@ static bool intel_pt_timeless_decoding(struct intel_pt *pt)  		return true;  	evlist__for_each_entry(pt->session->evlist, evsel) { -		if (!(evsel->attr.sample_type & PERF_SAMPLE_TIME)) +		if (!(evsel->core.attr.sample_type & PERF_SAMPLE_TIME))  			return true; -		if (intel_pt_get_config(pt, &evsel->attr, &config)) { +		if (intel_pt_get_config(pt, &evsel->core.attr, &config)) {  			if (config & pt->tsc_bit)  				timeless_decoding = false;  			else @@ -805,11 +806,11 @@ static bool intel_pt_timeless_decoding(struct intel_pt *pt)  static bool intel_pt_tracing_kernel(struct intel_pt *pt)  { -	struct perf_evsel *evsel; +	struct evsel *evsel;  	evlist__for_each_entry(pt->session->evlist, evsel) { -		if (intel_pt_get_config(pt, &evsel->attr, NULL) && -		    !evsel->attr.exclude_kernel) +		if (intel_pt_get_config(pt, &evsel->core.attr, NULL) && +		    !evsel->core.attr.exclude_kernel)  			return true;  	}  	return false; @@ -817,7 +818,7 @@ static bool intel_pt_tracing_kernel(struct intel_pt *pt)  static bool intel_pt_have_tsc(struct intel_pt *pt)  { -	struct perf_evsel *evsel; +	struct evsel *evsel;  	bool have_tsc = false;  	u64 config; @@ -825,7 +826,7 @@ static bool intel_pt_have_tsc(struct intel_pt *pt)  		return false;  	evlist__for_each_entry(pt->session->evlist, evsel) { -		if (intel_pt_get_config(pt, &evsel->attr, &config)) { +		if (intel_pt_get_config(pt, &evsel->core.attr, &config)) {  			if (config & pt->tsc_bit)  				have_tsc = true;  			else @@ -1702,9 +1703,9 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)  	struct perf_sample sample = { .ip = 0, };  	union perf_event *event = ptq->event_buf;  	struct intel_pt *pt = ptq->pt; -	struct perf_evsel *evsel = pt->pebs_evsel; -	u64 sample_type = evsel->attr.sample_type; -	u64 id = evsel->id[0]; +	struct evsel *evsel = pt->pebs_evsel; +	u64 sample_type = evsel->core.attr.sample_type; +	u64 id = evsel->core.id[0];  	u8 cpumode;  	if (intel_pt_skip_event(pt)) @@ -1715,8 +1716,8 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)  	sample.id = id;  	sample.stream_id = id; -	if (!evsel->attr.freq) -		sample.period = evsel->attr.sample_period; +	if (!evsel->core.attr.freq) +		sample.period = evsel->core.attr.sample_period;  	/* No support for non-zero CS base */  	if (items->has_ip) @@ -1757,7 +1758,7 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)  	if (sample_type & PERF_SAMPLE_REGS_INTR &&  	    items->mask[INTEL_PT_GP_REGS_POS]) {  		u64 regs[sizeof(sample.intr_regs.mask)]; -		u64 regs_mask = evsel->attr.sample_regs_intr; +		u64 regs_mask = evsel->core.attr.sample_regs_intr;  		u64 *pos;  		sample.intr_regs.abi = items->is_32_bit ? @@ -2401,7 +2402,7 @@ static int intel_pt_sync_switch(struct intel_pt *pt, int cpu, pid_t tid,  static int intel_pt_process_switch(struct intel_pt *pt,  				   struct perf_sample *sample)  { -	struct perf_evsel *evsel; +	struct evsel *evsel;  	pid_t tid;  	int cpu, ret; @@ -2713,13 +2714,13 @@ static int intel_pt_synth_event(struct perf_session *session, const char *name,  	return err;  } -static void intel_pt_set_event_name(struct perf_evlist *evlist, u64 id, +static void intel_pt_set_event_name(struct evlist *evlist, u64 id,  				    const char *name)  { -	struct perf_evsel *evsel; +	struct evsel *evsel;  	evlist__for_each_entry(evlist, evsel) { -		if (evsel->id && evsel->id[0] == id) { +		if (evsel->core.id && evsel->core.id[0] == id) {  			if (evsel->name)  				zfree(&evsel->name);  			evsel->name = strdup(name); @@ -2728,13 +2729,13 @@ static void intel_pt_set_event_name(struct perf_evlist *evlist, u64 id,  	}  } -static struct perf_evsel *intel_pt_evsel(struct intel_pt *pt, -					 struct perf_evlist *evlist) +static struct evsel *intel_pt_evsel(struct intel_pt *pt, +					 struct evlist *evlist)  { -	struct perf_evsel *evsel; +	struct evsel *evsel;  	evlist__for_each_entry(evlist, evsel) { -		if (evsel->attr.type == pt->pmu_type && evsel->ids) +		if (evsel->core.attr.type == pt->pmu_type && evsel->core.ids)  			return evsel;  	} @@ -2744,8 +2745,8 @@ static struct perf_evsel *intel_pt_evsel(struct intel_pt *pt,  static int intel_pt_synth_events(struct intel_pt *pt,  				 struct perf_session *session)  { -	struct perf_evlist *evlist = session->evlist; -	struct perf_evsel *evsel = intel_pt_evsel(pt, evlist); +	struct evlist *evlist = session->evlist; +	struct evsel *evsel = intel_pt_evsel(pt, evlist);  	struct perf_event_attr attr;  	u64 id;  	int err; @@ -2758,7 +2759,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,  	memset(&attr, 0, sizeof(struct perf_event_attr));  	attr.size = sizeof(struct perf_event_attr);  	attr.type = PERF_TYPE_HARDWARE; -	attr.sample_type = evsel->attr.sample_type & PERF_SAMPLE_MASK; +	attr.sample_type = evsel->core.attr.sample_type & PERF_SAMPLE_MASK;  	attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |  			    PERF_SAMPLE_PERIOD;  	if (pt->timeless_decoding) @@ -2767,15 +2768,15 @@ static int intel_pt_synth_events(struct intel_pt *pt,  		attr.sample_type |= PERF_SAMPLE_TIME;  	if (!pt->per_cpu_mmaps)  		attr.sample_type &= ~(u64)PERF_SAMPLE_CPU; -	attr.exclude_user = evsel->attr.exclude_user; -	attr.exclude_kernel = evsel->attr.exclude_kernel; -	attr.exclude_hv = evsel->attr.exclude_hv; -	attr.exclude_host = evsel->attr.exclude_host; -	attr.exclude_guest = evsel->attr.exclude_guest; -	attr.sample_id_all = evsel->attr.sample_id_all; -	attr.read_format = evsel->attr.read_format; - -	id = evsel->id[0] + 1000000000; +	attr.exclude_user = evsel->core.attr.exclude_user; +	attr.exclude_kernel = evsel->core.attr.exclude_kernel; +	attr.exclude_hv = evsel->core.attr.exclude_hv; +	attr.exclude_host = evsel->core.attr.exclude_host; +	attr.exclude_guest = evsel->core.attr.exclude_guest; +	attr.sample_id_all = evsel->core.attr.sample_id_all; +	attr.read_format = evsel->core.attr.read_format; + +	id = evsel->core.id[0] + 1000000000;  	if (!id)  		id = 1; @@ -2857,7 +2858,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,  		id += 1;  	} -	if (pt->synth_opts.pwr_events && (evsel->attr.config & 0x10)) { +	if (pt->synth_opts.pwr_events && (evsel->core.attr.config & 0x10)) {  		attr.config = PERF_SYNTH_INTEL_MWAIT;  		err = intel_pt_synth_event(session, "mwait", &attr, id);  		if (err) @@ -2894,9 +2895,25 @@ static int intel_pt_synth_events(struct intel_pt *pt,  	return 0;  } -static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist) +static void intel_pt_setup_pebs_events(struct intel_pt *pt)  { -	struct perf_evsel *evsel; +	struct evsel *evsel; + +	if (!pt->synth_opts.other_events) +		return; + +	evlist__for_each_entry(pt->session->evlist, evsel) { +		if (evsel->core.attr.aux_output && evsel->core.id) { +			pt->sample_pebs = true; +			pt->pebs_evsel = evsel; +			return; +		} +	} +} + +static struct evsel *intel_pt_find_sched_switch(struct evlist *evlist) +{ +	struct evsel *evsel;  	evlist__for_each_entry_reverse(evlist, evsel) {  		const char *name = perf_evsel__name(evsel); @@ -2908,12 +2925,12 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist)  	return NULL;  } -static bool intel_pt_find_switch(struct perf_evlist *evlist) +static bool intel_pt_find_switch(struct evlist *evlist)  { -	struct perf_evsel *evsel; +	struct evsel *evsel;  	evlist__for_each_entry(evlist, evsel) { -		if (evsel->attr.context_switch) +		if (evsel->core.attr.context_switch)  			return true;  	} @@ -3028,7 +3045,7 @@ static const char * const intel_pt_info_fmts[] = {  	[INTEL_PT_FILTER_STR_LEN]	= "  Filter string len.  %"PRIu64"\n",  }; -static void intel_pt_print_info(u64 *arr, int start, int finish) +static void intel_pt_print_info(__u64 *arr, int start, int finish)  {  	int i; @@ -3047,23 +3064,23 @@ static void intel_pt_print_info_str(const char *name, const char *str)  	fprintf(stdout, "  %-20s%s\n", name, str ? str : "");  } -static bool intel_pt_has(struct auxtrace_info_event *auxtrace_info, int pos) +static bool intel_pt_has(struct perf_record_auxtrace_info *auxtrace_info, int pos)  {  	return auxtrace_info->header.size >= -		sizeof(struct auxtrace_info_event) + (sizeof(u64) * (pos + 1)); +		sizeof(struct perf_record_auxtrace_info) + (sizeof(u64) * (pos + 1));  }  int intel_pt_process_auxtrace_info(union perf_event *event,  				   struct perf_session *session)  { -	struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info; +	struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;  	size_t min_sz = sizeof(u64) * INTEL_PT_PER_CPU_MMAPS;  	struct intel_pt *pt;  	void *info_end; -	u64 *info; +	__u64 *info;  	int err; -	if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) + +	if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info) +  					min_sz)  		return -EINVAL; @@ -3263,6 +3280,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,  	if (err)  		goto err_delete_thread; +	intel_pt_setup_pebs_events(pt); +  	err = auxtrace_queues__process_index(&pt->queues, session);  	if (err)  		goto err_delete_thread;  |