Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf: arm_spe: Relax period restriction

The minimum interval specified the PMSIDR_EL1.Interval field is a
hardware recommendation. However, this value is set by hardware designer
before the production. It is not actual hardware limitation but tools
currently have no way to test shorter periods.

This change relaxes the limitation by allowing any non-zero periods,
with simplifying code with clamp_t().

The downside is that small periods may increase the risk of AUX ring
buffer overruns. When an overrun occurs, the perf core layer will
trigger an irq work to disable the event and wake up the tool in user
space to read the trace data. After the tool finishes reading, it will
re-enable the AUX event.

Signed-off-by: Leo Yan <leo.yan@arm.com>
Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
Link: https://lore.kernel.org/r/20250627163028.3503122-1-leo.yan@arm.com
Signed-off-by: Will Deacon <will@kernel.org>

authored by

Leo Yan and committed by
Will Deacon
ba2ff3e1 58074a0f

+11 -7
+11 -7
drivers/perf/arm_spe_pmu.c
··· 308 308 309 309 static void arm_spe_event_sanitise_period(struct perf_event *event) 310 310 { 311 - struct arm_spe_pmu *spe_pmu = to_spe_pmu(event->pmu); 312 311 u64 period = event->hw.sample_period; 313 312 u64 max_period = PMSIRR_EL1_INTERVAL_MASK; 314 313 315 - if (period < spe_pmu->min_period) 316 - period = spe_pmu->min_period; 317 - else if (period > max_period) 318 - period = max_period; 319 - else 320 - period &= max_period; 314 + /* 315 + * The PMSIDR_EL1.Interval field (stored in spe_pmu->min_period) is a 316 + * recommendation for the minimum interval, not a hardware limitation. 317 + * 318 + * According to the Arm ARM (DDI 0487 L.a), section D24.7.12 PMSIRR_EL1, 319 + * Sampling Interval Reload Register, the INTERVAL field (bits [31:8]) 320 + * states: "Software must set this to a nonzero value". Use 1 as the 321 + * minimum value. 322 + */ 323 + u64 min_period = FIELD_PREP(PMSIRR_EL1_INTERVAL_MASK, 1); 321 324 325 + period = clamp_t(u64, period, min_period, max_period) & max_period; 322 326 event->hw.sample_period = period; 323 327 } 324 328