Received: by 10.223.176.5 with SMTP id f5csp2163708wra; Sun, 28 Jan 2018 13:56:19 -0800 (PST) X-Google-Smtp-Source: AH8x226CQ8HPlTlr3oXCCiwB+3AOKtABO8OsaSAAv8wvUqCZJzFIMu9WHDx4ALAAiAsdhBLSY5mZ X-Received: by 2002:a17:902:2865:: with SMTP id e92-v6mr19017489plb.267.1517176578866; Sun, 28 Jan 2018 13:56:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517176578; cv=none; d=google.com; s=arc-20160816; b=sfBgD3LbLY+8e6++fwrcnipXTMgQbcMKI+4Pd8Z3rAFr0Gg0vqTxowvmfL48WBwnsH ATnnwxG7xWjmQ9ePVDJIHDEOtKy+/HUP7B7WbYJhSNCG5Tcz+XRwqx058z3UhXKxIVsF KGhF9wsO2iwzhycIYE1o0MuDvuYwXWim4ZpX9Yt5bBoK3LMGNRTV9i2egqErH+Gt71n8 c2gSGUCrzHwZSp9pqnBnZkyEhxlsbHswz9UByGJkzK5S/+N4v/TUtBfj+es3iKKi7L6Z WzFYn+QF1Hvv8iH35wG1I/DATLRR+4ZmM9v4VaglDTZ1YQDjaaoMimbquBLC8VoPI1cw 8bsw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-disposition :content-transfer-encoding:mime-version:robot-unsubscribe:robot-id :git-commit-id:subject:to:references:in-reply-to:reply-to:cc :message-id:from:date:arc-authentication-results; bh=eeOUOAh3qEY+kWUFT4zRSpayWK3gofC+DT/U2zjSFRk=; b=MhIztMYyewSPJbO11f1v01vMYZlqEZqDB7awfoBzF+O7z6NwkGgQ6MlWY2UZVJ7b/9 mjaUb32tqvRYknfYbaaU5gy9YuNSMuEVszclr3QEuxbK/To8AkkphbKwGjXr/Fbxtr2X 5Tv7eG37m17Que9QU2C4kPDhMuB93CoFyjg/Zqo4ryA3Ls9kdWRUz+nGdczi/v0woRJZ 94XMJJGz8Dii6r8p2ULrLcrZuxiv3YwtNh5GjVszPylrcBcBknWNG1o0mU57mthWqDoL YrbGThCNYBZbFekd6f8K/CPicSGYb2GOUNbgUdUmliyV8+mvghmw6osd4ldU/6xIbLih b1WA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p7si10450349pfk.8.2018.01.28.13.56.04; Sun, 28 Jan 2018 13:56:18 -0800 (PST) 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; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753209AbeA1VUp (ORCPT + 99 others); Sun, 28 Jan 2018 16:20:45 -0500 Received: from terminus.zytor.com ([65.50.211.136]:59971 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753069AbeA1VUm (ORCPT ); Sun, 28 Jan 2018 16:20:42 -0500 Received: from terminus.zytor.com (localhost [127.0.0.1]) by terminus.zytor.com (8.15.2/8.15.2) with ESMTP id w0SLH8ic007594; Sun, 28 Jan 2018 13:17:08 -0800 Received: (from tipbot@localhost) by terminus.zytor.com (8.15.2/8.15.2/Submit) id w0SLH7rU007583; Sun, 28 Jan 2018 13:17:07 -0800 Date: Sun, 28 Jan 2018 13:17:07 -0800 X-Authentication-Warning: terminus.zytor.com: tipbot set sender to tipbot@zytor.com using -f From: tip-bot for Tor Jeremiassen Message-ID: Cc: suzuki.poulose@arm.com, jolsa@redhat.com, linux-kernel@vger.kernel.org, adrian.hunter@intel.com, mathieu.poirier@linaro.org, kim.phillips@arm.com, peterz@infradead.org, hpa@zytor.com, mike.leach@arm.com, tor@ti.com, tglx@linutronix.de, alexander.shishkin@linux.intel.com, acme@redhat.com, mingo@kernel.org, namhyung@kernel.org Reply-To: kim.phillips@arm.com, adrian.hunter@intel.com, mathieu.poirier@linaro.org, jolsa@redhat.com, linux-kernel@vger.kernel.org, suzuki.poulose@arm.com, namhyung@kernel.org, mingo@kernel.org, acme@redhat.com, alexander.shishkin@linux.intel.com, hpa@zytor.com, mike.leach@arm.com, peterz@infradead.org, tglx@linutronix.de, tor@ti.com In-Reply-To: <1516211539-5166-4-git-send-email-mathieu.poirier@linaro.org> References: <1516211539-5166-4-git-send-email-mathieu.poirier@linaro.org> To: linux-tip-commits@vger.kernel.org Subject: [tip:perf/core] perf tools: Add processing of coresight metadata Git-Commit-ID: cd8bfd8c973eaff8e15260cf1f02e2b84c9b1cb9 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 X-Spam-Status: No, score=-2.9 required=5.0 tests=ALL_TRUSTED,BAYES_00 autolearn=ham autolearn_force=no version=3.4.1 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on terminus.zytor.com Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: cd8bfd8c973eaff8e15260cf1f02e2b84c9b1cb9 Gitweb: https://git.kernel.org/tip/cd8bfd8c973eaff8e15260cf1f02e2b84c9b1cb9 Author: Tor Jeremiassen AuthorDate: Wed, 17 Jan 2018 10:52:12 -0700 Committer: Arnaldo Carvalho de Melo CommitDate: Thu, 25 Jan 2018 06:37:24 -0300 perf tools: Add processing of coresight metadata The auxtrace_info section contains metadata that describes the number of trace capable CPUs, their ETM version and trace configuration, including trace id values. This information is required by the trace decoder in order to properly decode the compressed trace packets. This patch adds code to read and parse this metadata, and store it for use in configuring instances of the cs-etm trace decoder. Co-authored-by: Mathieu Poirier Signed-off-by: Tor Jeremiassen 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-4-git-send-email-mathieu.poirier@linaro.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cs-etm.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++- tools/perf/util/cs-etm.h | 3 + 2 files changed, 194 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index f477971..18894ee 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -102,12 +102,24 @@ static void cs_etm__free_events(struct perf_session *session) static void cs_etm__free(struct perf_session *session) { + int i; + struct int_node *inode, *tmp; struct cs_etm_auxtrace *aux = container_of(session->auxtrace, struct cs_etm_auxtrace, auxtrace); cs_etm__free_events(session); session->auxtrace = NULL; + /* First remove all traceID/CPU# nodes for the RB tree */ + intlist__for_each_entry_safe(inode, tmp, traceid_list) + intlist__remove(traceid_list, inode); + /* Then the RB tree itself */ + intlist__delete(traceid_list); + + for (i = 0; i < aux->num_cpu; i++) + zfree(&aux->metadata[i]); + + zfree(&aux->metadata); zfree(&aux); } @@ -151,15 +163,69 @@ static bool cs_etm__is_timeless_decoding(struct cs_etm_auxtrace *etm) return timeless_decoding; } +static const char * const cs_etm_global_header_fmts[] = { + [CS_HEADER_VERSION_0] = " Header version %llx\n", + [CS_PMU_TYPE_CPUS] = " PMU type/num cpus %llx\n", + [CS_ETM_SNAPSHOT] = " Snapshot %llx\n", +}; + +static const char * const cs_etm_priv_fmts[] = { + [CS_ETM_MAGIC] = " Magic number %llx\n", + [CS_ETM_CPU] = " CPU %lld\n", + [CS_ETM_ETMCR] = " ETMCR %llx\n", + [CS_ETM_ETMTRACEIDR] = " ETMTRACEIDR %llx\n", + [CS_ETM_ETMCCER] = " ETMCCER %llx\n", + [CS_ETM_ETMIDR] = " ETMIDR %llx\n", +}; + +static const char * const cs_etmv4_priv_fmts[] = { + [CS_ETM_MAGIC] = " Magic number %llx\n", + [CS_ETM_CPU] = " CPU %lld\n", + [CS_ETMV4_TRCCONFIGR] = " TRCCONFIGR %llx\n", + [CS_ETMV4_TRCTRACEIDR] = " TRCTRACEIDR %llx\n", + [CS_ETMV4_TRCIDR0] = " TRCIDR0 %llx\n", + [CS_ETMV4_TRCIDR1] = " TRCIDR1 %llx\n", + [CS_ETMV4_TRCIDR2] = " TRCIDR2 %llx\n", + [CS_ETMV4_TRCIDR8] = " TRCIDR8 %llx\n", + [CS_ETMV4_TRCAUTHSTATUS] = " TRCAUTHSTATUS %llx\n", +}; + +static void cs_etm__print_auxtrace_info(u64 *val, int num) +{ + int i, j, cpu = 0; + + for (i = 0; i < CS_HEADER_VERSION_0_MAX; i++) + fprintf(stdout, cs_etm_global_header_fmts[i], val[i]); + + for (i = CS_HEADER_VERSION_0_MAX; cpu < num; cpu++) { + if (val[i] == __perf_cs_etmv3_magic) + for (j = 0; j < CS_ETM_PRIV_MAX; j++, i++) + fprintf(stdout, cs_etm_priv_fmts[j], val[i]); + else if (val[i] == __perf_cs_etmv4_magic) + for (j = 0; j < CS_ETMV4_PRIV_MAX; j++, i++) + fprintf(stdout, cs_etmv4_priv_fmts[j], val[i]); + else + /* failure.. return */ + return; + } +} + int cs_etm__process_auxtrace_info(union perf_event *event, struct perf_session *session) { struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info; struct cs_etm_auxtrace *etm = NULL; + struct int_node *inode; + unsigned int pmu_type; int event_header_size = sizeof(struct perf_event_header); int info_header_size; int total_size = auxtrace_info->header.size; - int err = 0; + int priv_size = 0; + int num_cpu; + int err = 0, idx = -1; + int i, j, k; + u64 *ptr, *hdr = NULL; + u64 **metadata = NULL; /* * sizeof(auxtrace_info_event::type) + @@ -170,10 +236,117 @@ int cs_etm__process_auxtrace_info(union perf_event *event, if (total_size < (event_header_size + info_header_size)) return -EINVAL; + priv_size = total_size - event_header_size - info_header_size; + + /* First the global part */ + ptr = (u64 *) auxtrace_info->priv; + + /* Look for version '0' of the header */ + if (ptr[0] != 0) + return -EINVAL; + + hdr = zalloc(sizeof(*hdr) * CS_HEADER_VERSION_0_MAX); + if (!hdr) + return -ENOMEM; + + /* Extract header information - see cs-etm.h for format */ + for (i = 0; i < CS_HEADER_VERSION_0_MAX; i++) + hdr[i] = ptr[i]; + num_cpu = hdr[CS_PMU_TYPE_CPUS] & 0xffffffff; + pmu_type = (unsigned int) ((hdr[CS_PMU_TYPE_CPUS] >> 32) & + 0xffffffff); + + /* + * Create an RB tree for traceID-CPU# tuple. Since the conversion has + * to be made for each packet that gets decoded, optimizing access in + * anything other than a sequential array is worth doing. + */ + traceid_list = intlist__new(NULL); + if (!traceid_list) { + err = -ENOMEM; + goto err_free_hdr; + } + + metadata = zalloc(sizeof(*metadata) * num_cpu); + if (!metadata) { + err = -ENOMEM; + goto err_free_traceid_list; + } + + /* + * The metadata is stored in the auxtrace_info section and encodes + * the configuration of the ARM embedded trace macrocell which is + * required by the trace decoder to properly decode the trace due + * to its highly compressed nature. + */ + for (j = 0; j < num_cpu; j++) { + if (ptr[i] == __perf_cs_etmv3_magic) { + metadata[j] = zalloc(sizeof(*metadata[j]) * + CS_ETM_PRIV_MAX); + if (!metadata[j]) { + err = -ENOMEM; + goto err_free_metadata; + } + for (k = 0; k < CS_ETM_PRIV_MAX; k++) + metadata[j][k] = ptr[i + k]; + + /* The traceID is our handle */ + idx = metadata[j][CS_ETM_ETMTRACEIDR]; + i += CS_ETM_PRIV_MAX; + } else if (ptr[i] == __perf_cs_etmv4_magic) { + metadata[j] = zalloc(sizeof(*metadata[j]) * + CS_ETMV4_PRIV_MAX); + if (!metadata[j]) { + err = -ENOMEM; + goto err_free_metadata; + } + for (k = 0; k < CS_ETMV4_PRIV_MAX; k++) + metadata[j][k] = ptr[i + k]; + + /* The traceID is our handle */ + idx = metadata[j][CS_ETMV4_TRCTRACEIDR]; + i += CS_ETMV4_PRIV_MAX; + } + + /* Get an RB node for this CPU */ + inode = intlist__findnew(traceid_list, idx); + + /* Something went wrong, no need to continue */ + if (!inode) { + err = PTR_ERR(inode); + goto err_free_metadata; + } + + /* + * The node for that CPU should not be taken. + * Back out if that's the case. + */ + if (inode->priv) { + err = -EINVAL; + goto err_free_metadata; + } + /* All good, associate the traceID with the CPU# */ + inode->priv = &metadata[j][CS_ETM_CPU]; + } + + /* + * Each of CS_HEADER_VERSION_0_MAX, CS_ETM_PRIV_MAX and + * CS_ETMV4_PRIV_MAX mark how many double words are in the + * global metadata, and each cpu's metadata respectively. + * The following tests if the correct number of double words was + * present in the auxtrace info section. + */ + if (i * 8 != priv_size) { + err = -EINVAL; + goto err_free_metadata; + } + etm = zalloc(sizeof(*etm)); - if (!etm) + if (!etm) { err = -ENOMEM; + goto err_free_metadata; + } err = auxtrace_queues__init(&etm->queues); if (err) @@ -182,6 +355,10 @@ int cs_etm__process_auxtrace_info(union perf_event *event, etm->session = session; etm->machine = &session->machines.host; + etm->num_cpu = num_cpu; + etm->pmu_type = pmu_type; + etm->snapshot_mode = (hdr[CS_ETM_SNAPSHOT] != 0); + etm->metadata = metadata; etm->auxtrace_type = auxtrace_info->type; etm->timeless_decoding = cs_etm__is_timeless_decoding(etm); @@ -192,8 +369,10 @@ int cs_etm__process_auxtrace_info(union perf_event *event, etm->auxtrace.free = cs_etm__free; session->auxtrace = &etm->auxtrace; - if (dump_trace) + if (dump_trace) { + cs_etm__print_auxtrace_info(auxtrace_info->priv, num_cpu); return 0; + } err = auxtrace_queues__process_index(&etm->queues, session); if (err) @@ -208,6 +387,15 @@ err_free_queues: session->auxtrace = NULL; err_free_etm: zfree(&etm); +err_free_metadata: + /* No need to check @metadata[j], free(NULL) is supported */ + for (j = 0; j < num_cpu; j++) + free(metadata[j]); + zfree(&metadata); +err_free_traceid_list: + intlist__delete(traceid_list); +err_free_hdr: + zfree(&hdr); return -EINVAL; } diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h index 5ab6a8e..5864d5d 100644 --- a/tools/perf/util/cs-etm.h +++ b/tools/perf/util/cs-etm.h @@ -64,6 +64,9 @@ enum { CS_ETMV4_PRIV_MAX, }; +/* RB tree for quick conversion between traceID and CPUs */ +struct intlist *traceid_list; + #define KiB(x) ((x) * 1024) #define MiB(x) ((x) * 1024 * 1024)