[PATCH 3/6] perf cs-etm: Synthesize missing HW_ID mappings for raw trace

James Clark james.clark at linaro.org
Fri Aug 21 02:50:31 PDT 2026


From: Leo Yan <leo.yan at arm.com>

The CoreSight driver emits PERF_RECORD_AUX_OUTPUT_HW_ID via
perf_report_aux_output_id(). If the perf ring buffer is full,
perf_report_aux_output_id() can fail to emit the record and return
silently.

When at least one HW_ID record is present in the file, perf skips the
legacy metadata-only trace ID mapping path. Therefore any raw AUX queue
whose HW_ID record was dropped can be left with an empty traceid_list,
and cs_etm__create_queue_decoders() will not create a decoder for that
queue.

Backfill missing mappings for non-empty UNFORMATTED queues whose trace
ID map is still empty after the HW_ID record scan. Real HW_ID mappings
remain preferred and are not overwritten in case someone is trying to
link what the kernel outputs to the raw trace dump.

Signed-off-by: Leo Yan <leo.yan at arm.com>
Signed-off-by: James Clark <james.clark at linaro.org>
---
 tools/perf/util/cs-etm.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 44e20067da1f..dd15e91b7b38 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -427,6 +427,39 @@ static int cs_etm__process_trace_id_v0_1(struct cs_etm_auxtrace *etm, int cpu,
 	return 0;
 }
 
+static int cs_etm__synth_unformatted_trace_ids(struct cs_etm_auxtrace *etm)
+{
+	struct auxtrace_queues *queues = &etm->queues;
+
+	for (unsigned int i = 0; i < queues->nr_queues; i++) {
+		struct auxtrace_queue *queue = &queues->queue_array[i];
+		struct cs_etm_queue *etmq = queue->priv;
+		u64 *cpu_data;
+		u8 trace_id;
+		int ret;
+
+		if (list_empty(&queue->head) || !etmq || etmq->format != UNFORMATTED)
+			continue;
+
+		if (!intlist__empty(etmq->traceid_list))
+			continue;
+
+		cpu_data = get_cpu_data(etm, queue->cpu);
+		if (!cpu_data)
+			return -EINVAL;
+
+		ret = cs_etm__metadata_get_trace_id(&trace_id, cpu_data);
+		if (ret)
+			return ret;
+
+		ret = cs_etm__insert_trace_id_node(etmq, trace_id, cpu_data);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int cs_etm__metadata_get_trace_id(u8 *trace_chan_id, u64 *cpu_metadata)
 {
 	u64 cs_etm_magic = cpu_metadata[CS_ETM_MAGIC];
@@ -3801,6 +3834,16 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event,
 			goto err_free_queues;
 	}
 
+	/*
+	 * Add fake IDs for any unformatted queues missing them. The IDs
+	 * themselves are only cosmetic in unformatted mode (raw dump output),
+	 * but a decoder won't be created if one was dropped and Perf can be
+	 * resilient to this.
+	 */
+	err = cs_etm__synth_unformatted_trace_ids(etm);
+	if (err)
+		goto err_free_queues;
+
 	err = cs_etm__create_decoders(etm);
 	if (err)
 		goto err_free_queues;

-- 
2.43.0




More information about the linux-arm-kernel mailing list