From: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
To: acme@kernel.org
Cc: linux-kernel@vger.kernel.org, hemant@linux.vnet.ibm.com,
naveen.n.rao@linux.vnet.ibm.com,
Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Subject: [RFC 3/4] perf kvm: Enable 'report' on powerpc
Date: Wed, 24 Feb 2016 14:37:44 +0530 [thread overview]
Message-ID: <1456304865-15131-4-git-send-email-ravi.bangoria@linux.vnet.ibm.com> (raw)
In-Reply-To: <1456304865-15131-1-git-send-email-ravi.bangoria@linux.vnet.ibm.com>
'perf kvm record' on powerpc will record kvm_hv:kvm_guest_exit event
instead of cycles. However, to have some kind of periodicity, we can't
use all the kvm exits, rather exits which are bound to happen in certain
intervals. HV_DECREMENTER Interrupt forces the threads to exit after an
interval of 10 ms.
This patch makes use of the 'kvm_guest_exit' tracepoint and checks the
exit reason for any kvm exit. If it is HV_DECREMENTER, then the
instruction pointer dumped along with this tracepoint is retrieved and
mapped with the guest kallsyms.
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Signed-off-by: Hemant Kumar <hemant@linux.vnet.ibm.com>
---
tools/perf/util/event.c | 7 +++--
tools/perf/util/evsel.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/evsel.h | 7 +++++
tools/perf/util/session.c | 7 +++--
4 files changed, 92 insertions(+), 6 deletions(-)
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index bc0a3f0..31bbc50 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1299,15 +1299,16 @@ int perf_event__preprocess_sample(const union perf_event *event,
struct machine *machine,
struct addr_location *al,
struct perf_sample *sample,
- struct perf_evsel *evsel __maybe_unused)
+ struct perf_evsel *evsel)
{
- u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+ u8 cpumode;
struct thread *thread = machine__findnew_thread(machine, sample->pid,
sample->tid);
-
if (thread == NULL)
return -1;
+ al->cpumode = cpumode = arch__get_cpumode(event, evsel, sample);
+
dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
/*
* Have we already created the kernel maps for this machine?
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 0902fe4..a4d309e 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1622,6 +1622,82 @@ static inline bool overflow(const void *endp, u16 max_size, const void *offset,
#define OVERFLOW_CHECK_u64(offset) \
OVERFLOW_CHECK(offset, sizeof(u64), sizeof(u64))
+#define KVMPPC_EXIT "kvm_hv:kvm_guest_exit"
+#define HV_DECREMENTER 2432
+#define HV_BIT 3
+#define PR_BIT 49
+#define PPC_MAX 63
+
+bool is_kvmppc_exit_event(struct perf_evsel *evsel)
+{
+ static unsigned int kvmppc_exit;
+
+ if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+ return false;
+
+ if (unlikely(kvmppc_exit == 0)) {
+ if (strcmp(KVMPPC_EXIT, evsel->name))
+ return false;
+ kvmppc_exit = evsel->attr.config;
+ } else if (kvmppc_exit != evsel->attr.config) {
+ return false;
+ }
+
+ return true;
+}
+
+bool is_hv_dec_trap(struct perf_evsel *evsel, struct perf_sample *sample)
+{
+ int trap = perf_evsel__intval(evsel, sample, "trap");
+ return trap == HV_DECREMENTER;
+}
+
+bool is_perf_data_reorded_on_ppc(struct perf_evlist *evlist)
+{
+ if (evlist && evlist->env && evlist->env->arch)
+ return !strcmp(evlist->env->arch, "ppc64") ||
+ !strcmp(evlist->env->arch, "ppc64le");
+ return false;
+}
+
+u8 arch__get_cpumode(const union perf_event *event,
+ struct perf_evsel *evsel,
+ struct perf_sample *sample)
+{
+ unsigned long hv, pr, msr;
+ u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+
+ if (!(is_perf_data_reorded_on_ppc(evsel->evlist) &&
+ perf_guest_only() &&
+ is_kvmppc_exit_event(evsel)))
+ goto ret;
+
+ if (sample->raw_data && is_hv_dec_trap(evsel, sample)) {
+ msr = perf_evsel__intval(evsel, sample, "msr");
+ hv = msr & ((unsigned long)1 << (PPC_MAX - HV_BIT));
+ pr = msr & ((unsigned long)1 << (PPC_MAX - PR_BIT));
+
+ if (!hv && pr)
+ cpumode = PERF_RECORD_MISC_GUEST_USER;
+ else
+ cpumode = PERF_RECORD_MISC_GUEST_KERNEL;
+ }
+
+ret:
+ return cpumode;
+}
+
+u64 arch__get_ip(struct perf_evsel *evsel, struct perf_sample *sample)
+{
+ if (is_perf_data_reorded_on_ppc(evsel->evlist) &&
+ perf_guest_only() &&
+ is_kvmppc_exit_event(evsel) &&
+ is_hv_dec_trap(evsel, sample))
+ return perf_evsel__intval(evsel, sample, "pc");
+
+ return sample->ip;
+}
+
int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
struct perf_sample *data)
{
@@ -1795,6 +1871,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
OVERFLOW_CHECK(array, data->raw_size, max_size);
data->raw_data = (void *)array;
array = (void *)array + data->raw_size;
+ data->ip = arch__get_ip(evsel, data);
}
if (type & PERF_SAMPLE_BRANCH_STACK) {
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index efad78f..a5f5cb5 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -408,4 +408,11 @@ typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *);
int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
attr__fprintf_f attr__fprintf, void *priv);
+u64 arch__get_ip(struct perf_evsel *evsel, struct perf_sample *sample);
+u8 arch__get_cpumode(const union perf_event *event, struct perf_evsel *evsel,
+ struct perf_sample *sample);
+bool is_kvmppc_exit_event(struct perf_evsel *evsel);
+bool is_hv_dec_trap(struct perf_evsel *evsel, struct perf_sample *sample);
+bool is_perf_data_reorded_on_ppc(struct perf_evlist *evlist);
+
#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 40b7a0d..52beee8 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1131,9 +1131,10 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
static struct machine *machines__find_for_cpumode(struct machines *machines,
union perf_event *event,
- struct perf_sample *sample)
+ struct perf_sample *sample,
+ struct perf_evsel *evsel)
{
- const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+ const u8 cpumode = arch__get_cpumode(event, evsel, sample);
struct machine *machine;
if (perf_guest &&
@@ -1237,7 +1238,7 @@ static int machines__deliver_event(struct machines *machines,
evsel = perf_evlist__id2evsel(evlist, sample->id);
- machine = machines__find_for_cpumode(machines, event, sample);
+ machine = machines__find_for_cpumode(machines, event, sample, evsel);
switch (event->header.type) {
case PERF_RECORD_SAMPLE:
--
2.1.4
next prev parent reply other threads:[~2016-02-24 9:09 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-24 9:07 [RFC 0/4] perf kvm: Guest Symbol Resolution for powerpc Ravi Bangoria
2016-02-24 9:07 ` [RFC 1/4] perf kvm: Enable 'record' on powerpc Ravi Bangoria
2016-03-22 19:12 ` Arnaldo Carvalho de Melo
2016-03-23 2:19 ` Arnaldo Carvalho de Melo
2016-03-24 21:15 ` Arnaldo Carvalho de Melo
2016-03-28 10:58 ` Ravi Bangoria
2016-03-28 12:28 ` Arnaldo Carvalho de Melo
2016-04-27 12:32 ` Ravi Bangoria
2016-04-27 21:47 ` Arnaldo Carvalho de Melo
2016-05-09 14:58 ` Ravi Bangoria
2016-02-24 9:07 ` [RFC 2/4] perf kvm: Introduce evsel as argument to perf_event__preprocess_sample Ravi Bangoria
2016-02-24 9:07 ` Ravi Bangoria [this message]
2016-02-24 9:07 ` [RFC 4/4] perf kvm: Fix output fields instead of 'trace' for perf kvm report on powerpc Ravi Bangoria
2016-03-02 14:25 ` Arnaldo Carvalho de Melo
2016-03-02 15:46 ` Ravi Bangoria
2016-03-02 16:22 ` Arnaldo Carvalho de Melo
2016-03-03 1:19 ` Ravi Bangoria
2016-03-08 15:42 ` Ravi Bangoria
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1456304865-15131-4-git-send-email-ravi.bangoria@linux.vnet.ibm.com \
--to=ravi.bangoria@linux.vnet.ibm.com \
--cc=acme@kernel.org \
--cc=hemant@linux.vnet.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=naveen.n.rao@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).