Skip to content

Commit ebfd9b7

Browse files
committed
Merge tag 'perf-urgent-2026-03-22' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar: - Fix a PMU driver crash on AMD EPYC systems, caused by a race condition in x86_pmu_enable() - Fix a possible counter-initialization bug in x86_pmu_enable() - Fix a counter inheritance bug in inherit_event() and __perf_event_read() - Fix an Intel PMU driver branch constraints handling bug found by UBSAN - Fix the Intel PMU driver's new Off-Module Response (OMR) support code for Diamond Rapids / Nova lake, to fix a snoop information parsing bug * tag 'perf-urgent-2026-03-22' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/x86/intel: Fix OMR snoop information parsing issues perf/x86/intel: Add missing branch counters constraint apply perf: Make sure to use pmu_ctx->pmu for groups x86/perf: Make sure to program the counter value for stopped events on migration perf/x86: Move event pointer setup earlier in x86_pmu_enable()
2 parents dea622e + e7fcc54 commit ebfd9b7

4 files changed

Lines changed: 41 additions & 27 deletions

File tree

arch/x86/events/core.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,14 +1372,17 @@ static void x86_pmu_enable(struct pmu *pmu)
13721372
else if (i < n_running)
13731373
continue;
13741374

1375-
if (hwc->state & PERF_HES_ARCH)
1375+
cpuc->events[hwc->idx] = event;
1376+
1377+
if (hwc->state & PERF_HES_ARCH) {
1378+
static_call(x86_pmu_set_period)(event);
13761379
continue;
1380+
}
13771381

13781382
/*
13791383
* if cpuc->enabled = 0, then no wrmsr as
13801384
* per x86_pmu_enable_event()
13811385
*/
1382-
cpuc->events[hwc->idx] = event;
13831386
x86_pmu_start(event, PERF_EF_RELOAD);
13841387
}
13851388
cpuc->n_added = 0;

arch/x86/events/intel/core.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4628,6 +4628,19 @@ static inline void intel_pmu_set_acr_caused_constr(struct perf_event *event,
46284628
event->hw.dyn_constraint &= hybrid(event->pmu, acr_cause_mask64);
46294629
}
46304630

4631+
static inline int intel_set_branch_counter_constr(struct perf_event *event,
4632+
int *num)
4633+
{
4634+
if (branch_sample_call_stack(event))
4635+
return -EINVAL;
4636+
if (branch_sample_counters(event)) {
4637+
(*num)++;
4638+
event->hw.dyn_constraint &= x86_pmu.lbr_counters;
4639+
}
4640+
4641+
return 0;
4642+
}
4643+
46314644
static int intel_pmu_hw_config(struct perf_event *event)
46324645
{
46334646
int ret = x86_pmu_hw_config(event);
@@ -4698,21 +4711,19 @@ static int intel_pmu_hw_config(struct perf_event *event)
46984711
* group, which requires the extra space to store the counters.
46994712
*/
47004713
leader = event->group_leader;
4701-
if (branch_sample_call_stack(leader))
4714+
if (intel_set_branch_counter_constr(leader, &num))
47024715
return -EINVAL;
4703-
if (branch_sample_counters(leader)) {
4704-
num++;
4705-
leader->hw.dyn_constraint &= x86_pmu.lbr_counters;
4706-
}
47074716
leader->hw.flags |= PERF_X86_EVENT_BRANCH_COUNTERS;
47084717

47094718
for_each_sibling_event(sibling, leader) {
4710-
if (branch_sample_call_stack(sibling))
4719+
if (intel_set_branch_counter_constr(sibling, &num))
4720+
return -EINVAL;
4721+
}
4722+
4723+
/* event isn't installed as a sibling yet. */
4724+
if (event != leader) {
4725+
if (intel_set_branch_counter_constr(event, &num))
47114726
return -EINVAL;
4712-
if (branch_sample_counters(sibling)) {
4713-
num++;
4714-
sibling->hw.dyn_constraint &= x86_pmu.lbr_counters;
4715-
}
47164727
}
47174728

47184729
if (num > fls(x86_pmu.lbr_counters))

arch/x86/events/intel/ds.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,12 @@ static u64 parse_omr_data_source(u8 dse)
345345
if (omr.omr_remote)
346346
val |= REM;
347347

348-
val |= omr.omr_hitm ? P(SNOOP, HITM) : P(SNOOP, HIT);
349-
350348
if (omr.omr_source == 0x2) {
351-
u8 snoop = omr.omr_snoop | omr.omr_promoted;
349+
u8 snoop = omr.omr_snoop | (omr.omr_promoted << 1);
352350

353-
if (snoop == 0x0)
351+
if (omr.omr_hitm)
352+
val |= P(SNOOP, HITM);
353+
else if (snoop == 0x0)
354354
val |= P(SNOOP, NA);
355355
else if (snoop == 0x1)
356356
val |= P(SNOOP, MISS);
@@ -359,7 +359,10 @@ static u64 parse_omr_data_source(u8 dse)
359359
else if (snoop == 0x3)
360360
val |= P(SNOOP, NONE);
361361
} else if (omr.omr_source > 0x2 && omr.omr_source < 0x7) {
362+
val |= omr.omr_hitm ? P(SNOOP, HITM) : P(SNOOP, HIT);
362363
val |= omr.omr_snoop ? P(SNOOPX, FWD) : 0;
364+
} else {
365+
val |= P(SNOOP, NONE);
363366
}
364367

365368
return val;

kernel/events/core.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4813,7 +4813,7 @@ static void __perf_event_read(void *info)
48134813
struct perf_event *sub, *event = data->event;
48144814
struct perf_event_context *ctx = event->ctx;
48154815
struct perf_cpu_context *cpuctx = this_cpu_ptr(&perf_cpu_context);
4816-
struct pmu *pmu = event->pmu;
4816+
struct pmu *pmu;
48174817

48184818
/*
48194819
* If this is a task context, we need to check whether it is
@@ -4825,33 +4825,30 @@ static void __perf_event_read(void *info)
48254825
if (ctx->task && cpuctx->task_ctx != ctx)
48264826
return;
48274827

4828-
raw_spin_lock(&ctx->lock);
4828+
guard(raw_spinlock)(&ctx->lock);
48294829
ctx_time_update_event(ctx, event);
48304830

48314831
perf_event_update_time(event);
48324832
if (data->group)
48334833
perf_event_update_sibling_time(event);
48344834

48354835
if (event->state != PERF_EVENT_STATE_ACTIVE)
4836-
goto unlock;
4836+
return;
48374837

48384838
if (!data->group) {
4839-
pmu->read(event);
4839+
perf_pmu_read(event);
48404840
data->ret = 0;
4841-
goto unlock;
4841+
return;
48424842
}
48434843

4844+
pmu = event->pmu_ctx->pmu;
48444845
pmu->start_txn(pmu, PERF_PMU_TXN_READ);
48454846

4846-
pmu->read(event);
4847-
4847+
perf_pmu_read(event);
48484848
for_each_sibling_event(sub, event)
48494849
perf_pmu_read(sub);
48504850

48514851
data->ret = pmu->commit_txn(pmu);
4852-
4853-
unlock:
4854-
raw_spin_unlock(&ctx->lock);
48554852
}
48564853

48574854
static inline u64 perf_event_count(struct perf_event *event, bool self)
@@ -14744,7 +14741,7 @@ inherit_event(struct perf_event *parent_event,
1474414741
get_ctx(child_ctx);
1474514742
child_event->ctx = child_ctx;
1474614743

14747-
pmu_ctx = find_get_pmu_context(child_event->pmu, child_ctx, child_event);
14744+
pmu_ctx = find_get_pmu_context(parent_event->pmu_ctx->pmu, child_ctx, child_event);
1474814745
if (IS_ERR(pmu_ctx)) {
1474914746
free_event(child_event);
1475014747
return ERR_CAST(pmu_ctx);

0 commit comments

Comments
 (0)