On 16/10/2026 17:55, Leo Yan wrote:
trbe_get_trace_size() assumes that the TRBE write pointer is always ahead of the perf AUX head. That is not true after a WRAP event, where the write pointer can move back to the start of the programmed TRBE span.
Calculate the size in two parts for WRAP: the bytes from the current AUX head to TRBLIMITR_EL1, plus any bytes from TRBBASER_EL1 to the current TRBPTR_EL1. Keep the non-WRAP path strict and reject an unexpected write pointer below the AUX head.
For CPUs affected by the overwrite-fill-mode or write-out-of-range errata, continue to ignore TRBPTR_EL1 on WRAP and account data only up to TRBLIMITR_EL1, since bytes beyond the programmed limit are uncertain.
Apply this fallback before validating the write pointer so a WRAP report with a pointer outside the programmed range still publishes the trace from the AUX head to the programmed limit.
Signed-off-by: Leo Yan leo.yan@arm.com
drivers/hwtracing/coresight/coresight-trbe.c | 62 +++++++++++++++++----------- 1 file changed, 37 insertions(+), 25 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c index 661f4a78e67c30652de8c834e4773819fa67b5ac..9a469c8009ce8a8a8b804c2b63a68e741f1dceaa 100644 --- a/drivers/hwtracing/coresight/coresight-trbe.c +++ b/drivers/hwtracing/coresight/coresight-trbe.c @@ -730,43 +730,55 @@ static enum trbe_fault_action trbe_get_fault_act(struct perf_output_handle *hand static unsigned long trbe_get_trace_size(struct perf_output_handle *handle, struct trbe_buf *buf, bool wrap) {
- u64 write;
- u64 start_off, end_off;
- u64 size; u64 overwrite_skip = TRBE_WORKAROUND_OVERWRITE_FILL_MODE_SKIP_BYTES;
- u64 base = buf->trbe_base;
- u64 start_off = PERF_IDX2OFF(handle->head, buf);
- u64 write = get_trbe_write_pointer();
- u64 limit = get_trbe_limit_pointer();
- u64 limit_off, write_off, size;
/*
* If the TRBE has wrapped around the write pointer has* wrapped and should be treated as limit.*
- When the TRBE is affected by TRBE_WORKAROUND_WRITE_OUT_OF_RANGE,
* it may write upto 64bytes beyond the "LIMIT". The driver already
* it may write up to 64bytes beyond the "LIMIT". The driver already
- keeps a valid page next to the LIMIT and we could potentially
- consume the trace data that may have been collected there. But we
- cannot be really sure it is available, and the TRBPTR may not
* indicate the same. Also, affected cores are also affected by another* erratum which forces the PAGE_SIZE alignment on the TRBPTR, and thus* could potentially pad an entire PAGE_SIZE - 64bytes, to get those* 64bytes. Thus we ignore the potential triggering of the erratum* on WRAP and limit the data to LIMIT.
* indicate the same.** Also, affected cores are also affected by another erratum* TRBE_WORKAROUND_OVERWRITE_FILL_MODE, which forces the PAGE_SIZE* alignment on the TRBPTR, and thus could potentially pad an entire* PAGE_SIZE - 64bytes, to get those 64bytes. Thus we ignore the* potential effects of the erratum on WRAP and limit the data to */* LIMIT.
- if (wrap)
write = get_trbe_limit_pointer();- else
write = get_trbe_write_pointer();
- if (wrap &&
(trbe_may_overwrite_in_fill_mode(buf->cpudata) ||trbe_may_write_out_of_range(buf->cpudata)))write = limit;
- /*
* TRBE may use a different base address than the base* of the ring buffer. Thus use the beginning of the ring* buffer to compute the offsets.*/- end_off = write - buf->trbe_base;
- start_off = PERF_IDX2OFF(handle->head, buf);
- /* Should never happen ... */
- if (WARN_ON_ONCE(write < base || write > limit))
return 0;
- if (WARN_ON_ONCE(end_off < start_off))
- limit_off = limit - base;
- write_off = write - base;
- if (WARN_ON_ONCE(start_off >= limit_off)) return 0;
- size = end_off - start_off;
- if (!wrap) {
if (WARN_ON_ONCE(write_off < start_off))return 0;size = write_off - start_off;- } else {
size = limit_off - start_off;if (write != limit)size += write_off;- }
- /*
- If the TRBE is affected by the following erratum, we must fill
- the space we skipped with IGNORE packets. And we are always
Reviewed-by: James Clark james.clark@linaro.org