On Mon, 15 Sept 2025 at 11:33, Leo Yan leo.yan@arm.com wrote:
The ETMv3 driver shares the same issue as ETMv4 regarding race conditions when accessing the device mode.
This commit applies the same fix: ensuring that the device mode is modified only by the target CPU to eliminate race conditions across CPUs.
Fixes: 22fd532eaa0c ("coresight: etm3x: adding operation mode for etm_enable()") Signed-off-by: Leo Yan leo.yan@arm.com
drivers/hwtracing/coresight/coresight-etm3x-core.c | 54 +++++++++++++++------- 1 file changed, 37 insertions(+), 17 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c index 45630a1cd32fbd05ec8b2a6979f0174cacce365e..f759a47eaed9e804e30530a232370c9504912ac6 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c @@ -442,10 +442,23 @@ struct etm_enable_arg { static void etm_enable_hw_smp_call(void *info) { struct etm_enable_arg *arg = info;
struct coresight_device *csdev; if (WARN_ON(!arg)) return;
csdev = arg->drvdata->csdev;
if (!coresight_take_mode(csdev, CS_MODE_SYSFS)) {
/* Someone is already using the tracer */
arg->rc = -EBUSY;
return;
}
arg->rc = etm_enable_hw(arg->drvdata);
/* The tracer didn't start */
if (arg->rc)
coresight_set_mode(csdev, CS_MODE_DISABLED);
}
static int etm_cpu_id(struct coresight_device *csdev) @@ -464,17 +477,26 @@ static int etm_enable_perf(struct coresight_device *csdev, struct perf_event *event, struct coresight_path *path) {
int ret = 0; struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) return -EINVAL;
if (!coresight_take_mode(csdev, CS_MODE_PERF))
return -EBUSY;
/* Configure the tracer based on the session's specifics */ etm_parse_event_config(drvdata, event); drvdata->traceid = path->trace_id; /* And enable it */
return etm_enable_hw(drvdata);
ret = etm_enable_hw(drvdata);
/* The tracer didn't start */
if (ret)
coresight_set_mode(csdev, CS_MODE_DISABLED);
return ret;
}
static int etm_enable_sysfs(struct coresight_device *csdev, struct coresight_path *path) @@ -517,12 +539,6 @@ static int etm_enable(struct coresight_device *csdev, struct perf_event *event, enum cs_mode mode, struct coresight_path *path) { int ret;
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
if (!coresight_take_mode(csdev, mode)) {
/* Someone is already using the tracer */
return -EBUSY;
} switch (mode) { case CS_MODE_SYSFS:
@@ -535,17 +551,12 @@ static int etm_enable(struct coresight_device *csdev, struct perf_event *event, ret = -EINVAL; }
/* The tracer didn't start */
if (ret)
coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED);
return ret;
}
-static void etm_disable_hw(void *info) +static void etm_disable_hw(struct etm_drvdata *drvdata) { int i;
struct etm_drvdata *drvdata = info; struct etm_config *config = &drvdata->config; struct coresight_device *csdev = drvdata->csdev;
@@ -567,6 +578,15 @@ static void etm_disable_hw(void *info) "cpu: %d disable smp call done\n", drvdata->cpu); }
+static void etm_disable_hw_smp_call(void *info) +{
struct etm_drvdata *drvdata = info;
etm_disable_hw(drvdata);
coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED);
+}
static void etm_disable_perf(struct coresight_device *csdev) { struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -588,6 +608,8 @@ static void etm_disable_perf(struct coresight_device *csdev)
CS_LOCK(drvdata->csa.base);
coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED);
/* * perf will release trace ids when _free_aux() * is called at the end of the session
@@ -612,7 +634,8 @@ static void etm_disable_sysfs(struct coresight_device *csdev) * Executing etm_disable_hw on the cpu whose ETM is being disabled * ensures that register writes occur when cpu is powered. */
smp_call_function_single(drvdata->cpu, etm_disable_hw, drvdata, 1);
smp_call_function_single(drvdata->cpu, etm_disable_hw_smp_call,
drvdata, 1); spin_unlock(&drvdata->spinlock); cpus_read_unlock();
@@ -652,9 +675,6 @@ static void etm_disable(struct coresight_device *csdev, WARN_ON_ONCE(mode); return; }
if (mode)
coresight_set_mode(csdev, CS_MODE_DISABLED);
}
static const struct coresight_ops_source etm_source_ops = {
-- 2.34.1
Reviewed-by: Mike Leach mike.leach@linaro.org
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK