perf tools: Add support for PERF_RECORD_AUX_OUTPUT_HW_ID

The PERF_RECORD_AUX_OUTPUT_HW_ID event provides a way to match AUX output
data like Intel PT PEBS-via-PT back to the event that it came from, by
providing a hardware ID that is present in the AUX output.

Reviewed-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: x86@kernel.org
Link: http://lore.kernel.org/lkml/20210907163903.11820-3-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Adrian Hunter 2021-09-07 19:39:02 +03:00 committed by Arnaldo Carvalho de Melo
parent 70ae034d49
commit 6175047358
10 changed files with 66 additions and 2 deletions

View file

@ -1141,6 +1141,21 @@ enum perf_event_type {
*/ */
PERF_RECORD_TEXT_POKE = 20, PERF_RECORD_TEXT_POKE = 20,
/*
* Data written to the AUX area by hardware due to aux_output, may need
* to be matched to the event by an architecture-specific hardware ID.
* This records the hardware ID, but requires sample_id to provide the
* event ID. e.g. Intel PT uses this record to disambiguate PEBS-via-PT
* records from multiple events.
*
* struct {
* struct perf_event_header header;
* u64 hw_id;
* struct sample_id sample_id;
* };
*/
PERF_RECORD_AUX_OUTPUT_HW_ID = 21,
PERF_RECORD_MAX, /* non-ABI */ PERF_RECORD_MAX, /* non-ABI */
}; };

View file

@ -289,6 +289,11 @@ struct perf_record_itrace_start {
__u32 tid; __u32 tid;
}; };
struct perf_record_aux_output_hw_id {
struct perf_event_header header;
__u64 hw_id;
};
struct perf_record_thread_map_entry { struct perf_record_thread_map_entry {
__u64 pid; __u64 pid;
char comm[16]; char comm[16];
@ -414,6 +419,7 @@ union perf_event {
struct perf_record_auxtrace_error auxtrace_error; struct perf_record_auxtrace_error auxtrace_error;
struct perf_record_aux aux; struct perf_record_aux aux;
struct perf_record_itrace_start itrace_start; struct perf_record_itrace_start itrace_start;
struct perf_record_aux_output_hw_id aux_output_hw_id;
struct perf_record_switch context_switch; struct perf_record_switch context_switch;
struct perf_record_thread_map thread_map; struct perf_record_thread_map thread_map;
struct perf_record_cpu_map cpu_map; struct perf_record_cpu_map cpu_map;

View file

@ -815,7 +815,8 @@ static int __cmd_inject(struct perf_inject *inject)
inject->tool.auxtrace_info = perf_event__process_auxtrace_info; inject->tool.auxtrace_info = perf_event__process_auxtrace_info;
inject->tool.auxtrace = perf_event__process_auxtrace; inject->tool.auxtrace = perf_event__process_auxtrace;
inject->tool.aux = perf_event__drop_aux; inject->tool.aux = perf_event__drop_aux;
inject->tool.itrace_start = perf_event__drop_aux, inject->tool.itrace_start = perf_event__drop_aux;
inject->tool.aux_output_hw_id = perf_event__drop_aux;
inject->tool.ordered_events = true; inject->tool.ordered_events = true;
inject->tool.ordering_requires_timestamps = true; inject->tool.ordering_requires_timestamps = true;
/* Allow space in the header for new attributes */ /* Allow space in the header for new attributes */
@ -882,6 +883,7 @@ int cmd_inject(int argc, const char **argv)
.lost_samples = perf_event__repipe, .lost_samples = perf_event__repipe,
.aux = perf_event__repipe, .aux = perf_event__repipe,
.itrace_start = perf_event__repipe, .itrace_start = perf_event__repipe,
.aux_output_hw_id = perf_event__repipe,
.context_switch = perf_event__repipe, .context_switch = perf_event__repipe,
.throttle = perf_event__repipe, .throttle = perf_event__repipe,
.unthrottle = perf_event__repipe, .unthrottle = perf_event__repipe,

View file

@ -1411,7 +1411,7 @@ static int record__synthesize(struct record *rec, bool tail)
goto out; goto out;
/* Synthesize id_index before auxtrace_info */ /* Synthesize id_index before auxtrace_info */
if (rec->opts.auxtrace_sample_mode) { if (rec->opts.auxtrace_sample_mode || rec->opts.full_auxtrace) {
err = perf_event__synthesize_id_index(tool, err = perf_event__synthesize_id_index(tool,
process_synthesized_event, process_synthesized_event,
session->evlist, machine); session->evlist, machine);

View file

@ -57,6 +57,7 @@ static const char *perf_event__names[] = {
[PERF_RECORD_BPF_EVENT] = "BPF_EVENT", [PERF_RECORD_BPF_EVENT] = "BPF_EVENT",
[PERF_RECORD_CGROUP] = "CGROUP", [PERF_RECORD_CGROUP] = "CGROUP",
[PERF_RECORD_TEXT_POKE] = "TEXT_POKE", [PERF_RECORD_TEXT_POKE] = "TEXT_POKE",
[PERF_RECORD_AUX_OUTPUT_HW_ID] = "AUX_OUTPUT_HW_ID",
[PERF_RECORD_HEADER_ATTR] = "ATTR", [PERF_RECORD_HEADER_ATTR] = "ATTR",
[PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
[PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
@ -237,6 +238,14 @@ int perf_event__process_itrace_start(struct perf_tool *tool __maybe_unused,
return machine__process_itrace_start_event(machine, event); return machine__process_itrace_start_event(machine, event);
} }
int perf_event__process_aux_output_hw_id(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample __maybe_unused,
struct machine *machine)
{
return machine__process_aux_output_hw_id_event(machine, event);
}
int perf_event__process_lost_samples(struct perf_tool *tool __maybe_unused, int perf_event__process_lost_samples(struct perf_tool *tool __maybe_unused,
union perf_event *event, union perf_event *event,
struct perf_sample *sample, struct perf_sample *sample,
@ -407,6 +416,12 @@ size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp)
event->itrace_start.pid, event->itrace_start.tid); event->itrace_start.pid, event->itrace_start.tid);
} }
size_t perf_event__fprintf_aux_output_hw_id(union perf_event *event, FILE *fp)
{
return fprintf(fp, " hw_id: %#"PRI_lx64"\n",
event->aux_output_hw_id.hw_id);
}
size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp) size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp)
{ {
bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT; bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT;
@ -534,6 +549,9 @@ size_t perf_event__fprintf(union perf_event *event, struct machine *machine, FIL
case PERF_RECORD_TEXT_POKE: case PERF_RECORD_TEXT_POKE:
ret += perf_event__fprintf_text_poke(event, machine, fp); ret += perf_event__fprintf_text_poke(event, machine, fp);
break; break;
case PERF_RECORD_AUX_OUTPUT_HW_ID:
ret += perf_event__fprintf_aux_output_hw_id(event, fp);
break;
default: default:
ret += fprintf(fp, "\n"); ret += fprintf(fp, "\n");
} }

View file

@ -330,6 +330,10 @@ int perf_event__process_itrace_start(struct perf_tool *tool,
union perf_event *event, union perf_event *event,
struct perf_sample *sample, struct perf_sample *sample,
struct machine *machine); struct machine *machine);
int perf_event__process_aux_output_hw_id(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct machine *machine);
int perf_event__process_switch(struct perf_tool *tool, int perf_event__process_switch(struct perf_tool *tool,
union perf_event *event, union perf_event *event,
struct perf_sample *sample, struct perf_sample *sample,
@ -397,6 +401,7 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_task(union perf_event *event, FILE *fp); size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp); size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp); size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_aux_output_hw_id(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp); size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp); size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp); size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp);

View file

@ -755,6 +755,14 @@ int machine__process_itrace_start_event(struct machine *machine __maybe_unused,
return 0; return 0;
} }
int machine__process_aux_output_hw_id_event(struct machine *machine __maybe_unused,
union perf_event *event)
{
if (dump_trace)
perf_event__fprintf_aux_output_hw_id(event, stdout);
return 0;
}
int machine__process_switch_event(struct machine *machine __maybe_unused, int machine__process_switch_event(struct machine *machine __maybe_unused,
union perf_event *event) union perf_event *event)
{ {
@ -2028,6 +2036,8 @@ int machine__process_event(struct machine *machine, union perf_event *event,
ret = machine__process_bpf(machine, event, sample); break; ret = machine__process_bpf(machine, event, sample); break;
case PERF_RECORD_TEXT_POKE: case PERF_RECORD_TEXT_POKE:
ret = machine__process_text_poke(machine, event, sample); break; ret = machine__process_text_poke(machine, event, sample); break;
case PERF_RECORD_AUX_OUTPUT_HW_ID:
ret = machine__process_aux_output_hw_id_event(machine, event); break;
default: default:
ret = -1; ret = -1;
break; break;

View file

@ -124,6 +124,8 @@ int machine__process_aux_event(struct machine *machine,
union perf_event *event); union perf_event *event);
int machine__process_itrace_start_event(struct machine *machine, int machine__process_itrace_start_event(struct machine *machine,
union perf_event *event); union perf_event *event);
int machine__process_aux_output_hw_id_event(struct machine *machine,
union perf_event *event);
int machine__process_switch_event(struct machine *machine, int machine__process_switch_event(struct machine *machine,
union perf_event *event); union perf_event *event);
int machine__process_namespaces_event(struct machine *machine, int machine__process_namespaces_event(struct machine *machine,

View file

@ -509,6 +509,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
tool->bpf = perf_event__process_bpf; tool->bpf = perf_event__process_bpf;
if (tool->text_poke == NULL) if (tool->text_poke == NULL)
tool->text_poke = perf_event__process_text_poke; tool->text_poke = perf_event__process_text_poke;
if (tool->aux_output_hw_id == NULL)
tool->aux_output_hw_id = perf_event__process_aux_output_hw_id;
if (tool->read == NULL) if (tool->read == NULL)
tool->read = process_event_sample_stub; tool->read = process_event_sample_stub;
if (tool->throttle == NULL) if (tool->throttle == NULL)
@ -1000,6 +1002,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
[PERF_RECORD_NAMESPACES] = perf_event__namespaces_swap, [PERF_RECORD_NAMESPACES] = perf_event__namespaces_swap,
[PERF_RECORD_CGROUP] = perf_event__cgroup_swap, [PERF_RECORD_CGROUP] = perf_event__cgroup_swap,
[PERF_RECORD_TEXT_POKE] = perf_event__text_poke_swap, [PERF_RECORD_TEXT_POKE] = perf_event__text_poke_swap,
[PERF_RECORD_AUX_OUTPUT_HW_ID] = perf_event__all64_swap,
[PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
[PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
[PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
@ -1556,6 +1559,8 @@ static int machines__deliver_event(struct machines *machines,
return tool->bpf(tool, event, sample, machine); return tool->bpf(tool, event, sample, machine);
case PERF_RECORD_TEXT_POKE: case PERF_RECORD_TEXT_POKE:
return tool->text_poke(tool, event, sample, machine); return tool->text_poke(tool, event, sample, machine);
case PERF_RECORD_AUX_OUTPUT_HW_ID:
return tool->aux_output_hw_id(tool, event, sample, machine);
default: default:
++evlist->stats.nr_unknown_events; ++evlist->stats.nr_unknown_events;
return -1; return -1;

View file

@ -53,6 +53,7 @@ struct perf_tool {
lost_samples, lost_samples,
aux, aux,
itrace_start, itrace_start,
aux_output_hw_id,
context_switch, context_switch,
throttle, throttle,
unthrottle, unthrottle,