[PATCH v3 3/5] perf/tools: add support for PERF_SAMPLE_SKID_IP

Stephane Eranian
2017-11-08T07:57:43Z

This patch adds the support code to handle the PERF_SAMPLE_SKID_IP
record type. This is done as an event term and as such can be enabled
per event: cpu/event=xxx,skid-ip=1/. This is a boolean term which is
false by default.

Signed-off-by: Stephane Eranian <eranian@google.com>
---
tools/include/uapi/linux/perf_event.h | 4 +++-
tools/perf/util/event.h | 1 +
tools/perf/util/evsel.c | 11 +++++++++++
tools/perf/util/evsel.h | 2 ++
tools/perf/util/parse-events.c | 7 +++++++
tools/perf/util/parse-events.h | 1 +
tools/perf/util/parse-events.l | 1 +
tools/perf/util/session.c | 3 +++
8 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index 362493a2f950..79655228dd9b 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -141,8 +141,9 @@ enum perf_event_sample_format {
PERF_SAMPLE_TRANSACTION = 1U << 17,
PERF_SAMPLE_REGS_INTR = 1U << 18,
PERF_SAMPLE_PHYS_ADDR = 1U << 19,
+ PERF_SAMPLE_SKID_IP = 1U << 20,

- PERF_SAMPLE_MAX = 1U << 20, /* non-ABI */
+ PERF_SAMPLE_MAX = 1U << 21, /* non-ABI */
};

/*
@@ -817,6 +818,7 @@ enum perf_event_type {
* { u64 abi; # enum perf_sample_regs_abi
* u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR
* { u64 phys_addr;} && PERF_SAMPLE_PHYS_ADDR
+ * { u64 skid_ip; } && PERF_SAMPLE_SKID_IP
* };
*/
PERF_RECORD_SAMPLE = 9,
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 1ae95efbfb95..41622a7ed649 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -202,6 +202,7 @@ struct perf_sample {
u32 raw_size;
u64 data_src;
u64 phys_addr;
+ u64 skid_ip;
u32 flags;
u16 insn_len;
u8 cpumode;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index f894893c203d..679954ed2201 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -775,6 +775,10 @@ static void apply_config_terms(struct perf_evsel *evsel,
case PERF_EVSEL__CONFIG_TERM_OVERWRITE:
attr->write_backward = term->val.overwrite ? 1 : 0;
break;
+ case PERF_EVSEL__CONFIG_TERM_SKID_IP:
+ if (term->val.skid_ip)
+ perf_evsel__set_sample_bit(evsel, SKID_IP);
+ break;
default:
break;
}
@@ -1478,6 +1482,7 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
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(SKID_IP),
{ .name = NULL, }
};
#undef bit_name
@@ -2225,6 +2230,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
array++;
}

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

diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 9277df96ffda..8555095f0d48 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -49,6 +49,7 @@ enum {
PERF_EVSEL__CONFIG_TERM_OVERWRITE,
PERF_EVSEL__CONFIG_TERM_DRV_CFG,
PERF_EVSEL__CONFIG_TERM_BRANCH,
+ PERF_EVSEL__CONFIG_TERM_SKID_IP,
PERF_EVSEL__CONFIG_TERM_MAX,
};

@@ -66,6 +67,7 @@ struct perf_evsel_config_term {
bool inherit;
bool overwrite;
char *branch;
+ bool skid_ip;
} val;
};

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index a7fcd95961ef..1a1d9fc509bd 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -918,6 +918,7 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
[PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite",
[PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite",
[PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config",
+ [PARSE_EVENTS__TERM_TYPE_SKID_IP] = "skid-ip",
};

static bool config_term_shrinked;
@@ -1026,6 +1027,9 @@ do { \
case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
CHECK_TYPE_VAL(NUM);
break;
+ case PARSE_EVENTS__TERM_TYPE_SKID_IP:
+ CHECK_TYPE_VAL(NUM);
+ break;
default:
err->str = strdup("unknown term");
err->idx = term->err_term;
@@ -1159,6 +1163,9 @@ do { \
case PARSE_EVENTS__TERM_TYPE_DRV_CFG:
ADD_CONFIG_TERM(DRV_CFG, drv_cfg, term->val.str);
break;
+ case PARSE_EVENTS__TERM_TYPE_SKID_IP:
+ ADD_CONFIG_TERM(SKID_IP, skid_ip, term->val.num ? 1 : 0);
+ break;
default:
break;
}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index be337c266697..d331f078a389 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -74,6 +74,7 @@ enum {
PARSE_EVENTS__TERM_TYPE_NOOVERWRITE,
PARSE_EVENTS__TERM_TYPE_OVERWRITE,
PARSE_EVENTS__TERM_TYPE_DRV_CFG,
+ PARSE_EVENTS__TERM_TYPE_SKID_IP,
__PARSE_EVENTS__TERM_TYPE_NR,
};

diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 241396cd059d..383443f4fe0d 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -257,6 +257,7 @@ inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); }
no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); }
no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); }
+skid-ip { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SKID_IP); }
, { return ','; }
"/" { BEGIN(INITIAL); return '/'; }
{name_minus} { return str(yyscanner, PE_NAME); }
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5c412310f266..223165055d41 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1131,6 +1131,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,

if (sample_type & PERF_SAMPLE_READ)
sample_read__printf(sample, evsel->attr.read_format);
+
+ if (sample_type & PERF_SAMPLE_SKID_IP)
+ printf("... skid_ip: %" PRIu64 "\n", sample->skid_ip);
}

static void dump_read(struct perf_evsel *evsel, union perf_event *event)
--
2.7.4