perf tools: Add support for PERF_RECORD_AUX_OUTPUT_HW_ID
authorAdrian Hunter <adrian.hunter@intel.com>
Tue, 7 Sep 2021 16:39:02 +0000 (19:39 +0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 20 Oct 2021 14:22:27 +0000 (11:22 -0300)
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>
tools/include/uapi/linux/perf_event.h
tools/lib/perf/include/perf/event.h
tools/perf/builtin-inject.c
tools/perf/builtin-record.c
tools/perf/util/event.c
tools/perf/util/event.h
tools/perf/util/machine.c
tools/perf/util/machine.h
tools/perf/util/session.c
tools/perf/util/tool.h

index f92880a..c89535d 100644 (file)
@@ -1141,6 +1141,21 @@ enum perf_event_type {
         */
        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 */
 };
 
index 4d0c02b..75ee385 100644 (file)
@@ -289,6 +289,11 @@ struct perf_record_itrace_start {
        __u32                    tid;
 };
 
+struct perf_record_aux_output_hw_id {
+       struct perf_event_header header;
+       __u64                   hw_id;
+};
+
 struct perf_record_thread_map_entry {
        __u64                    pid;
        char                     comm[16];
@@ -414,6 +419,7 @@ union perf_event {
        struct perf_record_auxtrace_error       auxtrace_error;
        struct perf_record_aux                  aux;
        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_thread_map           thread_map;
        struct perf_record_cpu_map              cpu_map;
index 6ad191e..ac6c570 100644 (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       = perf_event__process_auxtrace;
                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.ordering_requires_timestamps = true;
                /* 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,
                        .aux            = perf_event__repipe,
                        .itrace_start   = perf_event__repipe,
+                       .aux_output_hw_id = perf_event__repipe,
                        .context_switch = perf_event__repipe,
                        .throttle       = perf_event__repipe,
                        .unthrottle     = perf_event__repipe,
index 41bb884..78185c9 100644 (file)
@@ -1411,7 +1411,7 @@ static int record__synthesize(struct record *rec, bool tail)
                goto out;
 
        /* 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,
                                                      process_synthesized_event,
                                                      session->evlist, machine);
index ac70630..fe24801 100644 (file)
@@ -57,6 +57,7 @@ static const char *perf_event__names[] = {
        [PERF_RECORD_BPF_EVENT]                 = "BPF_EVENT",
        [PERF_RECORD_CGROUP]                    = "CGROUP",
        [PERF_RECORD_TEXT_POKE]                 = "TEXT_POKE",
+       [PERF_RECORD_AUX_OUTPUT_HW_ID]          = "AUX_OUTPUT_HW_ID",
        [PERF_RECORD_HEADER_ATTR]               = "ATTR",
        [PERF_RECORD_HEADER_EVENT_TYPE]         = "EVENT_TYPE",
        [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);
 }
 
+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,
                                     union perf_event *event,
                                     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);
 }
 
+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)
 {
        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:
                ret += perf_event__fprintf_text_poke(event, machine, fp);
                break;
+       case PERF_RECORD_AUX_OUTPUT_HW_ID:
+               ret += perf_event__fprintf_aux_output_hw_id(event, fp);
+               break;
        default:
                ret += fprintf(fp, "\n");
        }
index 19ad64f..95ffed6 100644 (file)
@@ -330,6 +330,10 @@ int perf_event__process_itrace_start(struct perf_tool *tool,
                                     union perf_event *event,
                                     struct perf_sample *sample,
                                     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,
                               union perf_event *event,
                               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_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_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_thread_map(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp);
index 44e40ba..fb8496d 100644 (file)
@@ -755,6 +755,14 @@ int machine__process_itrace_start_event(struct machine *machine __maybe_unused,
        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,
                                  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;
        case PERF_RECORD_TEXT_POKE:
                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:
                ret = -1;
                break;
index 7377ed6..a143087 100644 (file)
@@ -124,6 +124,8 @@ int machine__process_aux_event(struct machine *machine,
                               union perf_event *event);
 int machine__process_itrace_start_event(struct machine *machine,
                                        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,
                                  union perf_event *event);
 int machine__process_namespaces_event(struct machine *machine,
index 069c2cf..bdf1da9 100644 (file)
@@ -509,6 +509,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
                tool->bpf = perf_event__process_bpf;
        if (tool->text_poke == NULL)
                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)
                tool->read = process_event_sample_stub;
        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_CGROUP]              = perf_event__cgroup_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_EVENT_TYPE]   = perf_event__event_type_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);
        case PERF_RECORD_TEXT_POKE:
                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:
                ++evlist->stats.nr_unknown_events;
                return -1;
index bbbc0dc..ef873f2 100644 (file)
@@ -53,6 +53,7 @@ struct perf_tool {
                        lost_samples,
                        aux,
                        itrace_start,
+                       aux_output_hw_id,
                        context_switch,
                        throttle,
                        unthrottle,