[PATCH 13/21] perf tools: Add support to parse user data event

From: Jiri Olsa
Date: Wed Jan 24 2018 - 06:54:50 EST


Adding support to parse user data event and prepare
it for later processing.

Link: http://lkml.kernel.org/n/tip-j1pw90h5a9mhecpk949p68gs@xxxxxxxxxxxxxx
Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx>
---
tools/perf/util/event.c | 1 +
tools/perf/util/event.h | 8 ++++++++
tools/perf/util/evsel.c | 20 ++++++++++++++++++--
tools/perf/util/session.c | 23 +++++++++++++++++------
tools/perf/util/tool.h | 1 +
5 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 44e603c27944..89f20ae9d949 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -43,6 +43,7 @@ static const char *perf_event__names[] = {
[PERF_RECORD_SWITCH] = "SWITCH",
[PERF_RECORD_SWITCH_CPU_WIDE] = "SWITCH_CPU_WIDE",
[PERF_RECORD_NAMESPACES] = "NAMESPACES",
+ [PERF_RECORD_USER_DATA] = "USER_DATA",
[PERF_RECORD_HEADER_ATTR] = "ATTR",
[PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
[PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 546539da1592..5ac657aebb67 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -99,6 +99,12 @@ struct sample_event {
u64 array[];
};

+struct user_data_event {
+ struct perf_event_header header;
+ u64 type;
+ u64 array[];
+};
+
struct regs_dump {
u64 abi;
u64 mask;
@@ -203,6 +209,7 @@ struct perf_sample {
u32 raw_size;
u64 data_src;
u64 phys_addr;
+ u64 user_data_id;
u32 flags;
u16 insn_len;
u8 cpumode;
@@ -633,6 +640,7 @@ union perf_event {
struct read_event read;
struct throttle_event throttle;
struct sample_event sample;
+ struct user_data_event user_data;
struct attr_event attr;
struct event_update_event event_update;
struct event_type_event event_type;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 035da5d1fdd3..6f6eab6bc108 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1508,7 +1508,7 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC),
- bit_name(WEIGHT), bit_name(PHYS_ADDR),
+ bit_name(WEIGHT), bit_name(PHYS_ADDR), bit_name(USER_DATA_ID),
{ .name = NULL, }
};
#undef bit_name
@@ -1602,6 +1602,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
PRINT_ATTRf(context_switch, p_unsigned);
PRINT_ATTRf(write_backward, p_unsigned);
PRINT_ATTRf(namespaces, p_unsigned);
+ PRINT_ATTRf(user_data, p_unsigned);

PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
PRINT_ATTRf(bp_type, p_unsigned);
@@ -2310,6 +2311,10 @@ perf_sample__parse(struct perf_sample *data, struct parse_args *arg)
array++;
}

+ if (type & PERF_SAMPLE_USER_DATA_ID) {
+ data->user_data_id = *array;
+ array++;
+ }
return 0;
}

@@ -2335,7 +2340,15 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
if (event->header.type != PERF_RECORD_SAMPLE) {
if (!evsel->attr.sample_id_all)
return 0;
- return perf_evsel__parse_id_sample(evsel, event, data);
+
+ perf_evsel__parse_id_sample(evsel, event, data);
+
+ if (event->header.type != PERF_RECORD_USER_DATA)
+ return 0;
+
+ arg.type = event->user_data.type;
+ arg.array = event->user_data.array;
+ return perf_sample__parse(data, &arg);
}

if (perf_event__check_size(event, evsel->sample_size))
@@ -2493,6 +2506,9 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
if (type & PERF_SAMPLE_PHYS_ADDR)
result += sizeof(u64);

+ if (type & PERF_SAMPLE_USER_DATA_ID)
+ result += sizeof(u64);
+
return result;
}

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index da0635e2f100..cb910ea6f0a0 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -361,6 +361,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
{
if (tool->sample == NULL)
tool->sample = process_event_sample_stub;
+ if (tool->user_data == NULL)
+ tool->user_data = process_event_sample_stub;
if (tool->mmap == NULL)
tool->mmap = process_event_stub;
if (tool->mmap2 == NULL)
@@ -1127,6 +1129,13 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
if (sample_type & PERF_SAMPLE_TRANSACTION)
printf("... transaction: %" PRIx64 "\n", sample->transaction);

+ if (sample_type & PERF_SAMPLE_USER_DATA_ID) {
+ if (sample->misc & PERF_RECORD_MISC_USER_DATA)
+ printf("... user data ID: %" PRIu64 "\n", sample->user_data_id);
+ else
+ printf("... user data ID: N/A\n");
+ }
+
if (sample_type & PERF_SAMPLE_READ)
sample_read__printf(sample, evsel->attr.read_format);
}
@@ -1225,12 +1234,12 @@ static int deliver_sample_group(struct perf_evlist *evlist,
}

static int
- perf_evlist__deliver_sample(struct perf_evlist *evlist,
- struct perf_tool *tool,
- union perf_event *event,
- struct perf_sample *sample,
- struct perf_evsel *evsel,
- struct machine *machine)
+perf_evlist__deliver_sample(struct perf_evlist *evlist,
+ struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct machine *machine)
{
/* We know evsel != NULL. */
u64 sample_type = evsel->attr.sample_type;
@@ -1276,6 +1285,8 @@ static int machines__deliver_event(struct machines *machines,
return 0;
}
return perf_evlist__deliver_sample(evlist, tool, event, sample, evsel, machine);
+ case PERF_RECORD_USER_DATA:
+ return tool->user_data(tool, event, sample, evsel, machine);
case PERF_RECORD_MMAP:
return tool->mmap(tool, event, sample, machine);
case PERF_RECORD_MMAP2:
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 183c91453522..9ae190d4d0aa 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -43,6 +43,7 @@ enum show_feature_header {

struct perf_tool {
event_sample sample,
+ user_data,
read;
event_op mmap,
mmap2,
--
2.13.6