Skip to contentSkip to conversation

perf/x86/intel: Fix several bugs of auto counter

PATCH Superseded Dapeng Mi 3 participants 15 messages Apr 20 – Apr 23

Subsystems (3)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore

Dapeng Mi

author
#0 lore raw

v2 cover perf/x86/intel: Fix several bugs of auto counter

Changes:
v1 -> v2:
- Clear stale mask for all events (Sashiko, Patch 1/4)
- Enable auto counter reload for DMR. (Patch 3/4)
- Remove duplicated CFG_C MSR value tracking. (Patch 4/4)

This small patch-set fixes 2 issues in auto counter reload support.
- The stale ACR mask is not cleared before setting a new one. Patch 1/2 fixes this issue.
- PMI is enabled by default for self-reloaded ACR events which causes suspicious NMI warning. Patch 2/2 fixes this issue.

Besides an ACR unit test is added into perf tests which would be posted in a separate session.

Tests:

Run below ACR sampling commands on CWF, DMR, PTL and NVL (hybrid platforms), no issues are found.

a. Non-PEBS ACR sampling

perf record -e '{instructions/period=20000,acr_mask=0x2/u,cycles/period=40000,acr_mask=0x3/u}' ~/test

b. PEBS ACR sampling

perf record -e '{instructions/period=20000,acr_mask=0x2/pu,cycles/period=40000,acr_mask=0x3/u}' ~/test

History:
v1: https://lore.kernel.org/all/[email protected]/

Dapeng Mi (4):
perf/x86/intel: Clear stale ACR mask before updating new mask perf/x86/intel: Disable PMI for self-reloaded ACR events perf/x86/intel: Enable auto counter reload for DMR perf/x86/intel: Consolidate MSR_IA32_PERF_CFG_C tracking

 arch/x86/events/intel/core.c | 37 ++++++++++++++++++++++++++----------
 arch/x86/events/perf_event.h | 14 +++++++++++---
 2 files changed, 38 insertions(+), 13 deletions(-)

base-commit: 9805ed3c91478b08a586861b874bd8b6a2fed648

Signature · 1 line
2.34.1
author
#1 lore raw

PATCH v2 1/4 perf/x86/intel: Clear stale ACR mask before updating new mask

The current implementation forgets to clear the ACR mask before applying a new one. During event rescheduling, this allow bits from a previous stale ACR mask to persist, leading to an incorrect hardware state.

Ensure that the ACR mask is zeroed out before setting the new mask to prevent state pollution.

Fixes ec980e4facef ("perf/x86/intel: Support auto counter reload")

---

V2: Clear stale acr_mask for all events.

 arch/x86/events/intel/core.c | 6 ++++++
 1 file changed, 6 insertions(+)
arch/x86/events/intel/core.c +6 -0
index 4768236c054b..774ae9a4eeaf 100644
@@ -3334,6 +3334,12 @@ static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc)
 	struct perf_event *event, *leader;
 	int i, j, idx;
 
+	/* Clear stale ACR mask first. */
+	for (i = 0; i < cpuc->n_events; i++) {
+		event = cpuc->event_list[i];
+		event->hw.config1 = 0;
+	}
+
 	for (i = 0; i < cpuc->n_events; i++) {
 		leader = cpuc->event_list[i];
 		if (!is_acr_event_group(leader))
Signature · 1 line
2.34.1
#2 lore raw

Re: [Patch v2 1/4] perf/x86/intel: Clear stale ACR mask before updating new mask

Sashiko AI review found 1 potential issue(s): - [High] Unvalidated user input in ACR setup leads to cross-user hardware state corruption and PMU DoS --

Sashiko AI review found 1 potential issue(s):
- [High] Unvalidated user input in ACR setup leads to cross-user hardware state corruption and PMU DoS --

commit 67dc3d7b096879ed6418f54978bf45536496156f
Author: Dapeng Mi <[email protected]>

perf/x86/intel: Clear stale ACR mask before updating new mask

This commit zeroes out the ACR mask (event->hw.config1) for all scheduled events before applying a new mask. This ensures that bits from a previous stale ACR mask do not persist and pollute the hardware state during event rescheduling.

Quoted 5 lines
arch/x86/events/intel/core.c +0 -0
index 4768236c054bb..774ae9a4eeaf8 100644

arch/x86/events/intel/core.c static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc) · line 3342

Quoted 9 lines
arch/x86/events/intel/core.c +6 -0
@@ -3334,6 +3334,12 @@ static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc)
 	struct perf_event *event, *leader;
 	int i, j, idx;
 
+	/* Clear stale ACR mask first. */
+	for (i = 0; i < cpuc->n_events; i++) {
+		event = cpuc->event_list[i];
+		event->hw.config1 = 0;
+	}
+

Does this new clearing loop inadvertently amplify an existing regression where a single user can disable Auto Counter Reload for all processes on the same CPU?

Looking further down in the same function, the code iterates over user-controlled bits from event->attr.config2:

arch/x86/events/intel/core.c:intel_pmu_acr_late_setup() {
    ...
    for_each_set_bit(idx, (unsigned long *)&event->attr.config2, X86_PMC_IDX_MAX) {
        if (i + idx >= cpuc->n_events ||
            !is_acr_event_group(cpuc->event_list[i + idx]))
            return;
        __set_bit(cpuc->assign[i + idx], (unsigned long *)&event->hw.config1);
    }
    ...
}

Because idx is derived from the user-controlled event->attr.config2 mask without being validated against the actual size of the event group, a user could provide an artificially large idx.

The validation in intel_pmu_hw_config() only checks the weight of the mask using hweight64(), rather than checking the actual bit indices, leaving this exposed. Subsequent patches in the series do not fix this.

If the computed index hits a non-ACR event or exceeds cpuc->n_events, the loop triggers an early return. Since the newly added code zeroes out event->hw.config1 for all scheduled events before this loop, wouldn't this early return leave all subsequent valid ACR events with a cleared mask?

Additionally, if the out-of-bounds idx points to another user's valid ACR group, is_acr_event_group() returns true, and the code proceeds to update the event->hw.config1 with the victim's hardware counter index.

Could this also result in cross-user state corruption of event->hw.config1 when the event overflows and cross-reloads the victim's counter?

Quoted 3 lines
arch/x86/events/intel/core.c +0 -0
 	for (i = 0; i < cpuc->n_events; i++) {
 		leader = cpuc->event_list[i];
 		if (!is_acr_event_group(leader))
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
author
#3 lore raw

Re: [Patch v2 1/4] perf/x86/intel: Clear stale ACR mask before updating new mask

Quoted 58 lines · On 4/20/2026 11:24 AM, [email protected] wrote:

Sashiko AI review found 1 potential issue(s):
- [High] Unvalidated user input in ACR setup leads to cross-user hardware state corruption and PMU DoS --

commit 67dc3d7b096879ed6418f54978bf45536496156f
Author: Dapeng Mi <[email protected]>

perf/x86/intel: Clear stale ACR mask before updating new mask

This commit zeroes out the ACR mask (event->hw.config1) for all scheduled events before applying a new mask. This ensures that bits from a previous stale ACR mask do not persist and pollute the hardware state during event rescheduling.

Quoted 5 lines
arch/x86/events/intel/core.c +0 -0
index 4768236c054bb..774ae9a4eeaf8 100644

arch/x86/events/intel/core.c static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc) · line 3342

Quoted 9 lines
arch/x86/events/intel/core.c +6 -0
@@ -3334,6 +3334,12 @@ static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc)
 	struct perf_event *event, *leader;
 	int i, j, idx;
 
+	/* Clear stale ACR mask first. */
+	for (i = 0; i < cpuc->n_events; i++) {
+		event = cpuc->event_list[i];
+		event->hw.config1 = 0;
+	}
+

Does this new clearing loop inadvertently amplify an existing regression where a single user can disable Auto Counter Reload for all processes on the same CPU?

Looking further down in the same function, the code iterates over user-controlled bits from event->attr.config2:

arch/x86/events/intel/core.c:intel_pmu_acr_late_setup() {
    ...
    for_each_set_bit(idx, (unsigned long *)&event->attr.config2, X86_PMC_IDX_MAX) {
        if (i + idx >= cpuc->n_events ||
            !is_acr_event_group(cpuc->event_list[i + idx]))
            return;
        __set_bit(cpuc->assign[i + idx], (unsigned long *)&event->hw.config1);
    }
    ...
}

Because idx is derived from the user-controlled event->attr.config2 mask without being validated against the actual size of the event group, a user could provide an artificially large idx.

The validation in intel_pmu_hw_config() only checks the weight of the mask using hweight64(), rather than checking the actual bit indices, leaving this exposed. Subsequent patches in the series do not fix this.

If the computed index hits a non-ACR event or exceeds cpuc->n_events, the loop triggers an early return. Since the newly added code zeroes out event->hw.config1 for all scheduled events before this loop, wouldn't this early return leave all subsequent valid ACR events with a cleared mask?

Quoted 6 lines

Additionally, if the out-of-bounds idx points to another user's valid ACR group, is_acr_event_group() returns true, and the code proceeds to update the event->hw.config1 with the victim's hardware counter index.

Could this also result in cross-user state corruption of event->hw.config1 when the event overflows and cross-reloads the victim's counter?

That looks a real potential issue. Current validation for the acr_mask needs to be enhanced. The acr_mask from user space should not exceeds the index bitmap of current ACR events group.
Thanks.

Quoted 4 lines
Quoted 4 lines
arch/x86/events/intel/core.c +0 -0
 	for (i = 0; i < cpuc->n_events; i++) {
 		leader = cpuc->event_list[i];
 		if (!is_acr_event_group(leader))
author
#4 lore raw

Re: [Patch v2 1/4] perf/x86/intel: Clear stale ACR mask before updating new mask

Quoted 63 lines · Dapeng
Quoted 62 lines · On 4/20/2026 11:24 AM, [email protected] wrote:

Sashiko AI review found 1 potential issue(s):
- [High] Unvalidated user input in ACR setup leads to cross-user hardware state corruption and PMU DoS --

commit 67dc3d7b096879ed6418f54978bf45536496156f
Author: Dapeng Mi <[email protected]>

perf/x86/intel: Clear stale ACR mask before updating new mask

This commit zeroes out the ACR mask (event->hw.config1) for all scheduled events before applying a new mask. This ensures that bits from a previous stale ACR mask do not persist and pollute the hardware state during event rescheduling.

Quoted 5 lines
arch/x86/events/intel/core.c +0 -0
index 4768236c054bb..774ae9a4eeaf8 100644

arch/x86/events/intel/core.c static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc) · line 3342

Quoted 9 lines
arch/x86/events/intel/core.c +6 -0
@@ -3334,6 +3334,12 @@ static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc)
 	struct perf_event *event, *leader;
 	int i, j, idx;
 
+	/* Clear stale ACR mask first. */
+	for (i = 0; i < cpuc->n_events; i++) {
+		event = cpuc->event_list[i];
+		event->hw.config1 = 0;
+	}
+

Does this new clearing loop inadvertently amplify an existing regression where a single user can disable Auto Counter Reload for all processes on the same CPU?

Looking further down in the same function, the code iterates over user-controlled bits from event->attr.config2:

arch/x86/events/intel/core.c:intel_pmu_acr_late_setup() {
    ...
    for_each_set_bit(idx, (unsigned long *)&event->attr.config2, X86_PMC_IDX_MAX) {
        if (i + idx >= cpuc->n_events ||
            !is_acr_event_group(cpuc->event_list[i + idx]))
            return;
        __set_bit(cpuc->assign[i + idx], (unsigned long *)&event->hw.config1);
    }
    ...
}

Because idx is derived from the user-controlled event->attr.config2 mask without being validated against the actual size of the event group, a user could provide an artificially large idx.

The validation in intel_pmu_hw_config() only checks the weight of the mask using hweight64(), rather than checking the actual bit indices, leaving this exposed. Subsequent patches in the series do not fix this.

If the computed index hits a non-ACR event or exceeds cpuc->n_events, the loop triggers an early return. Since the newly added code zeroes out event->hw.config1 for all scheduled events before this loop, wouldn't this early return leave all subsequent valid ACR events with a cleared mask?

Additionally, if the out-of-bounds idx points to another user's valid ACR group, is_acr_event_group() returns true, and the code proceeds to update the event->hw.config1 with the victim's hardware counter index.

Quoted 6 lines
Quoted 2 lines

Could this also result in cross-user state corruption of event->hw.config1 when the event overflows and cross-reloads the victim's counter?

That looks a real potential issue. Current validation for the acr_mask needs to be enhanced. The acr_mask from user space should not exceeds the index bitmap of current ACR events group.
Thanks.

The following changes would be done to address all current found issues.
 - Calculate the indices bitmap for each ACR events group. Any bits in the user-space mask not present in the group's bitmap are now dropped.
 - Instead of an early return on invalid bits, drop only the invalid portions and continue iterating through all ACR events to ensure full configuration.
 - Explicitly clear the stale hardware ACR mask for each event prior to writing the new configuration.

arch/x86/events/intel/core.c +0 -0
index 4768236c054b..1a2c268018a2 100644
@@ -3332,23 +3332,41 @@ static void intel_pmu_enable_event(struct

perf_event *event)
 static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc) {
        struct perf_event *event, *leader;
-       int i, j, idx;
+       int i, j, k, bit, idx;
+       u64 group_mask;

        for (i = 0; i < cpuc->n_events; i++) {
                leader = cpuc->event_list[i];
                if (!is_acr_event_group(leader))
                        continue;

-               /* The ACR events must be contiguous. */
+               /* Find the last event of the ACR group. */
                for (j = i; j < cpuc->n_events; j++) {
                        event = cpuc->event_list[j];
                        if (event->group_leader != leader->group_leader) break;
-                       for_each_set_bit(idx, (unsigned long *)&event->attr.config2, X86_PMC_IDX_MAX) {
-                               if (i + idx >= cpuc->n_events ||
-                                   !is_acr_event_group(cpuc->event_list[i
+ idx]))
-                                       return;
-                               __set_bit(cpuc->assign[i + idx], (unsigned long *)&event->hw.config1);
+               }
+
+               /* Figure out the group indices bitmap. */
+               group_mask = 0;
+               for (k = i; k < j; k++)
+                       group_mask |= BIT_ULL(cpuc->assign[k]);
+
+               /*
+                * Translate the user-space ACR mask (attr.config2) into the physical
+                * counter bitmask (hw.config1) for each ACR event in the group.
+                * NOTE: ACR event contiguity is guaranteed by intel_pmu_hw_config().
+                */
+               for (k = i; k < j; k++) {
+                       event = cpuc->event_list[k];
+                       event->hw.config1 = 0;
+                       for_each_set_bit(bit, (unsigned long *)&event->attr.config2, X86_PMC_IDX_MAX) {
+                               idx = i + bit;
+                               if (idx >= cpuc->n_events ||
+                                   !(BIT_ULL(cpuc->assign[idx]) & group_mask) ||
+                                   !is_acr_event_group(cpuc->event_list[idx])) +                                       continue;
+                               __set_bit(cpuc->assign[idx], (unsigned long *)&event->hw.config1);
                        }
                }
                i = j - 1;

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
arch/x86/events/intel/core.c +0 -0
 	for (i = 0; i < cpuc->n_events; i++) {
 		leader = cpuc->event_list[i];
 		if (!is_acr_event_group(leader))
#5 lore raw

Re: [Patch v2 1/4] perf/x86/intel: Clear stale ACR mask before updating new mask

In reply to Dapeng Mi

arch/x86/events/intel/core.c static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc) · line 3341

Quoted 13 lines
arch/x86/events/intel/core.c +5 -0
index 4768236c054b..774ae9a4eeaf 100644
@@ -3334,6 +3334,12 @@ static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc)
 	struct perf_event *event, *leader;
 	int i, j, idx;
 
+	/* Clear stale ACR mask first. */
+	for (i = 0; i < cpuc->n_events; i++) {
+		event = cpuc->event_list[i];
+		event->hw.config1 = 0;
+	}

Are you sure nothing else could be using config1?

In principle ACR events can be used with some config1 setting.

-Andi

author
#6 lore raw

Re: [Patch v2 1/4] perf/x86/intel: Clear stale ACR mask before updating new mask

Quoted 8 lines · Andi Kleen
Quoted 8 lines
arch/x86/events/intel/core.c +0 -0
index 4768236c054b..774ae9a4eeaf 100644
@@ -3334,6 +3334,12 @@ static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc)
 	struct perf_event *event, *leader;
 	int i, j, idx;
 
Quoted 8 lines

arch/x86/events/intel/core.c static void intel_pmu_acr_late_setup(struct cpu_hw_events *cpuc) · line 3341

Quoted 5 lines
arch/x86/events/intel/core.c +5 -0
+	/* Clear stale ACR mask first. */
+	for (i = 0; i < cpuc->n_events; i++) {
+		event = cpuc->event_list[i];
+		event->hw.config1 = 0;
+	}

Are you sure nothing else could be using config1?

In principle ACR events can be used with some config1 setting.

Yes, the field "hw.config1" is introduced for support auto counter reload, it's only used to store the ACR counter indices. Thanks.

https://lore.kernel.org/all/[email protected]/

Quoted 3 lines

-Andi

author
#7 lore raw

PATCH v2 2/4 perf/x86/intel: Disable PMI for self-reloaded ACR events

In reply to Dapeng Mi

On platforms with Auto Counter Reload (ACR) support, such as NVL, a "NMI received for unknown reason 30" warning is observed when running multiple events in a group with ACR enabled:

  $ perf record -e '{instructions/period=20000,acr_mask=0x2/u,\
    cycles/period=40000,acr_mask=0x3/u}' ./test

The warning occurs because the Performance Monitoring Interrupt (PMI) is enabled for the self-reloaded event (the cycles event in this case). According to the Intel SDM, the overflow bit (IA32_PERF_GLOBAL_STATUS.PMCn_OVF) is never set for self-reloaded events. Since the bit is not set, the perf NMI handler cannot identify the source of the interrupt, leading to the "unknown reason" message.

Furthermore, enabling PMI for self-reloaded events is unnecessary and can lead to extraneous records that pollute the user's requested data.

Disable the interrupt bit for all events configured with ACR self-reload.

Fixes ec980e4facef ("perf/x86/intel: Support auto counter reload")
---
 arch/x86/events/intel/core.c | 17 +++++++++++++----
 arch/x86/events/perf_event.h | 10 ++++++++++
 2 files changed, 23 insertions(+), 4 deletions(-)
arch/x86/events/intel/core.c +13 -4
index 774ae9a4eeaf..510b087c9e89 100644
@@ -3118,11 +3118,11 @@ static void intel_pmu_enable_fixed(struct perf_event *event)
 	intel_set_masks(event, idx);
 
 	/*
-	 * Enable IRQ generation (0x8), if not PEBS,
-	 * and enable ring-3 counting (0x2) and ring-0 counting (0x1)
-	 * if requested:
+	 * Enable IRQ generation (0x8), if not PEBS and self-reloaded
+	 * ACR event, and enable ring-3 counting (0x2) and ring-0
+	 * counting (0x1) if requested:
 	 */
-	if (!event->attr.precise_ip)
+	if (!event->attr.precise_ip && !is_acr_self_reload_event(event))
 		bits |= INTEL_FIXED_0_ENABLE_PMI;
 	if (hwc->config & ARCH_PERFMON_EVENTSEL_USR)
 		bits |= INTEL_FIXED_0_USER;
@@ -3306,6 +3306,15 @@ static void intel_pmu_enable_event(struct perf_event *event)
 		intel_set_masks(event, idx);
 		static_call_cond(intel_pmu_enable_acr_event)(event);
 		static_call_cond(intel_pmu_enable_event_ext)(event);
+		/*
+		 * For self-reloaded ACR event, don't enable PMI since
+		 * HW won't set overflow bit in GLOBAL_STATUS. Otherwise,
+		 * the PMI would be recognized as a suspicious NMI.
+		 */
+		if (is_acr_self_reload_event(event))
+			hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT;
+		else if (!event->attr.precise_ip)
+			hwc->config |= ARCH_PERFMON_EVENTSEL_INT;
 		__x86_pmu_enable_event(hwc, enable_mask);
 		break;
 	case INTEL_PMC_IDX_FIXED ... INTEL_PMC_IDX_FIXED_BTS - 1:
arch/x86/events/perf_event.h +10 -0
index fad87d3c8b2c..524668dcf4cc 100644
@@ -137,6 +137,16 @@ static inline bool is_acr_event_group(struct perf_event *event)
 	return check_leader_group(event->group_leader, PERF_X86_EVENT_ACR);
 }
 
+static inline bool is_acr_self_reload_event(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (hwc->idx < 0)
+		return false;
+
+	return test_bit(hwc->idx, (unsigned long *)&hwc->config1);
+}
+
 struct amd_nb {
 	int nb_id;  /* NorthBridge id */
 	int refcnt; /* reference count */
Signature · 1 line
2.34.1
#8 lore raw

Re: [Patch v2 2/4] perf/x86/intel: Disable PMI for self-reloaded ACR events

arch/x86/events/intel/core.c static void intel_pmu_enable_event(struct perf_event *event) · line 3317

Quoted 13 lines · Dapeng Mi
arch/x86/events/intel/core.c +9 -0
@@ -3306,6 +3306,15 @@ static void intel_pmu_enable_event(struct perf_event *event)
 		intel_set_masks(event, idx);
 		static_call_cond(intel_pmu_enable_acr_event)(event);
 		static_call_cond(intel_pmu_enable_event_ext)(event);
+		/*
+		 * For self-reloaded ACR event, don't enable PMI since
+		 * HW won't set overflow bit in GLOBAL_STATUS. Otherwise,
+		 * the PMI would be recognized as a suspicious NMI.
+		 */
+		if (is_acr_self_reload_event(event))
+			hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT;
+		else if (!event->attr.precise_ip)
+			hwc->config |= ARCH_PERFMON_EVENTSEL_INT;

It seems weird to either clear or set the bit. You don't know the previous state of the bit here? I would assume it starts with zero?

arch/x86/events/perf_event.h static inline bool is_acr_event_group(struct perf_event *event) · line 147

Quoted 8 lines
arch/x86/events/perf_event.h +8 -0
+static inline bool is_acr_self_reload_event(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (hwc->idx < 0)
+		return false;
+
+	return test_bit(hwc->idx, (unsigned long *)&hwc->config1);

Are you sure this doesn't conflict with some other non ACR usage of config1?

-Andi

author
#9 lore raw

Re: [Patch v2 2/4] perf/x86/intel: Disable PMI for self-reloaded ACR events

Quoted 16 lines · Andi Kleen

arch/x86/events/intel/core.c static void intel_pmu_enable_event(struct perf_event *event) · line 3317

Quoted 13 lines · Dapeng Mi
arch/x86/events/intel/core.c +9 -0
@@ -3306,6 +3306,15 @@ static void intel_pmu_enable_event(struct perf_event *event)
 		intel_set_masks(event, idx);
 		static_call_cond(intel_pmu_enable_acr_event)(event);
 		static_call_cond(intel_pmu_enable_event_ext)(event);
+		/*
+		 * For self-reloaded ACR event, don't enable PMI since
+		 * HW won't set overflow bit in GLOBAL_STATUS. Otherwise,
+		 * the PMI would be recognized as a suspicious NMI.
+		 */
+		if (is_acr_self_reload_event(event))
+			hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT;
+		else if (!event->attr.precise_ip)
+			hwc->config |= ARCH_PERFMON_EVENTSEL_INT;

It seems weird to either clear or set the bit. You don't know the previous state of the bit here? I would assume it starts with zero?

It's hard and unsafe to trace the previous state. Generally speaking, the PMI bit would always be set by default at the initialization, then it would be cleared later if it's a PEBS or ACR self-reloaded event.

Quoted 10 lines

arch/x86/events/perf_event.h static inline bool is_acr_event_group(struct perf_event *event) · line 147

Quoted 9 lines
arch/x86/events/perf_event.h +8 -0
+static inline bool is_acr_self_reload_event(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (hwc->idx < 0)
+		return false;
+
+	return test_bit(hwc->idx, (unsigned long *)&hwc->config1);

Are you sure this doesn't conflict with some other non ACR usage of config1?

Yes, currently hw.config1 is only used to store ACR  event indices.

Thanks.

Quoted 3 lines

-Andi

#10 lore raw

Re: [Patch v2 2/4] perf/x86/intel: Disable PMI for self-reloaded ACR events

Quoted 3 lines
Quoted 1 line

Are you sure this doesn't conflict with some other non ACR usage of config1?

Yes, currently hw.config1 is only used to store ACR  event indices.

Thanks. Should probably rename the field to make that clear.

-Andi

author
#11 lore raw

Re: [Patch v2 2/4] perf/x86/intel: Disable PMI for self-reloaded ACR events

Quoted 3 lines · Andi Kleen
Quoted 2 lines
Quoted 1 line

Are you sure this doesn't conflict with some other non ACR usage of config1?

Yes, currently hw.config1 is only used to store ACR  event indices.

Thanks. Should probably rename the field to make that clear.

Yeah, would do. Thanks.

Quoted 3 lines

-Andi

author
#12 lore raw

Re: [Patch v2 2/4] perf/x86/intel: Disable PMI for self-reloaded ACR events

Quoted 5 lines · Dapeng
Quoted 3 lines · Andi Kleen
Quoted 2 lines
Quoted 1 line

Are you sure this doesn't conflict with some other non ACR usage of config1?

Yes, currently hw.config1 is only used to store ACR  event indices.

Thanks. Should probably rename the field to make that clear.

Yeah, would do. Thanks.

Just look the code again, the config1 is defined in hw_perf_event structure which is a generic structure used by all kinds of different architectures. Although currently it's only used to save the ACR events index mask by x86, it could still be used for other specific usages on other architectures in the future. So we'd better keep this generic name "config1" then.

Thanks.

Quoted 4 lines
Quoted 4 lines

-Andi

author
#13 lore raw

PATCH v2 3/4 perf/x86/intel: Enable auto counter reload for DMR

In reply to Dapeng Mi

Panther cove µarch starts to support auto counter reload (ACR), but the static_call intel_pmu_enable_acr_event() is not updated for the Panther Cove µarch used by DMR. It leads to the auto counter reload is not really enabled on DMR.

Update static_call intel_pmu_enable_acr_event() in intel_pmu_init_pnc().

Fixes d345b6bb8860 ("perf/x86/intel: Add core PMU support for DMR")

---

V2: New patch.

 arch/x86/events/intel/core.c | 1 +
 1 file changed, 1 insertion(+)
arch/x86/events/intel/core.c +1 -0
index 510b087c9e89..fa4073bf18fe 100644
@@ -7506,6 +7506,7 @@ static __always_inline void intel_pmu_init_pnc(struct pmu *pmu)
 	hybrid(pmu, event_constraints) = intel_pnc_event_constraints;
 	hybrid(pmu, pebs_constraints) = intel_pnc_pebs_event_constraints;
 	hybrid(pmu, extra_regs) = intel_pnc_extra_regs;
+	static_call_update(intel_pmu_enable_acr_event, intel_pmu_enable_acr);
 }
 
 static __always_inline void intel_pmu_init_skt(struct pmu *pmu)
Signature · 1 line
2.34.1
author
#14 lore raw

PATCH v2 4/4 perf/x86/intel: Consolidate MSR_IA32_PERF_CFG_C tracking

In reply to Dapeng Mi

Both Auto Counter Reload (ACR) and Architectural PEBS use the PERF_CFG_C MSRs to configure event behavior. Currently, the driver maintains two independent variables acr_cfg_c and cfg_c_val to cache the values intended for these MSRs.

Using separate variables to track a single hardware register state is error-prone and can lead to configuration conflicts. Consolidate the tracking into a single cfg_c_val variable to ensure a unified and consistent view of the PERF_CFG_C MSR state.

---

V2: New patch.

 arch/x86/events/intel/core.c | 13 +++++++------
 arch/x86/events/perf_event.h |  4 +---
 2 files changed, 8 insertions(+), 9 deletions(-)
arch/x86/events/intel/core.c +7 -6
index fa4073bf18fe..667917baf7f2 100644
@@ -3169,10 +3169,10 @@ static void intel_pmu_config_acr(int idx, u64 mask, u32 reload)
 		wrmsrl(msr_b + msr_offset, mask);
 		cpuc->acr_cfg_b[idx] = mask;
 	}
-	/* Only need to update the reload value when there is a valid config value. */
-	if (mask && cpuc->acr_cfg_c[idx] != reload) {
+	/* Only update CFG_C reload when ACR is actively enabled (mask != 0) */
+	if (mask && ((cpuc->cfg_c_val[idx] & ARCH_PEBS_RELOAD) != reload)) {
 		wrmsrl(msr_c + msr_offset, reload);
-		cpuc->acr_cfg_c[idx] = reload;
+		cpuc->cfg_c_val[idx] = reload;
 	}
 }
 
@@ -3198,14 +3198,15 @@ static void intel_pmu_enable_event_ext(struct perf_event *event)
 {
 	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
 	struct hw_perf_event *hwc = &event->hw;
-	union arch_pebs_index old, new;
-	struct arch_pebs_cap cap;
 	u64 ext = 0;
 
-	cap = hybrid(cpuc->pmu, arch_pebs_cap);
+	if (is_acr_event_group(event))
+		ext |= (-hwc->sample_period) & ARCH_PEBS_RELOAD;
 
 	if (event->attr.precise_ip) {
 		u64 pebs_data_cfg = intel_get_arch_pebs_data_config(event);
+		struct arch_pebs_cap cap = hybrid(cpuc->pmu, arch_pebs_cap);
+		union arch_pebs_index old, new;
 
 		ext |= ARCH_PEBS_EN;
 		if (hwc->flags & PERF_X86_EVENT_AUTO_RELOAD)
arch/x86/events/perf_event.h +1 -3
index 524668dcf4cc..40d6fe0afc4a 100644
@@ -322,10 +322,8 @@ struct cpu_hw_events {
 	u64			fixed_ctrl_val;
 	u64			active_fixed_ctrl_val;
 
-	/* Intel ACR configuration */
+	/* Intel ACR/arch-PEBS configuration */
 	u64			acr_cfg_b[X86_PMC_IDX_MAX];
-	u64			acr_cfg_c[X86_PMC_IDX_MAX];
-	/* Cached CFG_C values */
 	u64			cfg_c_val[X86_PMC_IDX_MAX];
 
 	/*
Signature · 1 line
2.34.1