[PATCH 12/25] coresight: trbe: Track per-CPU sink interrupt handling
From: Leo Yan <leo.yan@arm.com>
Date: 2026-09-15 15:49:54
Also in:
linux-arm-kernel, linux-perf-users, lkml
Subsystem:
arm/coresight framework and drivers, hardware tracing facilities, the rest · Maintainers:
Suzuki K Poulose, Alexander Shishkin, Linus Torvalds
A sampling NMI can interrupt TRBE while it is using the active AUX handle or buffer. Circular buffer mode avoids wrap interrupts but can still generate fault interrupts. Add an in_interrupt flag to per-CPU sinks and set it around the TRBE IRQ handler. Compiler barriers keep AUX buffer accesses between the flag updates. This lets NMI callbacks detect when they have interrupted sink handling before modifying its state. Assisted-by: Codex:gpt-6 Signed-off-by: Leo Yan <leo.yan@arm.com> --- drivers/hwtracing/coresight/coresight-trbe.c | 17 ++++++++++++++++- include/linux/coresight.h | 2 ++ 2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c
index ab3c5c7d27f3d272b07eade1e6452559808b196c..8eb625d3fc99db57a18e35ef59ef814dacf20a09 100644
--- a/drivers/hwtracing/coresight/coresight-trbe.c
+++ b/drivers/hwtracing/coresight/coresight-trbe.c@@ -1185,7 +1185,7 @@ static u64 cpu_prohibit_trace(void) return trfcr; } -static irqreturn_t arm_trbe_irq_handler(int irq, void *dev) +static irqreturn_t __arm_trbe_irq_handler(int irq, void *dev) { struct perf_output_handle **handle_ptr = dev; struct perf_output_handle *handle = *handle_ptr;
@@ -1249,6 +1249,21 @@ static irqreturn_t arm_trbe_irq_handler(int irq, void *dev) return IRQ_HANDLED; } +static irqreturn_t arm_trbe_irq_handler(int irq, void *dev) +{ + struct coresight_device *csdev = coresight_get_percpu_sink(smp_processor_id()); + irqreturn_t ret; + + /* Circular Buffer mode can still interrupt on a fault. */ + WRITE_ONCE(csdev->in_interrupt, true); + barrier(); + ret = __arm_trbe_irq_handler(irq, dev); + barrier(); + WRITE_ONCE(csdev->in_interrupt, false); + + return ret; +} + static int arm_trbe_save(struct coresight_device *csdev) { struct trbe_cpudata *cpudata = dev_get_drvdata(&csdev->dev);
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index ddf18c970e343041787424c2019f2b5dd49154c2..8830c30be0df53a22525ef4fc3c7e41a0ec6fd90 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h@@ -275,6 +275,7 @@ struct coresight_trace_id_map { * when a source has been selected and a path is enabled from * source to that sink. A sink can also become enabled but not * activated if it's used via Perf. + * @in_interrupt: Per-CPU sink interrupt handler is running. * @ea: Device attribute for sink representation under PMU directory. * @def_sink: cached reference to default sink found for this device. * @nr_links: number of sysfs links created to other components from this
@@ -299,6 +300,7 @@ struct coresight_device { bool orphan; /* sink specific fields */ bool sysfs_sink_activated; + bool in_interrupt; struct dev_ext_attribute *ea; struct coresight_device *def_sink; struct coresight_trace_id_map perf_sink_id_map;
--
2.34.1