From: Leo Yan leo.yan@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@arm.com Signed-off-by: James Clark james.clark@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;