[PATCH v2 2/2] perf: arm_spe: Ensure profiling buffer is properly disabled

Leo Yan leo.yan at arm.com
Mon Nov 10 08:28:32 PST 2025


During interrupt handling, if arm_spe_perf_aux_output_begin() fails to
calculate a valid limit, it queues the disable callback in the IRQ work
and sets the PERF_HES_STOPPED flag.

Afterwards, the disable callback arm_spe_pmu_stop() is invoked, but
since the PERF_HES_STOPPED flag has already been set, arm_spe_pmu_stop()
exits immediately. As a result, the profiling buffer is not properly
stopped — profiling on exception levels is not disabled, and buffered
data is not drained.

To fix this, explicitly disable the profiling buffer for stopped events
in the interrupt handler.

Fixes: d5d9696b0380 ("drivers/perf: Add support for ARMv8.2 Statistical Profiling Extension")
Signed-off-by: Leo Yan <leo.yan at arm.com>
---
 drivers/perf/arm_spe_pmu.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c
index fc8f908c2c3a270f2d1ae574c2badb1fbcf51484..4f51510d5f8a660c12e3934eae8a66f1a1416617 100644
--- a/drivers/perf/arm_spe_pmu.c
+++ b/drivers/perf/arm_spe_pmu.c
@@ -761,6 +761,20 @@ static irqreturn_t arm_spe_pmu_irq_handler(int irq, void *dev)
 		if (!(handle->aux_flags & PERF_AUX_FLAG_TRUNCATED)) {
 			arm_spe_perf_aux_output_begin(handle, event);
 			isb();
+
+			/*
+			 * A non-zero state indicates that an error occurred in
+			 * arm_spe_perf_aux_output_begin(), for example, if the
+			 * buffer overflowed and failed to get a valid limit.
+			 *
+			 * Since the PERF_HES_STOPPED flag has been set, the
+			 * afterwards disable callback exits immediately and
+			 * the buffer disable flow is skipped (see
+			 * arm_spe_pmu_stop()). Explicitly disable the profiling
+			 * buffer here.
+			 */
+			if (event->hw.state)
+				arm_spe_pmu_disable_and_drain_local();
 		}
 		break;
 	case SPE_PMU_BUF_FAULT_ACT_SPURIOUS:

-- 
2.34.1




More information about the linux-arm-kernel mailing list