Indexed AUX fragments do not necessarily form a contiguous trace stream. Snapshot reads can retain only the end of the AUX buffer and advance past the omitted prefix. AUX metadata records can also be lost when the normal perf ring buffer is full, leaving the corresponding trace unqueued. Neither case guarantees that the next queued fragment carries a collision flag or retains the source's restart synchronization packets.
Track the expected next logical AUX offset for each decoder queue in cs_etm__get_trace(). Request a decoder reset before processing a fragment whose offset differs from the expected end. This prevents decoding bytes after a gap using stale packet and execution state. The comparison also covers overlapping fragments and backward offsets.
Perf can internally split large buffers into consecutive pieces while retaining the original AUX offset. Preserve continuity across those pieces and accumulate their sizes when tracking the expected end. Keep the decoder byte index separate from the logical AUX offset. Track initialization separately, as zero is a valid expected offset after the counter wraps.
Zero-length fragments still carry logical offsets. Check them for gaps and retain any reset request until nonempty data is decoded.
Signed-off-by: Leo Yan leo.yan@arm.com --- tools/perf/util/cs-etm.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 8f04d7ceddd9d1f7ff22af234b19400efe27ba2b..37ae7ff5149433ed27cb3c9b880e8422d742a74d 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -123,6 +123,9 @@ struct cs_etm_queue { u8 pending_timestamp_chan_id; enum cs_etm_format format; u64 offset; + /* Expected logical AUX offset after the last fetched buffer. */ + u64 next_aux_offset; + bool have_aux_offset; const unsigned char *buf; size_t buf_len, buf_used; /* Conversion between traceID and index in traceid_queues array */ @@ -1496,6 +1499,21 @@ cs_etm__get_trace(struct cs_etm_queue *etmq) old_buffer->cpu.cpu != aux_buffer->cpu.cpu)) etmq->reset_decoder = true;
+ /* + * Snapshot clipping or missing AUX records can leave a gap between + * fragments. Check logical AUX offsets, as etmq->offset only counts + * bytes submitted to the decoder. Internally split buffers retain + * the original offset and mark subsequent pieces as consecutive. + */ + if (etmq->have_aux_offset && !aux_buffer->consecutive && + aux_buffer->offset != etmq->next_aux_offset) + etmq->reset_decoder = true; + + if (!etmq->have_aux_offset || !aux_buffer->consecutive) + etmq->next_aux_offset = aux_buffer->offset; + etmq->next_aux_offset += aux_buffer->size; + etmq->have_aux_offset = true; + return 0; }