From nobody Fri Dec 19 04:02:24 2025 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 86E2A81745; Mon, 29 Apr 2024 15:24:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714404267; cv=none; b=cI73dGlYrC8Ji4TY8vyjmgDzv3v//B0qkqGrpIiYvt0TN8mE9fbRkkOeB1jE7PrMzYdmdW8uoWb8GSL23WkADUvbnCDwks9izY6F8glsCxDVcRBWCQRdPRLyMpZPdNbqZdtUWzUYv5nNRBvi3rEKSWk1JeKCd5H43OhcfjEYJfU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714404267; c=relaxed/simple; bh=B4nm6nLK51aoQsLttd3Ekb+C8feSvY1WbvdomQFg9hE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ERZFARzwV9BMSFPOGdGyRKrxjn/SD+DYpbCxbC7Lw9TxXGDgiA7bsgiuqgApLmTUj+CypyHfpfnaRX6wvR48fqjE5q8/6RXd8UVnew7in7CN3OWCWOSIONmszyIGBukSDSFjYbbNwZzKctyfRSaP9TL2+HqPpAs0YkkUEkNMzq4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com 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 A00892F4; Mon, 29 Apr 2024 08:24:51 -0700 (PDT) Received: from e127643.broadband (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7D47C3F86F; Mon, 29 Apr 2024 08:24:21 -0700 (PDT) From: James Clark To: linux-perf-users@vger.kernel.org, gankulkarni@os.amperecomputing.com, scclevenger@os.amperecomputing.com, coresight@lists.linaro.org, suzuki.poulose@arm.com, mike.leach@linaro.org Cc: James Clark , Alexander Shishkin , Maxime Coquelin , Alexandre Torgue , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Jiri Olsa , Ian Rogers , Adrian Hunter , John Garry , Will Deacon , Leo Yan , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com Subject: [PATCH 06/17] perf: cs-etm: Create decoders based on the trace ID mappings Date: Mon, 29 Apr 2024 16:21:51 +0100 Message-Id: <20240429152207.479221-7-james.clark@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240429152207.479221-1-james.clark@arm.com> References: <20240429152207.479221-1-james.clark@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that each queue has a unique set of trace ID mappings, use this list to create the decoders. This also works the same way for unformatted where a single dummy entry is added into the trace ID list. Previously each queue would have a decoder created for each traced CPU on the system but this won't work anymore because CPUs can have overlapping trace IDs. Signed-off-by: James Clark --- tools/perf/util/cs-etm.c | 143 +++++++++++++++++++++++---------------- 1 file changed, 85 insertions(+), 58 deletions(-) diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index be858aed26c4..73fc0ab2fb09 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -268,6 +268,10 @@ static int cs_etm__map_trace_id_v0(struct cs_etm_auxtr= ace *etm, u8 trace_chan_id int ret; struct cs_etm_queue *etmq =3D etm->queues.queue_array[i].priv; =20 + /* Ignore HW_IDs on unformatted queues */ + if (etmq->formatted_set && !etmq->formatted) + continue; + ret =3D cs_etm__insert_trace_id_node(etmq, trace_chan_id, cpu_metadata); if (ret) @@ -673,80 +677,58 @@ static void cs_etm__packet_dump(const char *pkt_strin= g) } =20 static void cs_etm__set_trace_param_etmv3(struct cs_etm_trace_params *t_pa= rams, - struct cs_etm_auxtrace *etm, int t_idx, - int m_idx, u32 etmidr) + u64 *metadata, u32 etmidr) { - u64 **metadata =3D etm->metadata; - - t_params[t_idx].protocol =3D cs_etm__get_v7_protocol_version(etmidr); - t_params[t_idx].etmv3.reg_ctrl =3D metadata[m_idx][CS_ETM_ETMCR]; - t_params[t_idx].etmv3.reg_trc_id =3D metadata[m_idx][CS_ETM_ETMTRACEIDR]; + t_params->protocol =3D cs_etm__get_v7_protocol_version(etmidr); + t_params->etmv3.reg_ctrl =3D metadata[CS_ETM_ETMCR]; + t_params->etmv3.reg_trc_id =3D metadata[CS_ETM_ETMTRACEIDR]; } =20 static void cs_etm__set_trace_param_etmv4(struct cs_etm_trace_params *t_pa= rams, - struct cs_etm_auxtrace *etm, int t_idx, - int m_idx) + u64 *metadata) { - u64 **metadata =3D etm->metadata; - - t_params[t_idx].protocol =3D CS_ETM_PROTO_ETMV4i; - t_params[t_idx].etmv4.reg_idr0 =3D metadata[m_idx][CS_ETMV4_TRCIDR0]; - t_params[t_idx].etmv4.reg_idr1 =3D metadata[m_idx][CS_ETMV4_TRCIDR1]; - t_params[t_idx].etmv4.reg_idr2 =3D metadata[m_idx][CS_ETMV4_TRCIDR2]; - t_params[t_idx].etmv4.reg_idr8 =3D metadata[m_idx][CS_ETMV4_TRCIDR8]; - t_params[t_idx].etmv4.reg_configr =3D metadata[m_idx][CS_ETMV4_TRCCONFIGR= ]; - t_params[t_idx].etmv4.reg_traceidr =3D metadata[m_idx][CS_ETMV4_TRCTRACEI= DR]; + t_params->protocol =3D CS_ETM_PROTO_ETMV4i; + t_params->etmv4.reg_idr0 =3D metadata[CS_ETMV4_TRCIDR0]; + t_params->etmv4.reg_idr1 =3D metadata[CS_ETMV4_TRCIDR1]; + t_params->etmv4.reg_idr2 =3D metadata[CS_ETMV4_TRCIDR2]; + t_params->etmv4.reg_idr8 =3D metadata[CS_ETMV4_TRCIDR8]; + t_params->etmv4.reg_configr =3D metadata[CS_ETMV4_TRCCONFIGR]; + t_params->etmv4.reg_traceidr =3D metadata[CS_ETMV4_TRCTRACEIDR]; } =20 static void cs_etm__set_trace_param_ete(struct cs_etm_trace_params *t_para= ms, - struct cs_etm_auxtrace *etm, int t_idx, - int m_idx) + u64 *metadata) { - u64 **metadata =3D etm->metadata; - - t_params[t_idx].protocol =3D CS_ETM_PROTO_ETE; - t_params[t_idx].ete.reg_idr0 =3D metadata[m_idx][CS_ETE_TRCIDR0]; - t_params[t_idx].ete.reg_idr1 =3D metadata[m_idx][CS_ETE_TRCIDR1]; - t_params[t_idx].ete.reg_idr2 =3D metadata[m_idx][CS_ETE_TRCIDR2]; - t_params[t_idx].ete.reg_idr8 =3D metadata[m_idx][CS_ETE_TRCIDR8]; - t_params[t_idx].ete.reg_configr =3D metadata[m_idx][CS_ETE_TRCCONFIGR]; - t_params[t_idx].ete.reg_traceidr =3D metadata[m_idx][CS_ETE_TRCTRACEIDR]; - t_params[t_idx].ete.reg_devarch =3D metadata[m_idx][CS_ETE_TRCDEVARCH]; + t_params->protocol =3D CS_ETM_PROTO_ETE; + t_params->ete.reg_idr0 =3D metadata[CS_ETE_TRCIDR0]; + t_params->ete.reg_idr1 =3D metadata[CS_ETE_TRCIDR1]; + t_params->ete.reg_idr2 =3D metadata[CS_ETE_TRCIDR2]; + t_params->ete.reg_idr8 =3D metadata[CS_ETE_TRCIDR8]; + t_params->ete.reg_configr =3D metadata[CS_ETE_TRCCONFIGR]; + t_params->ete.reg_traceidr =3D metadata[CS_ETE_TRCTRACEIDR]; + t_params->ete.reg_devarch =3D metadata[CS_ETE_TRCDEVARCH]; } =20 static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params, - struct cs_etm_auxtrace *etm, - bool formatted, - int sample_cpu, - int decoders) -{ - int t_idx, m_idx; - u32 etmidr; - u64 architecture; - - for (t_idx =3D 0; t_idx < decoders; t_idx++) { - if (formatted) - m_idx =3D t_idx; - else { - m_idx =3D get_cpu_data_idx(etm, sample_cpu); - if (m_idx =3D=3D -1) { - pr_warning("CS_ETM: unknown CPU, falling back to first metadata\n"); - m_idx =3D 0; - } - } + struct cs_etm_queue *etmq) +{ + struct int_node *inode; =20 - architecture =3D etm->metadata[m_idx][CS_ETM_MAGIC]; + intlist__for_each_entry(inode, etmq->traceid_list) { + u64 *metadata =3D inode->priv; + u64 architecture =3D metadata[CS_ETM_MAGIC]; + u32 etmidr; =20 switch (architecture) { case __perf_cs_etmv3_magic: - etmidr =3D etm->metadata[m_idx][CS_ETM_ETMIDR]; - cs_etm__set_trace_param_etmv3(t_params, etm, t_idx, m_idx, etmidr); + etmidr =3D metadata[CS_ETM_ETMIDR]; + cs_etm__set_trace_param_etmv3(t_params++, metadata, etmidr); break; case __perf_cs_etmv4_magic: - cs_etm__set_trace_param_etmv4(t_params, etm, t_idx, m_idx); + cs_etm__set_trace_param_etmv4(t_params++, metadata); break; case __perf_cs_ete_magic: - cs_etm__set_trace_param_ete(t_params, etm, t_idx, m_idx); + cs_etm__set_trace_param_ete(t_params++, metadata); break; default: return -EINVAL; @@ -2918,6 +2900,42 @@ static u64 *cs_etm__create_meta_blk(u64 *buff_in, in= t *buff_in_offset, return metadata; } =20 +/* + * traceid_list is used to create decoders and give them the trace ID + * mappings. In unformatted mode just insert one entry for the sample + * CPU so the decoder knows which settings to use. + */ +static int cs_etm__map_trace_ids_unformatted(struct cs_etm_auxtrace *etm) +{ + for (unsigned int i =3D 0; i < etm->queues.nr_queues; ++i) { + int ret; + struct cs_etm_queue *etmq; + u8 trace_chan_id; + u64 *cpu_data; + + etmq =3D etm->queues.queue_array[i].priv; + if (!etmq->formatted_set || etmq->formatted) + continue; + + /* Giving it a real ID doesn't do much but can help with debugging */ + trace_chan_id =3D CORESIGHT_LEGACY_CPU_TRACE_ID(i); + cpu_data =3D get_cpu_data(etm, i); + if (cpu_data =3D=3D NULL) { + pr_warning("CS_ETM: unknown CPU, falling back to first metadata\n"); + cpu_data =3D etm->metadata[0]; + } + + ret =3D cs_etm__insert_trace_id_node(etmq, trace_chan_id, cpu_data); + if (ret) + return ret; + + ret =3D cs_etm__metadata_set_trace_id(trace_chan_id, cpu_data); + if (ret) + return ret; + } + return 0; +} + /** * Puts a fragment of an auxtrace buffer into the auxtrace queues based * on the bounds of aux_event, if it matches with the buffer that's at @@ -3220,21 +3238,26 @@ static int cs_etm__clear_unused_trace_ids_metadata(= int num_cpu, u64 **metadata) static int cs_etm__create_queue_decoders(struct cs_etm_queue *etmq) { struct cs_etm_decoder_params d_params; + struct cs_etm_trace_params *t_params; + int decoders =3D intlist__nr_entries(etmq->traceid_list); =20 /* * Each queue can only contain data from one CPU when unformatted, so onl= y one decoder is * needed. */ - int decoders =3D etmq->formatted ? etmq->etm->num_cpu : 1; + if (etmq->formatted_set && !etmq->formatted) + assert(decoders =3D=3D 1); + + if (decoders =3D=3D 0) + return 0; =20 /* Use metadata to fill in trace parameters for trace decoder */ - struct cs_etm_trace_params *t_params =3D zalloc(sizeof(*t_params) * deco= ders); + t_params =3D zalloc(sizeof(*t_params) * decoders); =20 if (!t_params) goto out_free; =20 - if (cs_etm__init_trace_params(t_params, etmq->etm, etmq->formatted, - etmq->queue_nr, decoders)) + if (cs_etm__init_trace_params(t_params, etmq)) goto out_free; =20 /* Set decoder parameters to decode trace packets */ @@ -3497,6 +3520,10 @@ int cs_etm__process_auxtrace_info_full(union perf_ev= ent *event, if (err) goto err_free_queues; =20 + err =3D cs_etm__map_trace_ids_unformatted(etm); + if (err) + goto err_free_queues; + err =3D cs_etm__create_decoders(etm); if (err) goto err_free_queues; --=20 2.34.1