Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754934Ab2HGNWh (ORCPT ); Tue, 7 Aug 2012 09:22:37 -0400 Received: from mx1.redhat.com ([209.132.183.28]:65372 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754911Ab2HGNWf (ORCPT ); Tue, 7 Aug 2012 09:22:35 -0400 From: Jiri Olsa To: linux-kernel@vger.kernel.org Cc: Arnaldo Carvalho de Melo , Arun Sharma , Benjamin Redelings , Corey Ashford , Cyrill Gorcunov , "Frank Ch. Eigler" , Frederic Weisbecker , Ingo Molnar , Masami Hiramatsu , Paul Mackerras , Peter Zijlstra , Robert Richter , Stephane Eranian , Tom Zanussi , Ulrich Drepper , Jiri Olsa Subject: [PATCH 10/12] perf tools: Support user regs and stack in sample parsing Date: Tue, 7 Aug 2012 15:20:45 +0200 Message-Id: <1344345647-11536-11-git-send-email-jolsa@redhat.com> In-Reply-To: <1344345647-11536-1-git-send-email-jolsa@redhat.com> References: <1344345647-11536-1-git-send-email-jolsa@redhat.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6607 Lines: 226 Adding following info to be parsed out of the event sample: - user register set - user stack dump Both are global and specific to all events within the session. This info will be used in the unwind patches coming in shortly. Adding simple output printout (report -D) for both register and stack dumps. Original-patch-by: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Arun Sharma Cc: Benjamin Redelings Cc: Corey Ashford Cc: Cyrill Gorcunov Cc: Frank Ch. Eigler Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Masami Hiramatsu Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Robert Richter Cc: Stephane Eranian Cc: Tom Zanussi Cc: Ulrich Drepper [ Use evsel->attr.sample_regs_user ] Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Jiri Olsa --- tools/perf/util/event.h | 12 ++++++++++++ tools/perf/util/evsel.c | 28 ++++++++++++++++++++++++++++ tools/perf/util/header.c | 2 ++ tools/perf/util/session.c | 41 ++++++++++++++++++++++++++++++++++++++--- 4 files changed, 80 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index d84870b..0e088d0 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -69,6 +69,16 @@ struct sample_event { u64 array[]; }; +struct regs_dump { + u64 *regs; +}; + +struct stack_dump { + u16 offset; + u64 size; + char *data; +}; + struct perf_sample { u64 ip; u32 pid, tid; @@ -82,6 +92,8 @@ struct perf_sample { void *raw_data; struct ip_callchain *callchain; struct branch_stack *branch_stack; + struct regs_dump user_regs; + struct stack_dump user_stack; }; #define BUILD_ID_SIZE 20 diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 2eaae14..a2da682 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -8,6 +8,7 @@ */ #include +#include #include "asm/bug.h" #include "evsel.h" #include "evlist.h" @@ -733,6 +734,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, struct perf_sample *data, bool swapped) { u64 type = evsel->attr.sample_type; + u64 regs_user = evsel->attr.sample_regs_user; const u64 *array; /* @@ -869,6 +871,32 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, sz /= sizeof(u64); array += sz; } + + if (type & PERF_SAMPLE_REGS_USER) { + /* First u64 tells us if we have any regs in sample. */ + u64 avail = *array++; + + if (avail) { + data->user_regs.regs = (u64 *)array; + array += hweight_long(regs_user); + } + } + + if (type & PERF_SAMPLE_STACK_USER) { + u64 size = *array++; + + data->user_stack.offset = ((char *)(array - 1) + - (char *) event); + + if (!size) { + data->user_stack.size = 0; + } else { + data->user_stack.data = (char *)array; + array += size / sizeof(*array); + data->user_stack.size = *array; + } + } + return 0; } diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index db91425..24c489b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1830,6 +1830,8 @@ static const int attr_file_abi_sizes[] = { [0] = PERF_ATTR_SIZE_VER0, [1] = PERF_ATTR_SIZE_VER1, [2] = PERF_ATTR_SIZE_VER2, + [3] = PERF_ATTR_SIZE_VER3, + [4] = PERF_ATTR_SIZE_VER4, 0, }; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 2437fb0..c9ed7e3 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -15,6 +15,7 @@ #include "util.h" #include "cpumap.h" #include "event-parse.h" +#include "perf_regs.h" static int perf_session__open(struct perf_session *self, bool force) { @@ -860,6 +861,34 @@ static void branch_stack__printf(struct perf_sample *sample) sample->branch_stack->entries[i].to); } +static void regs_dump__printf(u64 mask, u64 *regs) +{ + unsigned rid, i = 0; + + for_each_set_bit(rid, (unsigned long *) &mask, sizeof(mask) * 8) { + u64 val = regs[i++]; + + printf(".... %-5s 0x%" PRIx64 "\n", + perf_reg_name(rid), val); + } +} + +static void regs_user__printf(struct perf_sample *sample, u64 mask) +{ + struct regs_dump *user_regs = &sample->user_regs; + + if (user_regs->regs) { + printf("... user regs: mask 0x%" PRIx64 "\n", mask); + regs_dump__printf(mask, user_regs->regs); + } +} + +static void stack_user__printf(struct stack_dump *dump) +{ + printf("... ustack: size %" PRIu64 ", offset 0x%x\n", + dump->size, dump->offset); +} + static void perf_session__print_tstamp(struct perf_session *session, union perf_event *event, struct perf_sample *sample) @@ -897,7 +926,7 @@ static void dump_event(struct perf_session *session, union perf_event *event, event->header.size, perf_event__name(event->header.type)); } -static void dump_sample(struct perf_session *session, union perf_event *event, +static void dump_sample(struct perf_evsel *evsel, union perf_event *event, struct perf_sample *sample) { u64 sample_type; @@ -909,13 +938,19 @@ static void dump_sample(struct perf_session *session, union perf_event *event, event->header.misc, sample->pid, sample->tid, sample->ip, sample->period, sample->addr); - sample_type = perf_evlist__sample_type(session->evlist); + sample_type = evsel->attr.sample_type; if (sample_type & PERF_SAMPLE_CALLCHAIN) callchain__printf(sample); if (sample_type & PERF_SAMPLE_BRANCH_STACK) branch_stack__printf(sample); + + if (sample_type & PERF_SAMPLE_REGS_USER) + regs_user__printf(sample, evsel->attr.sample_regs_user); + + if (sample_type & PERF_SAMPLE_STACK_USER) + stack_user__printf(&sample->user_stack); } static struct machine * @@ -973,7 +1008,7 @@ static int perf_session_deliver_event(struct perf_session *session, switch (event->header.type) { case PERF_RECORD_SAMPLE: - dump_sample(session, event, sample); + dump_sample(evsel, event, sample); if (evsel == NULL) { ++session->hists.stats.nr_unknown_id; return 0; -- 1.7.11.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/