[tip: perf/urgent] perf: Fix racy update of cpc->hrtimer_interval

From: tip-bot2 for Benjamin Segall

Date: Mon Nov 09 2026 - 03:42:41 EST


The following commit has been merged into the perf/urgent branch of tip:

Commit-ID: 3bbd85b2f67aff58f2cbec9a7fb705677b94473b
Gitweb: https://git.kernel.org/tip/3bbd85b2f67aff58f2cbec9a7fb705677b94473b
Author: Benjamin Segall <bsegall@xxxxxxxxxx>
AuthorDate: Mon, 02 Nov 2026 15:11:56 -08:00
Committer: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
CommitterDate: Fri, 06 Nov 2026 11:45:15 +01:00

perf: Fix racy update of cpc->hrtimer_interval

Updates to cpc->hrtimer_interval can race with reads either in the
hrtimer itself, or other calls to perf_mux_hrtimer_restart. This is not
exactly expected to be a common config change, but it's easy enough to
fix.

Since there's already an IPI to each cpu to restart the timer, and all
reads are with irqs disabled, just move the update onto the target cpu.

Fixes: 62b856397927 ("perf: Add sysfs entry to adjust multiplexing interval per PMU")
Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Signed-off-by: Ben Segall <bsegall@xxxxxxxxxx>
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
Link: https://sashiko.dev/#/patchset/xm265wykhyrv.fsf%40google.com
Link: https://patch.msgid.link/xm26se1ihlqb.fsf@xxxxxxxxxx
---
kernel/events/core.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index f5f2261..1404dab 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1332,14 +1332,19 @@ static int perf_mux_hrtimer_restart(struct perf_cpu_pmu_context *cpc)
return 0;
}

-static int perf_mux_hrtimer_restart_ipi(void *arg)
+static __always_inline struct perf_cpu_pmu_context *this_cpc(struct pmu *pmu)
{
- return perf_mux_hrtimer_restart(arg);
+ return *this_cpu_ptr(pmu->cpu_pmu_context);
}

-static __always_inline struct perf_cpu_pmu_context *this_cpc(struct pmu *pmu)
+static int perf_mux_hrtimer_interval_ipi(void *arg)
{
- return *this_cpu_ptr(pmu->cpu_pmu_context);
+ struct pmu *pmu = arg;
+ struct perf_cpu_pmu_context *cpc = this_cpc(pmu);
+ int ms = pmu->hrtimer_interval_ms;
+
+ cpc->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * ms);
+ return perf_mux_hrtimer_restart(cpc);
}

void perf_pmu_disable(struct pmu *pmu)
@@ -12780,13 +12785,8 @@ perf_event_mux_interval_ms_store(struct device *dev,

/* update all cpuctx for this PMU */
cpus_read_lock();
- for_each_online_cpu(cpu) {
- struct perf_cpu_pmu_context *cpc;
- cpc = *per_cpu_ptr(pmu->cpu_pmu_context, cpu);
- cpc->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * timer);
-
- cpu_function_call(cpu, perf_mux_hrtimer_restart_ipi, cpc);
- }
+ for_each_online_cpu(cpu)
+ cpu_function_call(cpu, perf_mux_hrtimer_interval_ipi, pmu);
cpus_read_unlock();
mutex_unlock(&mux_interval_mutex);