Re: [PATCH 07/23] perf/x86: Apply PMU partition mask on static constraints
From: Chen, Zide
Date: Thu Aug 27 2026 - 19:01:58 EST
On 8/26/2026 3:12 AM, Mi, Dapeng wrote:
> It seems not a good practice for me to modify all the places calling these
> static constraints. We could have to add new get_event_constraints()
> helpers for future platforms, and we have to duplicate these
> part_constraint() code.
> Could we leverage the dynamic constraint mechanism? We can set the
> event->hw.dyn_constraint to be host counters mask, then we don't need any
> specific change for these static constraints.
In all code paths that use these static constraints, for example,
counter0_constraint, it is assumed that GP counter 0 is available on the
host. However, with PMU partitioning, any counter may be unavailable,
even in the model-specific code path, and this assumption is broken.
So, adding a wrapper seems unavoidable.
Additionally, part_constraint() already makes use of dyn_constraint, right?
> Thanks.
>
> On 8/22/2026 6:19 AM, Zide Chen wrote:
>> Static, counter-specific constraints used for attr.precise_ip == 3, or
>> other special cases bypass intel_get_event_constraints(), which is
>> where partition_mask is applied via dyn_constraint().
>>
>> As a result, such a host !exclude_guest event can still be scheduled
>> onto a counter that partition_mask reserves for the guest, causing
>> host and guest to share the same hardware counter.
>>
>> Some of these static constraint paths, e.g. glp or cmt, are currently
>> only reachable on platforms that don't support PerfMon masking. Still,
>> apply part_constraint() to all of them uniformly, so future platforms
>> that combine PerfMon masking with these constraint paths are not
>> silently exposed to this bug.
>>
>> Signed-off-by: Zide Chen <zide.chen@xxxxxxxxx>
>> ---
>> arch/x86/events/intel/core.c | 39 +++++++++++++++++++++++-------------
>> 1 file changed, 25 insertions(+), 14 deletions(-)
>>
>> diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
>> index 7951accfcf2c..0f76e56fd2db 100644
>> --- a/arch/x86/events/intel/core.c
>> +++ b/arch/x86/events/intel/core.c
>> @@ -4459,6 +4459,9 @@ dyn_constraint(struct cpu_hw_events *cpuc, struct event_constraint *c, int idx)
>> * Mask out guest-owned counters from a constraint when PMU partition has been
>> * entered, so !exclude_guest host events are not scheduled onto them while
>> * the CPU is in non-root mode.
>> + *
>> + * This is also used by PMU-specific get_event_constraints() wrappers
>> + * that hard-code a static, counter-specific constraint.
>> */
>> static struct event_constraint *
>> part_constraint(struct cpu_hw_events *cpuc, int idx,
>> @@ -5568,7 +5571,7 @@ hsw_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
>> /* Handle special quirk on in_tx_checkpointed only in counter 2 */
>> if (event->hw.config & HSW_IN_TX_CHECKPOINTED) {
>> if (c->idxmsk64 & (1U << 2))
>> - return &counter2_constraint;
>> + return part_constraint(cpuc, idx, event, &counter2_constraint);
>> return &emptyconstraint;
>> }
>>
>> @@ -5585,7 +5588,7 @@ icl_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
>> */
>> if ((event->attr.precise_ip == 3) &&
>> constraint_match(&fixed0_constraint, event->hw.config))
>> - return &fixed0_constraint;
>> + return part_constraint(cpuc, idx, event, &fixed0_constraint);
>>
>> return hsw_get_event_constraints(cpuc, idx, event);
>> }
>> @@ -5607,7 +5610,7 @@ glc_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
>> if ((event->attr.precise_ip == 3) &&
>> !constraint_match(&fixed0_constraint, event->hw.config)) {
>> if (c->idxmsk64 & BIT_ULL(0))
>> - return &counter0_constraint;
>> + return part_constraint(cpuc, idx, event, &counter0_constraint);
>>
>> return &emptyconstraint;
>> }
>> @@ -5623,7 +5626,7 @@ glp_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
>>
>> /* :ppp means to do reduced skid PEBS which is PMC0 only. */
>> if (event->attr.precise_ip == 3)
>> - return &counter0_constraint;
>> + return part_constraint(cpuc, idx, event, &counter0_constraint);
>>
>> c = intel_get_event_constraints(cpuc, idx, event);
>>
>> @@ -5645,9 +5648,9 @@ tnt_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
>> if (event->attr.precise_ip == 3) {
>> /* Force instruction:ppp on PMC0 and Fixed counter 0 */
>> if (constraint_match(&fixed0_constraint, event->hw.config))
>> - return &fixed0_counter0_constraint;
>> + return part_constraint(cpuc, idx, event, &fixed0_counter0_constraint);
>>
>> - return &counter0_constraint;
>> + return part_constraint(cpuc, idx, event, &counter0_constraint);
>> }
>>
>> return c;
>> @@ -5705,22 +5708,30 @@ cmt_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
>> if (event->attr.precise_ip == 3) {
>> /* Force instruction:ppp on PMC0, 1 and Fixed counter 0 */
>> if (constraint_match(&fixed0_constraint, event->hw.config)) {
>> + c = &fixed0_counter0_1_constraint;
>> +
>> /* The fixed counter 0 doesn't support LBR event logging. */
>> if (branch_sample_counters(event))
>> - return &counter0_1_constraint;
>> - else
>> - return &fixed0_counter0_1_constraint;
>> + c = &counter0_1_constraint;
>> +
>> + return part_constraint(cpuc, idx, event, c);
>> }
>>
>> switch (c->idxmsk64 & 0x3ull) {
>> case 0x1:
>> - return &counter0_constraint;
>> + c = &counter0_constraint;
>> + break;
>> case 0x2:
>> - return &counter1_constraint;
>> + c = &counter1_constraint;
>> + break;
>> case 0x3:
>> - return &counter0_1_constraint;
>> + c = &counter0_1_constraint;
>> + break;
>> + default:
>> + c = &emptyconstraint;
>> + break;
>> }
>> - return &emptyconstraint;
>> + return part_constraint(cpuc, idx, event, c);
>> }
>>
>> return c;
>> @@ -5744,7 +5755,7 @@ rwc_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
>> */
>> if (event->attr.precise_ip == 3)
>> return &emptyconstraint;
>> - return &counters_1_7_constraint;
>> + return part_constraint(cpuc, idx, event, &counters_1_7_constraint);
>> }
>>
>> return c;