[PATCH 1/2] perf/x86/amd/uncore: Remove redundant event slot scan
From: Usama Arif
Date: Mon Sep 21 2026 - 13:46:56 EST
amd_uncore_add() first checks the slot recorded in event->hw.idx. If
that misses, it scans ctx->events[] for the event before looking for a
free slot.
Perf serializes ->add() and ->del() for an event. Initialization sets
idx to -1. A successful ->add() claims a slot and records its index
before returning, while ->del() clears the slot before resetting idx.
CPU context migration follows the same delete/add sequence.
Thus an installed event can only reside at the recorded index. If the
direct check misses, the event is not present in ctx->events[].
Remove the redundant scan. This avoids walking all counters before each
new slot search after multiplexing has scheduled an event out.
On a host running a production workload in the Meta fleet, amd_uncore_add()
was called 56,575 times per second from mux rotation. Its 16-counter DF PMU
makes each failed search scan 16 pointers across two cache lines.
Cc: Sandipan Das <sandipan.das@xxxxxxx>
Signed-off-by: Usama Arif <usama.arif@xxxxxxxxx>
---
arch/x86/events/amd/uncore.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c
index 7181973b5b127..53be8efaedc5d 100644
--- a/arch/x86/events/amd/uncore.c
+++ b/arch/x86/events/amd/uncore.c
@@ -206,17 +206,15 @@ static int amd_uncore_add(struct perf_event *event, int flags)
struct amd_uncore_ctx *ctx = *per_cpu_ptr(pmu->ctx, event->cpu);
struct hw_perf_event *hwc = &event->hw;
- /* are we already assigned? */
+ /*
+ * Perf serializes ->add() and ->del() for an event. A successful
+ * ->add() records the claimed slot in hwc->idx before returning, and
+ * ->del() clears that slot before resetting hwc->idx. Therefore, an
+ * existing assignment must be at hwc->idx.
+ */
if (hwc->idx != -1 && ctx->events[hwc->idx] == event)
goto out;
- for (i = 0; i < pmu->num_counters; i++) {
- if (ctx->events[i] == event) {
- hwc->idx = i;
- goto out;
- }
- }
-
/* if not, take the first available counter */
hwc->idx = -1;
for (i = 0; i < pmu->num_counters; i++) {
--
2.53.0-Meta