Thread (13 messages) 13 messages, 1 author, 4d ago
DORMANTno replies

[PATCH RFC 12/12] rvtrace: Reset RAM sink write pointer on every context switch

From: Eric Lin <hidden>
Date: 2026-06-30 09:47:45
Also in: linux-riscv, lkml
Subsystem: hardware tracing facilities, the rest · Maintainers: Alexander Shishkin, Linus Torvalds

Currently, rvtrace_ramsink_copyto_auxbuf() only resets the RAM sink
Write Pointer (WP) when a buffer wrap occurs. If no wrap occurs, the
WP is not reset and is left at its advanced position.

This creates a highly non-deterministic tracing environment. For example,
consider a scenario where a user traces a program: On the first run, the
trace data fits within the buffer (no wrap) and the output is perfectly
captured. However, the WP is now left near the end of the RAM sink. If
the user runs the exact same program a second time, the hardware resumes
writing from this advanced WP. The buffer quickly wraps around,
prematurely overwriting the new trace data and resulting in unexpected,
incomplete output.

Fix this by unconditionally resetting the WP to the base address of the
RAM sink at the end of every data copy. This guarantees that every time
a trace session starts or a task is scheduled in, it has the full
capacity of the RAM sink available.

Consequently, tracking `prev_wp` is no longer necessary for calculating
offsets in the non-wrap case, so the data copy logic has been simplified
to always read from the start of the buffer.

Co-developed-by: Nick Hu <redacted>
Signed-off-by: Nick Hu <redacted>
Co-developed-by: Vincent Chen <redacted>
Signed-off-by: Vincent Chen <redacted>
Signed-off-by: Eric Lin <redacted>
---
 drivers/hwtracing/rvtrace/rvtrace-ramsink.c | 25 +++++++++++--------------
 1 file changed, 11 insertions(+), 14 deletions(-)
diff --git a/drivers/hwtracing/rvtrace/rvtrace-ramsink.c b/drivers/hwtracing/rvtrace/rvtrace-ramsink.c
index d89cdcb971dd..8e9cbaa70f16 100644
--- a/drivers/hwtracing/rvtrace/rvtrace-ramsink.c
+++ b/drivers/hwtracing/rvtrace/rvtrace-ramsink.c
@@ -59,7 +59,6 @@ struct rvtrace_ramsink_regs {
  * @stop_on_wrap: Whether to stop tracing when buffer wraps
  * @mem_acc_width: Memory access width in bytes
  * @regs:         Pointer to register offset definitions
- * @prev_wp:      Previous write pointer position (for incremental copies)
  */
 struct rvtrace_ramsink_priv {
 	size_t size;
@@ -70,7 +69,6 @@ struct rvtrace_ramsink_priv {
 	bool stop_on_wrap;
 	int mem_acc_width;
 	const struct rvtrace_ramsink_regs *regs;
-	u64 prev_wp;
 };
 
 /**
@@ -202,25 +200,25 @@ size_t rvtrace_ramsink_copyto_auxbuf(struct rvtrace_component *comp,
 	wrap = wp & RVTRACE_RAMSINK_WPLOW_WRAP;
 	wp &= ~RVTRACE_RAMSINK_WPLOW_WRAP;
 	if (wrap) {
-		rvtrace_write32(comp->pdata, lower_32_bits(priv->start),
-				regs->wp_low);
-		rvtrace_write32(comp->pdata, upper_32_bits(priv->start),
-				regs->wp_high);
 		src.cur = wp - priv->start;
-		priv->prev_wp = priv->start;
 		/*
-		 * There is no way to tell if trRamWp wrapped around more than once. As a
-		 * result priv->prev_wp can't be used and the entire buffer must be copied
-		 * even though some data might be duplicated.
+		 * There is no way to tell if trRamWp wrapped around more than once.
+		 * The entire buffer must be copied even though some data might be duplicated.
 		 */
 		bytes = priv->size;
 	} else {
-		src.cur =  priv->prev_wp - priv->start;
-		bytes = wp - priv->prev_wp;
-		priv->prev_wp = wp;
+		src.cur = 0;
+		bytes = wp - priv->start;
 	}
 
 	tbuf_to_pbuf_copy(&src, &dst, bytes);
+
+	/* Reset WP after trace data copy to perf AUX buf */
+	rvtrace_write32(comp->pdata, lower_32_bits(priv->start),
+			regs->wp_low);
+	rvtrace_write32(comp->pdata, upper_32_bits(priv->start),
+			regs->wp_high);
+
 	dev_dbg(&comp->dev, "Copied %zu bytes\n", bytes);
 	return bytes;
 }
@@ -258,7 +256,6 @@ static int rvtrace_ramsink_setup_buf(struct rvtrace_component *comp,
 		return -ENOMEM;
 
 	priv->end = priv->start + priv->size;
-	priv->prev_wp = priv->start;
 	if (priv->end <= start_min || priv->start >= limit_max) {
 		dma_free_coherent(pdev, priv->size, priv->va, priv->start);
 		dev_err(&comp->dev, "DMA memory not addressable by device\n");
-- 
2.34.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help