From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753418AbeA1VXX (ORCPT ); Sun, 28 Jan 2018 16:23:23 -0500 Received: from terminus.zytor.com ([65.50.211.136]:39115 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752886AbeA1VXU (ORCPT ); Sun, 28 Jan 2018 16:23:20 -0500 Date: Sun, 28 Jan 2018 13:19:41 -0800 From: tip-bot for Mathieu Poirier Message-ID: Cc: mike.leach@arm.com, acme@redhat.com, alexander.shishkin@linux.intel.com, peterz@infradead.org, tglx@linutronix.de, namhyung@kernel.org, mingo@kernel.org, mathieu.poirier@linaro.org, kim.phillips@arm.com, adrian.hunter@intel.com, hpa@zytor.com, linux-kernel@vger.kernel.org, suzuki.poulose@arm.com, jolsa@redhat.com, tor@ti.com Reply-To: mike.leach@arm.com, tglx@linutronix.de, mingo@kernel.org, namhyung@kernel.org, acme@redhat.com, alexander.shishkin@linux.intel.com, peterz@infradead.org, mathieu.poirier@linaro.org, kim.phillips@arm.com, adrian.hunter@intel.com, hpa@zytor.com, jolsa@redhat.com, linux-kernel@vger.kernel.org, suzuki.poulose@arm.com, tor@ti.com In-Reply-To: <1516211539-5166-10-git-send-email-mathieu.poirier@linaro.org> References: <1516211539-5166-10-git-send-email-mathieu.poirier@linaro.org> To: linux-tip-commits@vger.kernel.org Subject: [tip:perf/core] perf tools: Add mechanic to synthesise CoreSight trace packets Git-Commit-ID: b12235b113cfd7e4a31f0c8bdb0d8e8588ba6683 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: b12235b113cfd7e4a31f0c8bdb0d8e8588ba6683 Gitweb: https://git.kernel.org/tip/b12235b113cfd7e4a31f0c8bdb0d8e8588ba6683 Author: Mathieu Poirier AuthorDate: Wed, 17 Jan 2018 10:52:18 -0700 Committer: Arnaldo Carvalho de Melo CommitDate: Thu, 25 Jan 2018 06:37:27 -0300 perf tools: Add mechanic to synthesise CoreSight trace packets Once decoded from trace packets information on trace range needs to be communicated to the perf synthesis infrastructure so that it is available to the perf tools built-in rendering tools and scripts. Co-authored-by: Tor Jeremiassen Signed-off-by: Mathieu Poirier Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Kim Phillips Cc: Mike Leach Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Suzuki Poulouse Cc: linux-arm-kernel@lists.infradead.org Link: http://lkml.kernel.org/r/1516211539-5166-10-git-send-email-mathieu.poirier@linaro.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cs-etm.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 407095a..b9f0a53 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -453,6 +453,157 @@ static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm, } } +/* + * The cs etm packet encodes an instruction range between a branch target + * and the next taken branch. Generate sample accordingly. + */ +static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq, + struct cs_etm_packet *packet) +{ + int ret = 0; + struct cs_etm_auxtrace *etm = etmq->etm; + struct perf_sample sample = {.ip = 0,}; + union perf_event *event = etmq->event_buf; + u64 start_addr = packet->start_addr; + u64 end_addr = packet->end_addr; + + event->sample.header.type = PERF_RECORD_SAMPLE; + event->sample.header.misc = PERF_RECORD_MISC_USER; + event->sample.header.size = sizeof(struct perf_event_header); + + sample.ip = start_addr; + sample.pid = etmq->pid; + sample.tid = etmq->tid; + sample.addr = end_addr; + sample.id = etmq->etm->branches_id; + sample.stream_id = etmq->etm->branches_id; + sample.period = 1; + sample.cpu = packet->cpu; + sample.flags = 0; + sample.cpumode = PERF_RECORD_MISC_USER; + + ret = perf_session__deliver_synth_event(etm->session, event, &sample); + + if (ret) + pr_err( + "CS ETM Trace: failed to deliver instruction event, error %d\n", + ret); + + return ret; +} + +struct cs_etm_synth { + struct perf_tool dummy_tool; + struct perf_session *session; +}; + +static int cs_etm__event_synth(struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample __maybe_unused, + struct machine *machine __maybe_unused) +{ + struct cs_etm_synth *cs_etm_synth = + container_of(tool, struct cs_etm_synth, dummy_tool); + + return perf_session__deliver_synth_event(cs_etm_synth->session, + event, NULL); +} + +static int cs_etm__synth_event(struct perf_session *session, + struct perf_event_attr *attr, u64 id) +{ + struct cs_etm_synth cs_etm_synth; + + memset(&cs_etm_synth, 0, sizeof(struct cs_etm_synth)); + cs_etm_synth.session = session; + + return perf_event__synthesize_attr(&cs_etm_synth.dummy_tool, attr, 1, + &id, cs_etm__event_synth); +} + +static int cs_etm__synth_events(struct cs_etm_auxtrace *etm, + struct perf_session *session) +{ + struct perf_evlist *evlist = session->evlist; + struct perf_evsel *evsel; + struct perf_event_attr attr; + bool found = false; + u64 id; + int err; + + evlist__for_each_entry(evlist, evsel) { + if (evsel->attr.type == etm->pmu_type) { + found = true; + break; + } + } + + if (!found) { + pr_debug("No selected events with CoreSight Trace data\n"); + return 0; + } + + memset(&attr, 0, sizeof(struct perf_event_attr)); + attr.size = sizeof(struct perf_event_attr); + attr.type = PERF_TYPE_HARDWARE; + attr.sample_type = evsel->attr.sample_type & PERF_SAMPLE_MASK; + attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID | + PERF_SAMPLE_PERIOD; + if (etm->timeless_decoding) + attr.sample_type &= ~(u64)PERF_SAMPLE_TIME; + else + attr.sample_type |= PERF_SAMPLE_TIME; + + attr.exclude_user = evsel->attr.exclude_user; + attr.exclude_kernel = evsel->attr.exclude_kernel; + attr.exclude_hv = evsel->attr.exclude_hv; + attr.exclude_host = evsel->attr.exclude_host; + attr.exclude_guest = evsel->attr.exclude_guest; + attr.sample_id_all = evsel->attr.sample_id_all; + attr.read_format = evsel->attr.read_format; + + /* create new id val to be a fixed offset from evsel id */ + id = evsel->id[0] + 1000000000; + + if (!id) + id = 1; + + if (etm->synth_opts.branches) { + attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS; + attr.sample_period = 1; + attr.sample_type |= PERF_SAMPLE_ADDR; + err = cs_etm__synth_event(session, &attr, id); + if (err) + return err; + etm->sample_branches = true; + etm->branches_sample_type = attr.sample_type; + etm->branches_id = id; + } + + return 0; +} + +static int cs_etm__sample(struct cs_etm_queue *etmq) +{ + int ret; + struct cs_etm_packet packet; + + while (1) { + ret = cs_etm_decoder__get_packet(etmq->decoder, &packet); + if (ret <= 0) + return ret; + + /* + * If the packet contains an instruction range, generate an + * instruction sequence event. + */ + if (packet.sample_type & CS_ETM_RANGE) + cs_etm__synth_branch_sample(etmq, &packet); + } + + return 0; +} + static int cs_etm__run_decoder(struct cs_etm_queue *etmq) { struct cs_etm_auxtrace *etm = etmq->etm; @@ -494,6 +645,12 @@ more: etmq->offset += processed; buffer_used += processed; + + /* + * Nothing to do with an error condition, let's hope the next + * chunk will be better. + */ + err = cs_etm__sample(etmq); } while (buffer.len > buffer_used); goto more; @@ -828,6 +985,17 @@ int cs_etm__process_auxtrace_info(union perf_event *event, return 0; } + if (session->itrace_synth_opts && session->itrace_synth_opts->set) { + etm->synth_opts = *session->itrace_synth_opts; + } else { + itrace_synth_opts__set_default(&etm->synth_opts); + etm->synth_opts.callchain = false; + } + + err = cs_etm__synth_events(etm, session); + if (err) + goto err_free_queues; + err = auxtrace_queues__process_index(&etm->queues, session); if (err) goto err_free_queues;