From nobody Fri May 8 11:29:47 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CBB2EC433EF for ; Wed, 4 May 2022 15:02:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1351757AbiEDPGS (ORCPT ); Wed, 4 May 2022 11:06:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54514 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351747AbiEDPGL (ORCPT ); Wed, 4 May 2022 11:06:11 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 581C1377DB; Wed, 4 May 2022 08:02:33 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 24BD912FC; Wed, 4 May 2022 08:02:33 -0700 (PDT) Received: from hype-n1-sdp.warwick.arm.com (hype-n1-sdp.warwick.arm.com [10.32.32.32]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 1127E3F885; Wed, 4 May 2022 08:02:30 -0700 (PDT) From: German Gomez To: linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, acme@kernel.org Cc: German Gomez , Mike Leach , Leo Yan , John Garry , Will Deacon , Mathieu Poirier , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 1/4] perf pmu: Add function to check if a pmu file exists Date: Wed, 4 May 2022 16:02:12 +0100 Message-Id: <20220504150216.581281-2-german.gomez@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220504150216.581281-1-german.gomez@arm.com> References: <20220504150216.581281-1-german.gomez@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add a utility function perf_pmu__file_exists() to check if a given pmu file exists in the sysfs filesystem. Signed-off-by: German Gomez --- tools/perf/util/pmu.c | 17 +++++++++++++++++ tools/perf/util/pmu.h | 2 ++ 2 files changed, 19 insertions(+) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 9a1c7e63e663..9479e9a4da54 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1854,6 +1854,23 @@ int perf_pmu__scan_file(struct perf_pmu *pmu, const = char *name, const char *fmt, return ret; } =20 +bool perf_pmu__file_exists(struct perf_pmu *pmu, const char *name) +{ + char path[PATH_MAX]; + struct stat statbuf; + const char *sysfs =3D sysfs__mountpoint(); + + if (!sysfs) + return false; + + snprintf(path, PATH_MAX, + "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name); + if (!file_available(path)) + return false; + + return stat(path, &statbuf) =3D=3D 0; +} + static int perf_pmu__new_caps(struct list_head *list, char *name, char *va= lue) { struct perf_pmu_caps *caps =3D zalloc(sizeof(*caps)); diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 541889fa9f9c..ab728eaf13b6 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -120,6 +120,8 @@ bool pmu_have_event(const char *pname, const char *name= ); =20 int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char= *fmt, ...) __scanf(3, 4); =20 +bool perf_pmu__file_exists(struct perf_pmu *pmu, const char *name); + int perf_pmu__test(void); =20 struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu); --=20 2.25.1 From nobody Fri May 8 11:29:47 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EF0D5C433EF for ; Wed, 4 May 2022 15:02:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1351813AbiEDPG3 (ORCPT ); Wed, 4 May 2022 11:06:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54618 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351765AbiEDPGN (ORCPT ); Wed, 4 May 2022 11:06:13 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 40D9F36320; Wed, 4 May 2022 08:02:37 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 10EB213D5; Wed, 4 May 2022 08:02:37 -0700 (PDT) Received: from hype-n1-sdp.warwick.arm.com (hype-n1-sdp.warwick.arm.com [10.32.32.32]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id F148B3F885; Wed, 4 May 2022 08:02:34 -0700 (PDT) From: German Gomez To: linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, acme@kernel.org Cc: German Gomez , Mike Leach , Leo Yan , John Garry , Will Deacon , Mathieu Poirier , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 2/4] perf cs_etm: Keep separate symbols for ETMv4 and ETE parameters Date: Wed, 4 May 2022 16:02:13 +0100 Message-Id: <20220504150216.581281-3-german.gomez@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220504150216.581281-1-german.gomez@arm.com> References: <20220504150216.581281-1-german.gomez@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Previously, adding a new parameter at the end of ETMv4 meant adding it somewhere in the middle of ETE, which is not supported by the current header version. Signed-off-by: German Gomez --- tools/perf/arch/arm/util/cs-etm.c | 43 +++++++++++++++++++++++++----- tools/perf/util/cs-etm.c | 44 +++++++++++++++++++++---------- tools/perf/util/cs-etm.h | 11 +++++++- 3 files changed, 76 insertions(+), 22 deletions(-) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/c= s-etm.c index 11c71aa219f7..4899eb549b4d 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -53,7 +53,15 @@ static const char * const metadata_etmv4_ro[] =3D { [CS_ETMV4_TRCIDR2] =3D "trcidr/trcidr2", [CS_ETMV4_TRCIDR8] =3D "trcidr/trcidr8", [CS_ETMV4_TRCAUTHSTATUS] =3D "mgmt/trcauthstatus", - [CS_ETE_TRCDEVARCH] =3D "mgmt/trcdevarch" +}; + +static const char * const metadata_ete_ro[] =3D { + [CS_ETE_TRCIDR0] =3D "trcidr/trcidr0", + [CS_ETE_TRCIDR1] =3D "trcidr/trcidr1", + [CS_ETE_TRCIDR2] =3D "trcidr/trcidr2", + [CS_ETE_TRCIDR8] =3D "trcidr/trcidr8", + [CS_ETE_TRCAUTHSTATUS] =3D "mgmt/trcauthstatus", + [CS_ETE_TRCDEVARCH] =3D "mgmt/trcdevarch", }; =20 static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu); @@ -616,7 +624,7 @@ static bool cs_etm_is_ete(struct auxtrace_record *itr, = int cpu) { struct cs_etm_recording *ptr =3D container_of(itr, struct cs_etm_recordin= g, itr); struct perf_pmu *cs_etm_pmu =3D ptr->cs_etm_pmu; - int trcdevarch =3D cs_etm_get_ro(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ET= E_TRCDEVARCH]); + int trcdevarch =3D cs_etm_get_ro(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_= TRCDEVARCH]); =20 /* * ETE if ARCHVER is 5 (ARCHVER is 4 for ETM) and ARCHPART is 0xA13. @@ -647,6 +655,31 @@ static void cs_etm_save_etmv4_header(__u64 data[], str= uct auxtrace_record *itr, metadata_etmv4_ro[CS_ETMV4_TRCAUTHSTATUS]); } =20 +static void cs_etm_save_ete_header(__u64 data[], struct auxtrace_record *i= tr, int cpu) +{ + struct cs_etm_recording *ptr =3D container_of(itr, struct cs_etm_recordin= g, itr); + struct perf_pmu *cs_etm_pmu =3D ptr->cs_etm_pmu; + + /* Get trace configuration register */ + data[CS_ETE_TRCCONFIGR] =3D cs_etmv4_get_config(itr); + /* Get traceID from the framework */ + data[CS_ETE_TRCTRACEIDR] =3D coresight_get_trace_id(cpu); + /* Get read-only information from sysFS */ + data[CS_ETE_TRCIDR0] =3D cs_etm_get_ro(cs_etm_pmu, cpu, + metadata_ete_ro[CS_ETE_TRCIDR0]); + data[CS_ETE_TRCIDR1] =3D cs_etm_get_ro(cs_etm_pmu, cpu, + metadata_ete_ro[CS_ETE_TRCIDR1]); + data[CS_ETE_TRCIDR2] =3D cs_etm_get_ro(cs_etm_pmu, cpu, + metadata_ete_ro[CS_ETE_TRCIDR2]); + data[CS_ETE_TRCIDR8] =3D cs_etm_get_ro(cs_etm_pmu, cpu, + metadata_ete_ro[CS_ETE_TRCIDR8]); + data[CS_ETE_TRCAUTHSTATUS] =3D cs_etm_get_ro(cs_etm_pmu, cpu, + metadata_ete_ro[CS_ETE_TRCAUTHSTATUS]); + /* ETE uses the same registers as ETMv4 plus TRCDEVARCH */ + data[CS_ETE_TRCDEVARCH] =3D cs_etm_get_ro(cs_etm_pmu, cpu, + metadata_ete_ro[CS_ETE_TRCDEVARCH]); +} + static void cs_etm_get_metadata(int cpu, u32 *offset, struct auxtrace_record *itr, struct perf_record_auxtrace_info *info) @@ -660,11 +693,7 @@ static void cs_etm_get_metadata(int cpu, u32 *offset, /* first see what kind of tracer this cpu is affined to */ if (cs_etm_is_ete(itr, cpu)) { magic =3D __perf_cs_ete_magic; - /* ETE uses the same registers as ETMv4 plus TRCDEVARCH */ - cs_etm_save_etmv4_header(&info->priv[*offset], itr, cpu); - info->priv[*offset + CS_ETE_TRCDEVARCH] =3D - cs_etm_get_ro(cs_etm_pmu, cpu, - metadata_etmv4_ro[CS_ETE_TRCDEVARCH]); + cs_etm_save_ete_header(&info->priv[*offset], itr, cpu); =20 /* How much space was used */ increment =3D CS_ETE_PRIV_MAX; diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 8b95fb3c4d7b..5991a1a46b5c 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -464,12 +464,12 @@ static void cs_etm__set_trace_param_ete(struct cs_etm= _trace_params *t_params, u64 **metadata =3D etm->metadata; =20 t_params[idx].protocol =3D CS_ETM_PROTO_ETE; - t_params[idx].ete.reg_idr0 =3D metadata[idx][CS_ETMV4_TRCIDR0]; - t_params[idx].ete.reg_idr1 =3D metadata[idx][CS_ETMV4_TRCIDR1]; - t_params[idx].ete.reg_idr2 =3D metadata[idx][CS_ETMV4_TRCIDR2]; - t_params[idx].ete.reg_idr8 =3D metadata[idx][CS_ETMV4_TRCIDR8]; - t_params[idx].ete.reg_configr =3D metadata[idx][CS_ETMV4_TRCCONFIGR]; - t_params[idx].ete.reg_traceidr =3D metadata[idx][CS_ETMV4_TRCTRACEIDR]; + t_params[idx].ete.reg_idr0 =3D metadata[idx][CS_ETE_TRCIDR0]; + t_params[idx].ete.reg_idr1 =3D metadata[idx][CS_ETE_TRCIDR1]; + t_params[idx].ete.reg_idr2 =3D metadata[idx][CS_ETE_TRCIDR2]; + t_params[idx].ete.reg_idr8 =3D metadata[idx][CS_ETE_TRCIDR8]; + t_params[idx].ete.reg_configr =3D metadata[idx][CS_ETE_TRCCONFIGR]; + t_params[idx].ete.reg_traceidr =3D metadata[idx][CS_ETE_TRCTRACEIDR]; t_params[idx].ete.reg_devarch =3D metadata[idx][CS_ETE_TRCDEVARCH]; } =20 @@ -2537,7 +2537,20 @@ static const char * const cs_etmv4_priv_fmts[] =3D { [CS_ETMV4_TRCIDR2] =3D " TRCIDR2 %llx\n", [CS_ETMV4_TRCIDR8] =3D " TRCIDR8 %llx\n", [CS_ETMV4_TRCAUTHSTATUS] =3D " TRCAUTHSTATUS %llx\n", - [CS_ETE_TRCDEVARCH] =3D " TRCDEVARCH %llx\n" +}; + +static const char * const cs_ete_priv_fmts[] =3D { + [CS_ETM_MAGIC] =3D " Magic number %llx\n", + [CS_ETM_CPU] =3D " CPU %lld\n", + [CS_ETM_NR_TRC_PARAMS] =3D " NR_TRC_PARAMS %llx\n", + [CS_ETE_TRCCONFIGR] =3D " TRCCONFIGR %llx\n", + [CS_ETE_TRCTRACEIDR] =3D " TRCTRACEIDR %llx\n", + [CS_ETE_TRCIDR0] =3D " TRCIDR0 %llx\n", + [CS_ETE_TRCIDR1] =3D " TRCIDR1 %llx\n", + [CS_ETE_TRCIDR2] =3D " TRCIDR2 %llx\n", + [CS_ETE_TRCIDR8] =3D " TRCIDR8 %llx\n", + [CS_ETE_TRCAUTHSTATUS] =3D " TRCAUTHSTATUS %llx\n", + [CS_ETE_TRCDEVARCH] =3D " TRCDEVARCH %llx\n", }; =20 static const char * const param_unk_fmt =3D @@ -2597,19 +2610,22 @@ static int cs_etm__print_cpu_metadata_v1(__u64 *val= , int *offset) else fprintf(stdout, cs_etm_priv_fmts[j], val[i]); } - } else if (magic =3D=3D __perf_cs_etmv4_magic || magic =3D=3D __perf_cs_e= te_magic) { - /* - * ETE and ETMv4 can be printed in the same block because the number of = parameters - * is saved and they share the list of parameter names. ETE is also only= supported - * in V1 files. - */ + } else if (magic =3D=3D __perf_cs_etmv4_magic) { for (j =3D 0; j < total_params; j++, i++) { /* if newer record - could be excess params */ - if (j >=3D CS_ETE_PRIV_MAX) + if (j >=3D CS_ETMV4_PRIV_MAX) fprintf(stdout, param_unk_fmt, j, val[i]); else fprintf(stdout, cs_etmv4_priv_fmts[j], val[i]); } + } else if (magic =3D=3D __perf_cs_ete_magic) { + for (j =3D 0; j < total_params; j++, i++) { + /* if newer record - could be excess params */ + if (j >=3D CS_ETE_PRIV_MAX) + fprintf(stdout, param_unk_fmt, j, val[i]); + else + fprintf(stdout, cs_ete_priv_fmts[j], val[i]); + } } else { /* failure - note bad magic value and error out */ fprintf(stdout, magic_unk_fmt, magic); diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h index 90c83f932d9a..817d068de98c 100644 --- a/tools/perf/util/cs-etm.h +++ b/tools/perf/util/cs-etm.h @@ -81,7 +81,16 @@ enum { * added in header V1 */ enum { - CS_ETE_TRCDEVARCH =3D CS_ETMV4_PRIV_MAX, + /* Dynamic, configurable parameters */ + CS_ETE_TRCCONFIGR =3D CS_ETM_COMMON_BLK_MAX_V1, + CS_ETE_TRCTRACEIDR, + /* RO, taken from sysFS */ + CS_ETE_TRCIDR0, + CS_ETE_TRCIDR1, + CS_ETE_TRCIDR2, + CS_ETE_TRCIDR8, + CS_ETE_TRCAUTHSTATUS, + CS_ETE_TRCDEVARCH, CS_ETE_PRIV_MAX }; =20 --=20 2.25.1 From nobody Fri May 8 11:29:47 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 65AB3C433F5 for ; Wed, 4 May 2022 15:03:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231773AbiEDPGh (ORCPT ); Wed, 4 May 2022 11:06:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54650 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351774AbiEDPGS (ORCPT ); Wed, 4 May 2022 11:06:18 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2464D3EBAD; Wed, 4 May 2022 08:02:41 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id EDABD1042; Wed, 4 May 2022 08:02:40 -0700 (PDT) Received: from hype-n1-sdp.warwick.arm.com (hype-n1-sdp.warwick.arm.com [10.32.32.32]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id D9B4C3F885; Wed, 4 May 2022 08:02:38 -0700 (PDT) From: German Gomez To: linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, acme@kernel.org Cc: German Gomez , Mike Leach , Leo Yan , John Garry , Will Deacon , Mathieu Poirier , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 3/4] perf cs_etm: Record ts_source in AUXTRACE_INFO for ETMv4 and ETE Date: Wed, 4 May 2022 16:02:14 +0100 Message-Id: <20220504150216.581281-4-german.gomez@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220504150216.581281-1-german.gomez@arm.com> References: <20220504150216.581281-1-german.gomez@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Read the value of ts_source exposed by the driver and store it in the ETMv4 and ETE header. If the interface doesn't exist (such as in older Kernels), defaults to a safe value of -1. Signed-off-by: German Gomez --- tools/perf/arch/arm/util/cs-etm.c | 46 +++++++++++++++++++++++++++++++ tools/perf/util/cs-etm.c | 2 ++ tools/perf/util/cs-etm.h | 2 ++ 3 files changed, 50 insertions(+) diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/c= s-etm.c index 4899eb549b4d..f063fece90c3 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -53,6 +53,7 @@ static const char * const metadata_etmv4_ro[] =3D { [CS_ETMV4_TRCIDR2] =3D "trcidr/trcidr2", [CS_ETMV4_TRCIDR8] =3D "trcidr/trcidr8", [CS_ETMV4_TRCAUTHSTATUS] =3D "mgmt/trcauthstatus", + [CS_ETMV4_TS_SOURCE] =3D "ts_source", }; =20 static const char * const metadata_ete_ro[] =3D { @@ -62,6 +63,7 @@ static const char * const metadata_ete_ro[] =3D { [CS_ETE_TRCIDR8] =3D "trcidr/trcidr8", [CS_ETE_TRCAUTHSTATUS] =3D "mgmt/trcauthstatus", [CS_ETE_TRCDEVARCH] =3D "mgmt/trcdevarch", + [CS_ETE_TS_SOURCE] =3D "ts_source", }; =20 static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu); @@ -612,6 +614,32 @@ static int cs_etm_get_ro(struct perf_pmu *pmu, int cpu= , const char *path) return val; } =20 +static int cs_etm_get_ro_signed(struct perf_pmu *pmu, int cpu, const char = *path) +{ + char pmu_path[PATH_MAX]; + int scan; + int val =3D 0; + + /* Get RO metadata from sysfs */ + snprintf(pmu_path, PATH_MAX, "cpu%d/%s", cpu, path); + + scan =3D perf_pmu__scan_file(pmu, pmu_path, "%d", &val); + if (scan !=3D 1) + pr_err("%s: error reading: %s\n", __func__, pmu_path); + + return val; +} + +static bool cs_etm_pmu_path_exists(struct perf_pmu *pmu, int cpu, const ch= ar *path) +{ + char pmu_path[PATH_MAX]; + + /* Get RO metadata from sysfs */ + snprintf(pmu_path, PATH_MAX, "cpu%d/%s", cpu, path); + + return perf_pmu__file_exists(pmu, pmu_path); +} + #define TRCDEVARCH_ARCHPART_SHIFT 0 #define TRCDEVARCH_ARCHPART_MASK GENMASK(11, 0) #define TRCDEVARCH_ARCHPART(x) (((x) & TRCDEVARCH_ARCHPART_MASK) >> TRC= DEVARCH_ARCHPART_SHIFT) @@ -653,6 +681,15 @@ static void cs_etm_save_etmv4_header(__u64 data[], str= uct auxtrace_record *itr, metadata_etmv4_ro[CS_ETMV4_TRCIDR8]); data[CS_ETMV4_TRCAUTHSTATUS] =3D cs_etm_get_ro(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETMV4_TRCAUTHSTATUS]); + + /* Kernels older than 5.19 may not expose ts_source */ + if (cs_etm_pmu_path_exists(cs_etm_pmu, cpu, metadata_etmv4_ro[CS_ETMV4_TS= _SOURCE])) + data[CS_ETMV4_TS_SOURCE] =3D (__u64) cs_etm_get_ro_signed(cs_etm_pmu, cp= u, + metadata_etmv4_ro[CS_ETMV4_TS_SOURCE]); + else { + pr_warning("[%03d] pmu file 'ts_source' not found. Fallback to safe valu= e (-1)\n", cpu); + data[CS_ETMV4_TS_SOURCE] =3D (__u64) -1; + } } =20 static void cs_etm_save_ete_header(__u64 data[], struct auxtrace_record *i= tr, int cpu) @@ -678,6 +715,15 @@ static void cs_etm_save_ete_header(__u64 data[], struc= t auxtrace_record *itr, in /* ETE uses the same registers as ETMv4 plus TRCDEVARCH */ data[CS_ETE_TRCDEVARCH] =3D cs_etm_get_ro(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TRCDEVARCH]); + + /* Kernels older than 5.19 may not expose ts_source */ + if (cs_etm_pmu_path_exists(cs_etm_pmu, cpu, metadata_ete_ro[CS_ETE_TS_SOU= RCE])) + data[CS_ETE_TS_SOURCE] =3D (__u64) cs_etm_get_ro_signed(cs_etm_pmu, cpu, + metadata_ete_ro[CS_ETE_TS_SOURCE]); + else { + pr_warning("[%03d] pmu file 'ts_source' not found. Fallback to safe valu= e (-1)\n", cpu); + data[CS_ETE_TS_SOURCE] =3D (__u64) -1; + } } =20 static void cs_etm_get_metadata(int cpu, u32 *offset, diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 5991a1a46b5c..e883ef6d9c75 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -2537,6 +2537,7 @@ static const char * const cs_etmv4_priv_fmts[] =3D { [CS_ETMV4_TRCIDR2] =3D " TRCIDR2 %llx\n", [CS_ETMV4_TRCIDR8] =3D " TRCIDR8 %llx\n", [CS_ETMV4_TRCAUTHSTATUS] =3D " TRCAUTHSTATUS %llx\n", + [CS_ETMV4_TS_SOURCE] =3D " TS_SOURCE %lld\n", }; =20 static const char * const cs_ete_priv_fmts[] =3D { @@ -2551,6 +2552,7 @@ static const char * const cs_ete_priv_fmts[] =3D { [CS_ETE_TRCIDR8] =3D " TRCIDR8 %llx\n", [CS_ETE_TRCAUTHSTATUS] =3D " TRCAUTHSTATUS %llx\n", [CS_ETE_TRCDEVARCH] =3D " TRCDEVARCH %llx\n", + [CS_ETE_TS_SOURCE] =3D " TS_SOURCE %lld\n", }; =20 static const char * const param_unk_fmt =3D diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h index 817d068de98c..35b783178347 100644 --- a/tools/perf/util/cs-etm.h +++ b/tools/perf/util/cs-etm.h @@ -70,6 +70,7 @@ enum { CS_ETMV4_TRCIDR2, CS_ETMV4_TRCIDR8, CS_ETMV4_TRCAUTHSTATUS, + CS_ETMV4_TS_SOURCE, CS_ETMV4_PRIV_MAX, }; =20 @@ -91,6 +92,7 @@ enum { CS_ETE_TRCIDR8, CS_ETE_TRCAUTHSTATUS, CS_ETE_TRCDEVARCH, + CS_ETE_TS_SOURCE, CS_ETE_PRIV_MAX }; =20 --=20 2.25.1 From nobody Fri May 8 11:29:47 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B9573C433EF for ; Wed, 4 May 2022 15:03:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1351800AbiEDPGn (ORCPT ); Wed, 4 May 2022 11:06:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54646 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351797AbiEDPGX (ORCPT ); Wed, 4 May 2022 11:06:23 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B6E2436320; Wed, 4 May 2022 08:02:45 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8D9E612FC; Wed, 4 May 2022 08:02:45 -0700 (PDT) Received: from hype-n1-sdp.warwick.arm.com (hype-n1-sdp.warwick.arm.com [10.32.32.32]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7A0843F885; Wed, 4 May 2022 08:02:43 -0700 (PDT) From: German Gomez To: linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, acme@kernel.org Cc: German Gomez , Mike Leach , Leo Yan , John Garry , Will Deacon , Mathieu Poirier , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 4/4] perf cs_etm: Set the time field in the synthetic samples Date: Wed, 4 May 2022 16:02:15 +0100 Message-Id: <20220504150216.581281-5-german.gomez@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220504150216.581281-1-german.gomez@arm.com> References: <20220504150216.581281-1-german.gomez@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" If virtual timestamps are detected, set sample time field accordingly, otherwise warn the user that the samples will not include the time data. | Test notes (FEAT_TRF platform) | | $ ./perf record -e cs_etm//u -a -- sleep 4 | $ ./perf script --fields +time | perf 422 [000] 163.375100: 1 branches:uH: = 0 [unknown] ([unknown]) | perf 422 [000] 163.375100: 1 branches:uH: ffffb80= 09544 ioctl+0x14 (/lib/aarch64-linux-gnu/libc-2.27.so) | perf 422 [000] 163.375100: 1 branches:uH: aaaaab6= bebf4 perf_evsel__run_ioctl+0x90 (/home/german/linux/tools/perf/perf) | [...] | perf 422 [000] 167.393100: 1 branches:uH: aaaaab6= bda00 __xyarray__entry+0x74 (/home/german/linux/tools/perf/perf) | perf 422 [000] 167.393099: 1 branches:uH: aaaaab6= bda0c __xyarray__entry+0x80 (/home/german/linux/tools/perf/perf) | perf 422 [000] 167.393099: 1 branches:uH: ffffb80= 09538 ioctl+0x8 (/lib/aarch64-linux-gnu/libc-2.27.so) | | The time from the first sample to the last sample is 4 seconds Signed-off-by: German Gomez --- tools/perf/util/cs-etm.c | 80 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index e883ef6d9c75..ace4ba3256df 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -35,6 +35,7 @@ #include "tool.h" #include "thread.h" #include "thread-stack.h" +#include "tsc.h" #include #include "util/synthetic-events.h" =20 @@ -46,10 +47,12 @@ struct cs_etm_auxtrace { struct perf_session *session; struct machine *machine; struct thread *unknown_thread; + struct perf_tsc_conversion tc; =20 u8 timeless_decoding; u8 snapshot_mode; u8 data_queued; + u8 has_virtual_ts; /* Virtual/Kernel timestamps in the trace. */ =20 int num_cpu; u64 latest_kernel_timestamp; @@ -1161,6 +1164,22 @@ static void cs_etm__copy_insn(struct cs_etm_queue *e= tmq, sample->insn_len, (void *)sample->insn); } =20 +static inline void cs_etm__resolve_sample_time(struct cs_etm_queue *etmq, + struct cs_etm_traceid_queue *tidq, + u64 *time) +{ + struct cs_etm_auxtrace *etm =3D etmq->etm; + struct cs_etm_packet_queue *packet_queue =3D &tidq->packet_queue; + + if (etm->timeless_decoding) + *time =3D 0; + else if (etm->has_virtual_ts) + *time =3D tsc_to_perf_time(packet_queue->cs_timestamp, &etm->tc); + else + *time =3D etm->latest_kernel_timestamp; + +} + static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq, struct cs_etm_traceid_queue *tidq, u64 addr, u64 period) @@ -1174,8 +1193,9 @@ static int cs_etm__synth_instruction_sample(struct cs= _etm_queue *etmq, event->sample.header.misc =3D cs_etm__cpu_mode(etmq, addr); event->sample.header.size =3D sizeof(struct perf_event_header); =20 - if (!etm->timeless_decoding) - sample.time =3D etm->latest_kernel_timestamp; + /* Set time field based con etm auxtrace config. */ + cs_etm__resolve_sample_time(etmq, tidq, &sample.time); + sample.ip =3D addr; sample.pid =3D tidq->pid; sample.tid =3D tidq->tid; @@ -1232,8 +1252,9 @@ static int cs_etm__synth_branch_sample(struct cs_etm_= queue *etmq, event->sample.header.misc =3D cs_etm__cpu_mode(etmq, ip); event->sample.header.size =3D sizeof(struct perf_event_header); =20 - if (!etm->timeless_decoding) - sample.time =3D etm->latest_kernel_timestamp; + /* Set time field based con etm auxtrace config. */ + cs_etm__resolve_sample_time(etmq, tidq, &sample.time); + sample.ip =3D ip; sample.pid =3D tidq->pid; sample.tid =3D tidq->tid; @@ -2899,12 +2920,46 @@ static int cs_etm__queue_aux_records(struct perf_se= ssion *session) return 0; } =20 +/* + * Loop through the ETMs and complain if we find at least one where ts_sou= rce !=3D 1 (virtual + * timestamps). + */ +static bool cs_etm__has_virtual_ts(u64 **metadata, int num_cpu) +{ + int j; + + for (j =3D 0; j < num_cpu; j++) { + +#define HAS_PARAM(j, type, param) (metadata[(j)][CS_ETM_NR_TRC_PARAMS] <= =3D (CS_##type##_##param - CS_ETM_COMMON_BLK_MAX_V1)) + + switch (metadata[j][CS_ETM_MAGIC]) { + case __perf_cs_etmv4_magic: + if (HAS_PARAM(j, ETMV4, TS_SOURCE) || metadata[j][CS_ETMV4_TS_SOURCE] != =3D 1) + return false; + break; + case __perf_cs_ete_magic: + if (HAS_PARAM(j, ETE, TS_SOURCE) || metadata[j][CS_ETE_TS_SOURCE] !=3D = 1) + return false; + break; + default: + /* Unknown / unsupported magic number. */ + return false; + } + +#undef HAS_PARAM + + } + + return true; +} + int cs_etm__process_auxtrace_info(union perf_event *event, struct perf_session *session) { struct perf_record_auxtrace_info *auxtrace_info =3D &event->auxtrace_info; struct cs_etm_auxtrace *etm =3D NULL; struct int_node *inode; + struct perf_record_time_conv *tc =3D &session->time_conv; unsigned int pmu_type; int event_header_size =3D sizeof(struct perf_event_header); int info_header_size; @@ -3071,6 +3126,13 @@ int cs_etm__process_auxtrace_info(union perf_event *= event, etm->auxtrace_type =3D auxtrace_info->type; etm->timeless_decoding =3D cs_etm__is_timeless_decoding(etm); =20 + /* Use virtual timestamps if all ETMs report ts_source =3D 1 */ + etm->has_virtual_ts =3D cs_etm__has_virtual_ts(metadata, num_cpu); + + if (!etm->has_virtual_ts) + ui__warning("Virtual timestamps are not enabled, or not supported by the= traced system.\n\n" + "The time field of the samples will not be set.\n\n"); + etm->auxtrace.process_event =3D cs_etm__process_event; etm->auxtrace.process_auxtrace_event =3D cs_etm__process_auxtrace_event; etm->auxtrace.flush_events =3D cs_etm__flush_events; @@ -3100,6 +3162,16 @@ int cs_etm__process_auxtrace_info(union perf_event *= event, goto err_delete_thread; } =20 + etm->tc.time_shift =3D tc->time_shift; + etm->tc.time_mult =3D tc->time_mult; + etm->tc.time_zero =3D tc->time_zero; + if (event_contains(*tc, time_cycles)) { + etm->tc.time_cycles =3D tc->time_cycles; + etm->tc.time_mask =3D tc->time_mask; + etm->tc.cap_user_time_zero =3D tc->cap_user_time_zero; + etm->tc.cap_user_time_short =3D tc->cap_user_time_short; + } + if (dump_trace) { cs_etm__print_auxtrace_info(auxtrace_info->priv, num_cpu); } --=20 2.25.1