From patchwork Sun Oct 18 18:24:47 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathieu Poirier X-Patchwork-Id: 55195 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lf0-f72.google.com (mail-lf0-f72.google.com [209.85.215.72]) by patches.linaro.org (Postfix) with ESMTPS id 96E5122FFA for ; Sun, 18 Oct 2015 18:27:09 +0000 (UTC) Received: by lfaz124 with SMTP id z124sf32581690lfa.0 for ; Sun, 18 Oct 2015 11:27:08 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=THuCV8KWTSdkW7Vh8wovlB3S8YDasUCs8jPpDazEarQ=; b=mtY0mJgfAXySVzXmUs0z/rbjNMYGlrWzx5mKeIwBgK+fLVg4J4EQg3zSBDGzs040V8 q3wUAabB8sH9TqAyZe7FdNv1prdLUInv7JgoGUwalpsiRRHzBOafPwj93I+P8jYwxDr7 kWS+AfqqBJoJketjt5SQ1FPnwJexf4SNSZCq1EaUFqCbeN1yDCU8oPUwvGaG7ViJX3yF olJZUc8BLvHe7G5iV4NKtocJfx6V1lxlyUNHUUrlA8A4eqyzI5HXsImDyosJ4fh75heA LkV35YYS12QSC6kpFMa/xtMxe2XokYoA5i2PhMyjk4uAZ0cK0QzUbwUkyZ6KX/3XEPZR JmIA== X-Gm-Message-State: ALoCoQkzOcoWANRRopP4nMVLAwzj0LlronMP7BzhBxOGq7nic+zz8JRArQcm1pmo/sSZBurlAMw9 X-Received: by 10.112.184.170 with SMTP id ev10mr6106360lbc.4.1445192828327; Sun, 18 Oct 2015 11:27:08 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.25.28.195 with SMTP id c186ls369933lfc.71.gmail; Sun, 18 Oct 2015 11:27:08 -0700 (PDT) X-Received: by 10.112.63.135 with SMTP id g7mr12661848lbs.16.1445192828029; Sun, 18 Oct 2015 11:27:08 -0700 (PDT) Received: from mail-lf0-f51.google.com (mail-lf0-f51.google.com. [209.85.215.51]) by mx.google.com with ESMTPS id o76si15273641lfi.6.2015.10.18.11.27.07 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 18 Oct 2015 11:27:07 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.51 as permitted sender) client-ip=209.85.215.51; Received: by lffv3 with SMTP id v3so98010529lff.0 for ; Sun, 18 Oct 2015 11:27:07 -0700 (PDT) X-Received: by 10.25.82.76 with SMTP id g73mr777664lfb.56.1445192827805; Sun, 18 Oct 2015 11:27:07 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp1078204lbq; Sun, 18 Oct 2015 11:27:06 -0700 (PDT) X-Received: by 10.68.65.104 with SMTP id w8mr29806724pbs.48.1445192826260; Sun, 18 Oct 2015 11:27:06 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id wy2si46465406pab.104.2015.10.18.11.27.05; Sun, 18 Oct 2015 11:27:06 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752865AbbJRS1C (ORCPT + 28 others); Sun, 18 Oct 2015 14:27:02 -0400 Received: from mail-pa0-f52.google.com ([209.85.220.52]:35754 "EHLO mail-pa0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752666AbbJRS0Y (ORCPT ); Sun, 18 Oct 2015 14:26:24 -0400 Received: by pasz6 with SMTP id z6so6771256pas.2 for ; Sun, 18 Oct 2015 11:26:24 -0700 (PDT) X-Received: by 10.68.197.226 with SMTP id ix2mr23090992pbc.42.1445192783981; Sun, 18 Oct 2015 11:26:23 -0700 (PDT) Received: from t430.cg.shawcable.net (S0106002369de4dac.cg.shawcable.net. [184.64.168.246]) by smtp.gmail.com with ESMTPSA id hq1sm20402076pbb.43.2015.10.18.11.26.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 18 Oct 2015 11:26:23 -0700 (PDT) From: Mathieu Poirier To: gregkh@linuxfoundation.org, a.p.zijlstra@chello.nl, alexander.shishkin@linux.intel.com, acme@kernel.org, mingo@redhat.com, corbet@lwn.net, nicolas.pitre@linaro.org Cc: adrian.hunter@intel.com, zhang.chunyan@linaro.org, mike.leach@arm.com, tor@ti.com, al.grant@arm.com, pawel.moll@arm.com, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, mathieu.poirier@linaro.org Subject: [PATCH V2 30/30] perf tools: adding coresight etm PMU record capabilities Date: Sun, 18 Oct 2015 12:24:47 -0600 Message-Id: <1445192687-24112-31-git-send-email-mathieu.poirier@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1445192687-24112-1-git-send-email-mathieu.poirier@linaro.org> References: <1445192687-24112-1-git-send-email-mathieu.poirier@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: mathieu.poirier@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.51 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Coresight ETMs are IP blocks allowing to perform HW assisted tracing on a CPU core. This patch introduce the required auxiliary API functions allowing the perf core to interact with a tracer. Signed-off-by: Mathieu Poirier --- tools/perf/arch/arm/util/Build | 2 +- tools/perf/arch/arm/util/auxtrace.c | 48 ++++ tools/perf/arch/arm/util/cs_etm.c | 444 ++++++++++++++++++++++++++++++++++++ tools/perf/arch/arm/util/cs_etm.h | 37 +++ 4 files changed, 530 insertions(+), 1 deletion(-) create mode 100644 tools/perf/arch/arm/util/auxtrace.c create mode 100644 tools/perf/arch/arm/util/cs_etm.c create mode 100644 tools/perf/arch/arm/util/cs_etm.h diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build index 371a3bf12297..87545604b029 100644 --- a/tools/perf/arch/arm/util/Build +++ b/tools/perf/arch/arm/util/Build @@ -3,4 +3,4 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-$(CONFIG_AUXTRACE_ARM) += pmu.o +libperf-$(CONFIG_AUXTRACE_ARM) += pmu.o auxtrace.o cs_etm.o diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c new file mode 100644 index 000000000000..4988fdf7cb8a --- /dev/null +++ b/tools/perf/arch/arm/util/auxtrace.c @@ -0,0 +1,48 @@ +/* + * Copyright(C) 2015 Linaro Limited. All rights reserved. + * Author: Mathieu Poirier + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include +#include + +#include "../../util/auxtrace.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "cs_etm.h" + +struct auxtrace_record +*auxtrace_record__init(struct perf_evlist *evlist, int *err) +{ + struct perf_pmu *cs_etm_pmu; + struct perf_evsel *evsel; + bool found_etm = false; + + cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME); + + if (evlist) { + evlist__for_each(evlist, evsel) { + if (cs_etm_pmu && + evsel->attr.type == cs_etm_pmu->type) + found_etm = true; + } + } + + if (found_etm) + return cs_etm_record_init(err); + + *err = -EINVAL; + return NULL; +} diff --git a/tools/perf/arch/arm/util/cs_etm.c b/tools/perf/arch/arm/util/cs_etm.c new file mode 100644 index 000000000000..2e89b44dd4da --- /dev/null +++ b/tools/perf/arch/arm/util/cs_etm.c @@ -0,0 +1,444 @@ +/* + * Copyright(C) 2015 Linaro Limited. All rights reserved. + * Author: Mathieu Poirier + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include "../../perf.h" +#include "../../util/auxtrace.h" +#include "../../util/cpumap.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "../../util/thread_map.h" +#include "cs_etm.h" + +#include + +/* Also used by Intel - should go to a common header */ +#define KiB(x) ((x) * 1024) +#define MiB(x) ((x) * 1024 * 1024) + +struct cs_etm_recording { + struct auxtrace_record itr; + struct perf_pmu *cs_etm_pmu; + struct perf_evlist *evlist; + bool snapshot_mode; + size_t snapshot_size; +}; + +static int cs_etm_parse_snapshot_options(struct auxtrace_record *itr, + struct record_opts *opts, + const char *str) +{ + struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); + unsigned long long snapshot_size = 0; + char *endptr; + + if (str) { + snapshot_size = strtoull(str, &endptr, 0); + if (*endptr || snapshot_size > SIZE_MAX) + return -1; + } + + opts->auxtrace_snapshot_mode = true; + opts->auxtrace_snapshot_size = snapshot_size; + ptr->snapshot_size = snapshot_size; + + return 0; +} + +static int cs_etm_recording_options(struct auxtrace_record *itr, + struct perf_evlist *evlist, + struct record_opts *opts) +{ + struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); + struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; + struct perf_evsel *evsel, *cs_etm_evsel = NULL; + const struct cpu_map *cpus = evlist->cpus; + bool privileged = (geteuid() == 0 || perf_event_paranoid() < 0); + + ptr->evlist = evlist; + ptr->snapshot_mode = opts->auxtrace_snapshot_mode; + + evlist__for_each(evlist, evsel) { + if (evsel->attr.type == cs_etm_pmu->type) { + if (cs_etm_evsel) { + pr_err("There may be only one %s event\n", + CORESIGHT_ETM_PMU_NAME); + return -EINVAL; + } + evsel->attr.freq = 0; + evsel->attr.sample_period = 1; + cs_etm_evsel = evsel; + opts->full_auxtrace = true; + } + } + + /* no need to continue if at least one event of interest was found */ + if (!cs_etm_evsel) + return 0; + + if (opts->use_clockid) { + pr_err("Cannot use clockid (-k option) with %s\n", + CORESIGHT_ETM_PMU_NAME); + return -EINVAL; + } + + /* we are in snapshot mode */ + if (opts->auxtrace_snapshot_mode) { + /* + * No size were given to '-S' or '-m,', so go with + * the default + */ + if (!opts->auxtrace_snapshot_size && + !opts->auxtrace_mmap_pages) { + if (privileged) { + opts->auxtrace_mmap_pages = MiB(4) / page_size; + } else { + opts->auxtrace_mmap_pages = + KiB(128) / page_size; + if (opts->mmap_pages == UINT_MAX) + opts->mmap_pages = KiB(256) / page_size; + } + } else if (!opts->auxtrace_mmap_pages && !privileged && + opts->mmap_pages == UINT_MAX) { + opts->mmap_pages = KiB(256) / page_size; + } + + /* + * '-m,xyz' was specified but no snapshot size, so make the + * snapshot size as big as the auxtrace mmap area. + */ + if (!opts->auxtrace_snapshot_size) { + opts->auxtrace_snapshot_size = + opts->auxtrace_mmap_pages * (size_t)page_size; + } + + /* + * -Sxyz was specified but no auxtrace mmap area, so make the + * auxtrace mmap area big enough to fit the requested snapshot + * size. + */ + if (!opts->auxtrace_mmap_pages) { + size_t sz = opts->auxtrace_snapshot_size; + + sz = round_up(sz, page_size) / page_size; + opts->auxtrace_mmap_pages = roundup_pow_of_two(sz); + } + + /* Snapshost size can't be bigger than the auxtrace area */ + if (opts->auxtrace_snapshot_size > + opts->auxtrace_mmap_pages * (size_t)page_size) { + pr_err("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n", + opts->auxtrace_snapshot_size, + opts->auxtrace_mmap_pages * (size_t)page_size); + return -EINVAL; + } + + /* Something went wrong somewhere - this shouldn't happen */ + if (!opts->auxtrace_snapshot_size || + !opts->auxtrace_mmap_pages) { + pr_err("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n"); + return -EINVAL; + } + } + + /* We are in full trace mode but '-m,xyz' wasn't specified */ + if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) { + if (privileged) { + opts->auxtrace_mmap_pages = MiB(4) / page_size; + } else { + opts->auxtrace_mmap_pages = KiB(128) / page_size; + if (opts->mmap_pages == UINT_MAX) + opts->mmap_pages = KiB(256) / page_size; + } + + } + + /* Validate auxtrace_mmap_pages provided by user */ + if (opts->auxtrace_mmap_pages) { + unsigned int max_page = (KiB(128) / page_size); + size_t sz = opts->auxtrace_mmap_pages * (size_t)page_size; + + if (!privileged && + opts->auxtrace_mmap_pages > max_page) { + opts->auxtrace_mmap_pages = max_page; + pr_err("auxtrace too big, truncating to %d\n", + max_page); + } + + if (!is_power_of_2(sz)) { + pr_err("Invalid mmap size for %s: must be a power of 2\n", + CORESIGHT_ETM_PMU_NAME); + return -EINVAL; + } + } + + if (opts->auxtrace_snapshot_mode) + pr_debug2("%s snapshot size: %zu\n", CORESIGHT_ETM_PMU_NAME, + opts->auxtrace_snapshot_size); + + if (cs_etm_evsel) { + /* + * To obtain the auxtrace buffer file descriptor, the auxtrace + * event must come first. + */ + perf_evlist__to_front(evlist, cs_etm_evsel); + /* + * In the case of per-cpu mmaps, we need the CPU on the + * AUX event. + */ + if (!cpu_map__empty(cpus)) + perf_evsel__set_sample_bit(cs_etm_evsel, CPU); + } + + /* Add dummy event to keep tracking */ + if (opts->full_auxtrace) { + struct perf_evsel *tracking_evsel; + int err; + + err = parse_events(evlist, "dummy:u", NULL); + if (err) + return err; + + tracking_evsel = perf_evlist__last(evlist); + perf_evlist__set_tracking_event(evlist, tracking_evsel); + + tracking_evsel->attr.freq = 0; + tracking_evsel->attr.sample_period = 1; + + /* In per-cpu case, always need the time of mmap events etc */ + if (!cpu_map__empty(cpus)) + perf_evsel__set_sample_bit(tracking_evsel, TIME); + } + + return 0; +} + +static size_t +cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused, + struct perf_session *session __maybe_unused) +{ + int records; + const struct cpu_map *cpus = session->evlist->cpus; + + if (!cpu_map__empty(cpus)) { + records = cpu_map__nr(cpus); + goto out; + } + + set_max_cpu_num(); + records = cpu__max_cpu(); +out: + return records * CS_ETM_PRIV_SIZE; +} + +static const char *metadata[CS_ETM_PRIV_MAX] = { + [CS_ETM_ETMCR] = "etmcr", + [CS_ETM_ETMCCER] = "etmccer", + [CS_ETM_ETMIDR] = "etmidr", + [CS_ETM_ETMTRACEIDR] = "etmtraceidr", +}; + +static int cs_etm_get_metadata(int cpu, int offset, + struct cs_etm_recording *ptr, + struct auxtrace_info_event *info) +{ + int i, ret = 0; + const char *sysfs = sysfs__mountpoint(); + + if (!sysfs) + return -EINVAL; + + info->priv[offset + CS_ETM_MAGIC] = __perf_cs_etm_magic; + info->priv[offset + CS_ETM_CPU] = cpu; + info->priv[offset + CS_ETM_SNAPSHOT] = ptr->snapshot_mode; + + /* get metadata from sysfs */ + for (i = CS_ETM_ETMCR; i < CS_ETM_PRIV_MAX && !ret; i++) { + FILE *file; + char path[PATH_MAX], value[128]; + + snprintf(path, PATH_MAX, + "%s" EVENT_SOURCE_DEVICE_PATH "%s/cpu%d/mgmt/%s", + sysfs, CORESIGHT_ETM_PMU_NAME, cpu, metadata[i]); + + file = fopen(path, "r"); + if (!file) + return -EINVAL; + + if (fscanf(file, "%s", value) != 1) + ret = -EINVAL; + + fclose(file); + + info->priv[offset + i] = strtol(value, NULL, 16); + } + + return 0; +} + +static int cs_etm_info_fill(struct auxtrace_record *itr, + struct perf_session *session, + struct auxtrace_info_event *auxtrace_info, + size_t priv_size) +{ + int i, nr_cpu, ret = 0; + const struct cpu_map *cpus = session->evlist->cpus; + struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); + + if (priv_size != cs_etm_info_priv_size(itr, session)) + return -EINVAL; + + if (!session->evlist->nr_mmaps) + return -EINVAL; + + auxtrace_info->type = PERF_AUXTRACE_CS_ETM; + + /* cpu map is not empty, we have specific CPUs to work with */ + if (!cpu_map__empty(cpus)) { + for (i = 0; i < cpu_map__nr(cpus); i++) + ret = cs_etm_get_metadata(cpus->map[i], + i * CS_ETM_PRIV_MAX, + ptr, auxtrace_info); + if (ret) + goto out; + } + + /* get configuration for all CPUs in the system */ + nr_cpu = cpu__max_cpu(); + for (i = 0; i < nr_cpu; i++) { + ret = cs_etm_get_metadata(i, i * CS_ETM_PRIV_MAX, + ptr, auxtrace_info); + if (ret) + goto out; + } + +out: + return ret; +} + +static int cs_etm_find_snapshot(struct auxtrace_record *itr __maybe_unused, + int idx, struct auxtrace_mmap *mm, + unsigned char *data __maybe_unused, + u64 *head, u64 *old) +{ + pr_debug3("%s: mmap index %d old head %zu new head %zu size %zu\n", + __func__, idx, (size_t)*old, (size_t)*head, mm->len); + + *old = *head; + *head += mm->len; + + return 0; +} + +static int cs_etm_snapshot_start(struct auxtrace_record *itr) +{ + struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); + struct perf_evsel *evsel; + + evlist__for_each(ptr->evlist, evsel) { + if (evsel->attr.type == ptr->cs_etm_pmu->type) + return perf_evlist__disable_event(ptr->evlist, evsel); + } + return -EINVAL; +} + +static int cs_etm_snapshot_finish(struct auxtrace_record *itr) +{ + struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); + struct perf_evsel *evsel; + + evlist__for_each(ptr->evlist, evsel) { + if (evsel->attr.type == ptr->cs_etm_pmu->type) + return perf_evlist__enable_event(ptr->evlist, evsel); + } + return -EINVAL; +} + +static u64 cs_etm_reference(struct auxtrace_record *itr __maybe_unused) +{ + return (((u64) rand() << 0) & 0x00000000FFFFFFFFull) | + (((u64) rand() << 32) & 0xFFFFFFFF00000000ull); +} + +static void cs_etm_recording_free(struct auxtrace_record *itr) +{ + struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); + free(ptr); +} + +static int cs_etm_read_finish(struct auxtrace_record *itr, int idx) +{ + struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); + struct perf_evsel *evsel; + + evlist__for_each(ptr->evlist, evsel) { + if (evsel->attr.type == ptr->cs_etm_pmu->type) + return perf_evlist__enable_event_idx(ptr->evlist, + evsel, idx); + } + + return -EINVAL; +} + +struct auxtrace_record *cs_etm_record_init(int *err) +{ + struct perf_pmu *cs_etm_pmu; + struct cs_etm_recording *ptr; + + cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME); + + if (!cs_etm_pmu) { + *err = -EINVAL; + goto out; + } + + ptr = zalloc(sizeof(struct cs_etm_recording)); + if (!ptr) { + *err = -ENOMEM; + goto out; + } + + ptr->cs_etm_pmu = cs_etm_pmu; + ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options; + ptr->itr.recording_options = cs_etm_recording_options; + ptr->itr.info_priv_size = cs_etm_info_priv_size; + ptr->itr.info_fill = cs_etm_info_fill; + ptr->itr.find_snapshot = cs_etm_find_snapshot; + ptr->itr.snapshot_start = cs_etm_snapshot_start; + ptr->itr.snapshot_finish = cs_etm_snapshot_finish; + ptr->itr.reference = cs_etm_reference; + ptr->itr.free = cs_etm_recording_free; + ptr->itr.read_finish = cs_etm_read_finish; + + *err = 0; + return &ptr->itr; +out: + return NULL; +} diff --git a/tools/perf/arch/arm/util/cs_etm.h b/tools/perf/arch/arm/util/cs_etm.h new file mode 100644 index 000000000000..b3b3f16d80e3 --- /dev/null +++ b/tools/perf/arch/arm/util/cs_etm.h @@ -0,0 +1,37 @@ +/* + * Copyright(C) 2015 Linaro Limited. All rights reserved. + * Author: Mathieu Poirier + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef INCLUDE__PERF_CS_ETM_H__ +#define INCLUDE__PERF_CS_ETM_H__ + +enum { + CS_ETM_MAGIC, + CS_ETM_CPU, + CS_ETM_SNAPSHOT, + CS_ETM_ETMCR, + CS_ETM_ETMCCER, + CS_ETM_ETMIDR, + CS_ETM_ETMTRACEIDR, + CS_ETM_PRIV_MAX, +}; + +static const u64 __perf_cs_etm_magic = 0x3030303030303030ULL; +#define CS_ETM_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64)) + +struct auxtrace_record *cs_etm_record_init(int *err); + +#endif