From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751373AbcETTwh (ORCPT ); Fri, 20 May 2016 15:52:37 -0400 Received: from mga01.intel.com ([192.55.52.88]:37137 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750836AbcETTwg (ORCPT ); Fri, 20 May 2016 15:52:36 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,340,1459839600"; d="scan'208";a="811487261" From: Andi Kleen To: acme@kernel.org Cc: jolsa@kernel.org, linux-kernel@vger.kernel.org, Andi Kleen , adrian.hunter@intel.com Subject: [PATCH 1/2] perf pt: Mark PT return events as "return" Date: Fri, 20 May 2016 12:52:17 -0700 Message-Id: <1463773938-26194-1-git-send-email-andi@firstfloor.org> X-Mailer: git-send-email 2.5.5 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Andi Kleen With perf script --itrace=cr we can synthesize calls and returns out of a PT log. However both calls and returns are marked with the same event, called branches. This makes it difficult to read and post process, because calls and returns are somewhat diffferent. Create a separate return event and mark the returns as return. Cc: adrian.hunter@intel.com Signed-off-by: Andi Kleen --- tools/perf/util/intel-pt.c | 53 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index ddec87f6e616..25f839e765ef 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c @@ -82,9 +82,12 @@ struct intel_pt { u64 instructions_id; bool sample_branches; + bool sample_returns; u32 branches_filter; u64 branches_sample_type; + u64 returns_sample_type; u64 branches_id; + u64 returns_id; bool sample_transactions; u64 transactions_sample_type; @@ -960,7 +963,8 @@ static int intel_pt_inject_event(union perf_event *event, return perf_event__synthesize_sample(event, type, 0, sample, swapped); } -static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) +static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq, + bool is_return) { int ret; struct intel_pt *pt = ptq->pt; @@ -990,8 +994,13 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) sample.pid = ptq->pid; sample.tid = ptq->tid; sample.addr = ptq->state->to_ip; - sample.id = ptq->pt->branches_id; - sample.stream_id = ptq->pt->branches_id; + if (is_return) { + sample.id = ptq->pt->returns_id; + sample.stream_id = ptq->pt->returns_id; + } else { + sample.id = ptq->pt->branches_id; + sample.stream_id = ptq->pt->branches_id; + } sample.period = 1; sample.cpu = ptq->cpu; sample.flags = ptq->flags; @@ -1014,6 +1023,8 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) if (pt->synth_opts.inject) { ret = intel_pt_inject_event(event, &sample, + is_return ? + pt->returns_sample_type : pt->branches_sample_type, pt->synth_needs_swap); if (ret) @@ -1241,7 +1252,13 @@ static int intel_pt_sample(struct intel_pt_queue *ptq) thread_stack__set_trace_nr(ptq->thread, state->trace_nr); if (pt->sample_branches) { - err = intel_pt_synth_branch_sample(ptq); + err = intel_pt_synth_branch_sample(ptq, false); + if (err) + return err; + } + + if (pt->sample_returns) { + err = intel_pt_synth_branch_sample(ptq, true); if (err) return err; } @@ -1956,7 +1973,33 @@ static int intel_pt_synth_events(struct intel_pt *pt, } pt->sample_branches = true; pt->branches_sample_type = attr.sample_type; - pt->branches_id = id; + pt->branches_id = id++; + } + if (pt->synth_opts.returns) { + attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS; + attr.sample_period = 1; + attr.sample_type |= PERF_SAMPLE_ADDR; + attr.sample_type &= ~(u64)PERF_SAMPLE_CALLCHAIN; + attr.sample_type &= ~(u64)PERF_SAMPLE_BRANCH_STACK; + pr_debug("Synthesizing 'return' event with id %" PRIu64 " sample type %#" PRIx64 "\n", + id, (u64)attr.sample_type); + err = intel_pt_synth_event(session, &attr, id); + if (err) { + pr_err("%s: failed to synthesize 'return' event type\n", + __func__); + return err; + } + pt->sample_returns = true; + pt->returns_sample_type = attr.sample_type; + pt->returns_id = id; + evlist__for_each(evlist, evsel) { + if (evsel->id && evsel->id[0] == pt->returns_id) { + if (evsel->name) + zfree(&evsel->name); + evsel->name = strdup("return"); + break; + } + } } pt->synth_needs_swap = evsel->needs_swap; -- 2.5.5