linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Suzuki K Poulose <suzuki.poulose@arm.com>
To: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org, coresight@lists.linaro.org,
	anshuman.khandual@arm.com, will@kernel.org,
	catalin.marinas@arm.com, james.morse@arm.com,
	mathieu.poirier@linaro.org, mike.leach@linaro.org,
	leo.yan@linaro.org, maz@kernel.org, mark.rutland@arm.com,
	Suzuki K Poulose <suzuki.poulose@arm.com>
Subject: [PATCH 08/10] coresight: trbe: Workaround TRBE errat overwrite in FILL mode
Date: Wed, 28 Jul 2021 14:52:15 +0100	[thread overview]
Message-ID: <20210728135217.591173-9-suzuki.poulose@arm.com> (raw)
In-Reply-To: <20210728135217.591173-1-suzuki.poulose@arm.com>

ARM Neoverse-N2 (#2139208) and Cortex-A710(##2119858) suffers from
an erratum, which when triggered, might cause the TRBE to overwrite
the trace data already collected in FILL mode, in the event of a WRAP.
i.e, the TRBE doesn't stop writing the data, instead wraps to the base
and could write upto 3 cache line size worth trace. Thus, this could
corrupt the trace at the "BASE" pointer.

The workaround is to program the write pointer 256bytes from the
base, such that if the erratum is triggered, it doesn't overwrite
the trace data that was captured. This skipped region could be
padded with ignore packets at the end of the session, so that
the decoder sees a continuous buffer with some padding at the
beginning. The trace data written at the base is considered
lost as the limit could have been in the middle of the perf
ring buffer, and jumping to the "base" is not acceptable.
We set the flags already to indicate that some amount of trace
was lost during the FILL event IRQ. So this is fine.

One important change with the work around is, we program the
TRBBASER_EL1 to current page where we are allowed to write.
Otherwise, it could overwrite a region that may be consumed
by the perf. Towards this, we always make sure that the
"handle->head" and thus the trbe_write is PAGE_SIZE aligned,
so that we can set the BASE to the PAGE base and move the
TRBPTR to the 256bytes offset.

Cc: Mike Leach <mike.leach@linaro.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Anshuman Khandual <anshuman.khandual@arm.com>
Cc: Leo Yan <leo.yan@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
 drivers/hwtracing/coresight/coresight-trbe.c | 111 +++++++++++++++++--
 1 file changed, 102 insertions(+), 9 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c
index 9ea28813182b..cd997ed5d918 100644
--- a/drivers/hwtracing/coresight/coresight-trbe.c
+++ b/drivers/hwtracing/coresight/coresight-trbe.c
@@ -17,6 +17,7 @@
 
 #include <asm/barrier.h>
 #include <asm/cputype.h>
+#include <asm/cpufeature.h>
 
 #include "coresight-self-hosted-trace.h"
 #include "coresight-trbe.h"
@@ -84,9 +85,17 @@ struct trbe_buf {
  * per TRBE instance, we keep track of the list of errata that
  * affects the given instance of the TRBE.
  */
-#define TRBE_ERRATA_MAX			0
+#define TRBE_WORKAROUND_OVERWRITE_FILL_MODE	0
+#define TRBE_ERRATA_MAX				1
+
+/*
+ * Safe limit for the number of bytes that may be overwritten
+ * when the erratum is triggered.
+ */
+#define TRBE_WORKAROUND_OVERWRITE_FILL_MODE_SKIP	256
 
 static unsigned long trbe_errata_cpucaps[TRBE_ERRATA_MAX] = {
+	[TRBE_WORKAROUND_OVERWRITE_FILL_MODE] = ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE,
 };
 
 /*
@@ -531,10 +540,13 @@ static enum trbe_fault_action trbe_get_fault_act(u64 trbsr)
 	if ((ec == TRBE_EC_STAGE1_ABORT) || (ec == TRBE_EC_STAGE2_ABORT))
 		return TRBE_FAULT_ACT_FATAL;
 
-	if (is_trbe_wrap(trbsr) && (ec == TRBE_EC_OTHERS) && (bsc == TRBE_BSC_FILLED)) {
-		if (get_trbe_write_pointer() == get_trbe_base_pointer())
-			return TRBE_FAULT_ACT_WRAP;
-	}
+	/*
+	 * It is not necessary to verify the TRBPTR == TRBBASER to detect
+	 * a FILL event. Moreover, CPU errata could make this check invalid.
+	 */
+	if (is_trbe_wrap(trbsr) && (ec == TRBE_EC_OTHERS) && (bsc == TRBE_BSC_FILLED))
+		return TRBE_FAULT_ACT_WRAP;
+
 	return TRBE_FAULT_ACT_SPURIOUS;
 }
 
@@ -544,6 +556,7 @@ static unsigned long trbe_get_trace_size(struct perf_output_handle *handle,
 {
 	u64 write;
 	u64 start_off, end_off;
+	u64 size;
 
 	/*
 	 * If the TRBE has wrapped around the write pointer has
@@ -559,7 +572,18 @@ static unsigned long trbe_get_trace_size(struct perf_output_handle *handle,
 
 	if (WARN_ON_ONCE(end_off < start_off))
 		return 0;
-	return (end_off - start_off);
+
+	size = end_off - start_off;
+	/*
+	 * If the TRBE is affected by the following erratum, we must fill
+	 * the space we skipped with IGNORE packets. And we are always
+	 * guaranteed to have at least a PAGE_SIZE space in the buffer.
+	 */
+	if (trbe_has_erratum(TRBE_WORKAROUND_OVERWRITE_FILL_MODE, buf->cpudata) &&
+	    !WARN_ON(size < TRBE_WORKAROUND_OVERWRITE_FILL_MODE_SKIP))
+		__trbe_pad_buf(buf, start_off, TRBE_WORKAROUND_OVERWRITE_FILL_MODE_SKIP);
+
+	return size;
 }
 
 static void *arm_trbe_alloc_buffer(struct coresight_device *csdev,
@@ -704,20 +728,73 @@ static unsigned long arm_trbe_update_buffer(struct coresight_device *csdev,
 	return size;
 }
 
+
+static int trbe_apply_work_around_before_enable(struct trbe_buf *buf)
+{
+	/*
+	 * TRBE_WORKAROUND_OVERWRITE_FILL_MODE causes the TRBE to overwrite a few cache
+	 * line size from the "TRBBASER_EL1" in the event of a "FILL".
+	 * Thus, we could loose some amount of the trace at the base.
+	 *
+	 * To work around this:
+	 * - Software must leave 256bytes of space from the base, so that
+	 *   the trace collected now is not overwritten.
+	 * - Fill the first 256bytes with IGNORE packets for the decoder
+	 *   to ignore at the end of the session, so that the decoder ignores
+	 *   this gap.
+	 *
+	 * This also means that, the TRBE driver must set the TRBBASER_EL1
+	 * such that, when the erratum is triggered, it doesn't overwrite
+	 * the "area" outside the area marked by (handle->head, +size).
+	 * So, we make sure that the handle->head is always PAGE aligned,
+	 * by tweaking the required alignment for the TRBE (trbe_align).
+	 * And when we enable the TRBE,
+	 *
+	 *   - move the TRBPTR_EL1 to 256bytes past the starting point.
+	 *     So that any trace collected in this run is not overwritten.
+	 *
+	 *   - set the TRBBASER_EL1 to the original trbe_write. This will
+	 *     ensure that, if the TRBE hits the erratum, it would only
+	 *     write within the region allowed for the TRBE.
+	 *
+	 * At the trace collection time, we always pad the skipped bytes
+	 * with IGNORE packets to make sure the decoder doesn't see any
+	 * overwritten packets.
+	 */
+	if (trbe_has_erratum(TRBE_WORKAROUND_OVERWRITE_FILL_MODE, buf->cpudata)) {
+		if (WARN_ON(!IS_ALIGNED(buf->trbe_write, PAGE_SIZE)))
+			return -EINVAL;
+		buf->trbe_hw_base = buf->trbe_write;
+		buf->trbe_write += TRBE_WORKAROUND_OVERWRITE_FILL_MODE_SKIP;
+	}
+
+	return 0;
+}
+
 static int __arm_trbe_enable(struct trbe_buf *buf,
 			     struct perf_output_handle *handle)
 {
+	int ret = 0;
+
 	buf->trbe_limit = compute_trbe_buffer_limit(handle);
 	buf->trbe_write = buf->trbe_base + PERF_IDX2OFF(handle->head, buf);
 	if (buf->trbe_limit == buf->trbe_base) {
-		trbe_stop_and_truncate_event(handle);
-		return -ENOSPC;
+		ret = -ENOSPC;
+		goto err;
 	}
 	/* Set the base of the TRBE to the buffer base */
 	buf->trbe_hw_base = buf->trbe_base;
+
+	ret = trbe_apply_work_around_before_enable(buf);
+	if (ret)
+		goto err;
+
 	*this_cpu_ptr(buf->cpudata->drvdata->handle) = handle;
 	trbe_enable_hw(buf);
 	return 0;
+err:
+	trbe_stop_and_truncate_event(handle);
+	return ret;
 }
 
 static int arm_trbe_enable(struct coresight_device *csdev, u32 mode, void *data)
@@ -1003,7 +1080,23 @@ static void arm_trbe_probe_cpu(void *info)
 		pr_err("Unsupported alignment on cpu %d\n", cpu);
 		goto cpu_clear;
 	}
-	cpudata->trbe_align = cpudata->trbe_hw_align;
+
+	/*
+	 * If the TRBE is affected by erratum TRBE_WORKAROUND_OVERWRITE_FILL_MODE,
+	 * we must always program the TBRPTR_EL1, 256bytes from a page
+	 * boundary, with TRBBASER_EL1 set to the page, to prevent
+	 * TRBE over-writing 256bytes at TRBBASER_EL1 on FILL event.
+	 *
+	 * Thus make sure we always align our write pointer to a PAGE_SIZE,
+	 * which also guarantees that we have at least a PAGE_SIZE space in
+	 * the buffer (TRBLIMITR is PAGE aligned) and thus we can skip
+	 * the required bytes at the base.
+	 */
+	if (trbe_has_erratum(TRBE_WORKAROUND_OVERWRITE_FILL_MODE, cpudata))
+		cpudata->trbe_align = PAGE_SIZE;
+	else
+		cpudata->trbe_align = cpudata->trbe_hw_align;
+
 	cpudata->trbe_flag = get_trbe_flag_update(trbidr);
 	cpudata->cpu = cpu;
 	cpudata->drvdata = drvdata;
-- 
2.24.1


  parent reply	other threads:[~2021-07-28 13:54 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-28 13:52 [PATCH 00/10] arm64: Self-hosted trace related erratum workarouds Suzuki K Poulose
2021-07-28 13:52 ` [PATCH 01/10] coresight: trbe: Add infrastructure for Errata handling Suzuki K Poulose
2021-08-02  6:43   ` Anshuman Khandual
2021-09-07  9:04     ` Suzuki K Poulose
2021-09-09  2:55       ` Anshuman Khandual
2021-07-28 13:52 ` [PATCH 02/10] coresight: trbe: Add a helper to calculate the trace generated Suzuki K Poulose
2021-07-30 10:01   ` Anshuman Khandual
2021-07-28 13:52 ` [PATCH 03/10] coresight: trbe: Add a helper to pad a given buffer area Suzuki K Poulose
2021-07-30 10:05   ` Anshuman Khandual
2021-07-28 13:52 ` [PATCH 04/10] coresight: trbe: Decouple buffer base from the hardware base Suzuki K Poulose
2021-07-30 10:53   ` Anshuman Khandual
2021-07-28 13:52 ` [PATCH 05/10] coresight: trbe: Allow driver to choose a different alignment Suzuki K Poulose
2021-07-30 11:02   ` Anshuman Khandual
2021-07-30 14:29     ` Suzuki K Poulose
2021-07-28 13:52 ` [PATCH 06/10] arm64: Add Neoverse-N2, Cortex-A710 CPU part definition Suzuki K Poulose
2021-07-30 11:26   ` Anshuman Khandual
2021-07-30 14:31     ` Suzuki K Poulose
2021-08-02 11:21   ` Catalin Marinas
2021-08-02 11:21   ` Catalin Marinas
2021-07-28 13:52 ` [PATCH 07/10] arm64: Add erratum detection for TRBE overwrite in FILL mode Suzuki K Poulose
2021-08-02  7:44   ` Anshuman Khandual
2021-08-02 11:22   ` Catalin Marinas
2021-08-06 12:44   ` Linu Cherian
2021-09-07  9:10     ` Suzuki K Poulose
2021-07-28 13:52 ` Suzuki K Poulose [this message]
2021-08-03 10:25   ` [PATCH 08/10] coresight: trbe: Workaround TRBE errat " Anshuman Khandual
2021-09-07  9:58     ` Suzuki K Poulose
2021-09-09  4:21       ` Anshuman Khandual
2021-09-09  8:37         ` Suzuki K Poulose
2021-08-06 16:09   ` Linu Cherian
2021-09-07  9:18     ` Suzuki K Poulose
2021-07-28 13:52 ` [PATCH 09/10] arm64: Enable workaround for TRBE " Suzuki K Poulose
2021-08-02  9:34   ` Anshuman Khandual
2021-08-02 11:24   ` Catalin Marinas
2021-07-28 13:52 ` [PATCH 10/10] arm64: errata: Add workaround for TSB flush failures Suzuki K Poulose
2021-07-29  9:55   ` Marc Zyngier
2021-07-29 10:41     ` Suzuki K Poulose
2021-08-02  9:12       ` Anshuman Khandual
2021-08-02  9:35         ` Marc Zyngier
2021-08-03  3:51           ` Anshuman Khandual
2021-09-08 13:39             ` Suzuki K Poulose
2021-08-02 11:27   ` Catalin Marinas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210728135217.591173-9-suzuki.poulose@arm.com \
    --to=suzuki.poulose@arm.com \
    --cc=anshuman.khandual@arm.com \
    --cc=catalin.marinas@arm.com \
    --cc=coresight@lists.linaro.org \
    --cc=james.morse@arm.com \
    --cc=leo.yan@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mathieu.poirier@linaro.org \
    --cc=maz@kernel.org \
    --cc=mike.leach@linaro.org \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).