lkml.org 
[lkml]   [2014]   [Jul]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 3/4] perf tools: add core support for sampling intr machine state regs
Date
Add the infrastructure to setup, collect and report the interrupt
machine state regs which can be captured by the kernel.

Signed-off-by: Stephane Eranian <eranian@google.com>
---
tools/perf/perf.h | 1 +
tools/perf/util/event.h | 7 +++++++
tools/perf/util/evsel.c | 25 ++++++++++++++++++++++++-
tools/perf/util/session.c | 26 ++++++++++++++++++++++++++
4 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 510c65f..309d956 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -54,6 +54,7 @@ struct record_opts {
bool sample_weight;
bool sample_time;
bool period;
+ bool sample_intr_regs;
unsigned int freq;
unsigned int mmap_pages;
unsigned int user_freq;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index e5dd40a..4ce2e99 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -160,6 +160,7 @@ struct perf_sample {
struct ip_callchain *callchain;
struct branch_stack *branch_stack;
struct regs_dump user_regs;
+ struct regs_dump intr_regs;
struct stack_dump user_stack;
struct sample_read read;
};
@@ -290,6 +291,12 @@ int perf_event__preprocess_sample(const union perf_event *event,

const char *perf_event__name(unsigned int id);

+int perf_event__parse_sample(const union perf_event *event, u64 type,
+ int sample_size, bool sample_id_all,
+ u64 sample_regs_user, u64 sample_stack_user,
+ u64 sample_regs_intr,
+ struct perf_sample *data, bool swapped);
+
size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
u64 read_format);
int perf_event__synthesize_sample(union perf_event *event, u64 type,
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 8606175..00e45d1 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -626,6 +626,11 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
if (opts->call_graph_enabled)
perf_evsel__config_callgraph(evsel, opts);

+ if (opts->sample_intr_regs) {
+ attr->sample_regs_intr = PERF_REGS_MASK;
+ perf_evsel__set_sample_bit(evsel, REGS_INTR);
+ }
+
if (target__has_cpu(&opts->target))
perf_evsel__set_sample_bit(evsel, CPU);

@@ -979,6 +984,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
ret += PRINT_ATTR_X64(branch_sample_type);
ret += PRINT_ATTR_X64(sample_regs_user);
ret += PRINT_ATTR_U32(sample_stack_user);
+ ret += PRINT_ATTR_X64(sample_regs_intr);

ret += fprintf(fp, "%.60s\n", graph_dotted_line);

@@ -1468,6 +1474,23 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
array++;
}

+ data->intr_regs.abi = PERF_SAMPLE_REGS_ABI_NONE;
+ if (type & PERF_SAMPLE_REGS_INTR) {
+ OVERFLOW_CHECK_u64(array);
+ data->intr_regs.abi = *array;
+ array++;
+
+ if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) {
+ u64 mask = evsel->attr.sample_regs_intr;
+
+ sz = hweight_long(mask) * sizeof(u64);
+ OVERFLOW_CHECK(array, sz, max_size);
+ data->intr_regs.mask = mask;
+ data->intr_regs.regs = (u64 *)array;
+ array = (void *)array + sz;
+ }
+ }
+
return 0;
}

@@ -1870,7 +1893,7 @@ static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
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(IDENTIFIER), bit_name(REGS_INTR),
{ .name = NULL, }
};
#undef bit_name
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 64a186e..6f112ca 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -713,6 +713,29 @@ static void regs_user__printf(struct perf_sample *sample)
}
}

+static const char *regs_abi[]= {
+ [PERF_SAMPLE_REGS_ABI_NONE] = "none",
+ [PERF_SAMPLE_REGS_ABI_32] = "32-bit",
+ [PERF_SAMPLE_REGS_ABI_64] = "64-bit",
+};
+
+static inline const char *regs_dump_abi(struct regs_dump *d)
+{
+ if (d->abi > PERF_SAMPLE_REGS_ABI_64)
+ return "???";
+ return regs_abi[d->abi];
+}
+
+static void regs_intr__printf(struct perf_sample *sample, u64 mask)
+{
+ struct regs_dump *intr_regs = &sample->intr_regs;
+
+ if (intr_regs->regs) {
+ printf("... intr regs: mask 0x%" PRIx64 " ABI: %s\n", mask, regs_dump_abi(intr_regs));
+ regs_dump__printf(mask, intr_regs->regs);
+ }
+}
+
static void stack_user__printf(struct stack_dump *dump)
{
printf("... ustack: size %" PRIu64 ", offset 0x%x\n",
@@ -809,6 +832,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
if (sample_type & PERF_SAMPLE_REGS_USER)
regs_user__printf(sample);

+ if (sample_type & PERF_SAMPLE_REGS_INTR)
+ regs_intr__printf(sample, evsel->attr.sample_regs_intr);
+
if (sample_type & PERF_SAMPLE_STACK_USER)
stack_user__printf(&sample->user_stack);

--
1.8.3.2


\
 
 \ /
  Last update: 2014-07-09 01:01    [W:0.098 / U:0.624 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site