[RESEND PATCH v4 02/11] perf/cxl: Clear stale event fields before reprogramming a counter
Dave Jiang <[email protected]> Wed, 5 Aug 2026 08:59:02 -0700
| Newsgroups | org.kernel.vger.linux-cxl,org.kernel.vger.linux-perf-users |
|---|---|
| Message-ID | <[email protected]> |
cxl_pmu_event_start() ORs the event group id, event mask, edge and invert
selections into a configurable counter's config register without clearing
them first, and cxl_pmu_event_stop() leaves them set. Reuse the counter for
another event and the new selection lands on top of the old one, so the
counter counts the wrong events with stale edge and invert behaviour.
Use FIELD_MODIFY() so each field is replaced rather than accumulated.
Fixes: 5d7107c72796 ("perf: CXL Performance Monitoring Unit driver")
Reported-by: [email protected]
Closes: https://sashiko.dev/#/patchset/[email protected]?part=1
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Dave Jiang <[email protected]>
---
drivers/perf/cxl_pmu.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c
index ff01b658e1b4..b16e2e4090a3 100644
--- a/drivers/perf/cxl_pmu.c
+++ b/drivers/perf/cxl_pmu.c
@@ -646,17 +646,17 @@ static void cxl_pmu_event_start(struct perf_event *event, int flags)
cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_INT_ON_OVRFLW, 1);
cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_FREEZE_ON_OVRFLW, 1);
cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_ENABLE, 1);
- cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EDGE,
- cxl_pmu_config1_get_edge(event) ? 1 : 0);
- cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_INVERT,
- cxl_pmu_config1_get_invert(event) ? 1 : 0);
+ FIELD_MODIFY(CXL_PMU_COUNTER_CFG_EDGE, &cfg,
+ cxl_pmu_config1_get_edge(event) ? 1 : 0);
+ FIELD_MODIFY(CXL_PMU_COUNTER_CFG_INVERT, &cfg,
+ cxl_pmu_config1_get_invert(event) ? 1 : 0);
/* Fixed purpose counters have next two fields RO */
if (test_bit(hwc->idx, info->conf_counter_bm)) {
- cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EVENT_GRP_ID_IDX_MSK,
- hwc->event_base);
- cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EVENTS_MSK,
- cxl_pmu_config_get_mask(event));
+ FIELD_MODIFY(CXL_PMU_COUNTER_CFG_EVENT_GRP_ID_IDX_MSK, &cfg,
+ hwc->event_base);
+ FIELD_MODIFY(CXL_PMU_COUNTER_CFG_EVENTS_MSK, &cfg,
+ cxl_pmu_config_get_mask(event));
}
cfg &= ~CXL_PMU_COUNTER_CFG_THRESHOLD_MSK;
/*
--
2.54.0