Re: [PATCH v2 2/9] perf/cxl: Clear stale event fields before reprogramming a counter

Dave Jiang <[email protected]> Thu, 30 Jul 2026 08:45:05 -0700
Newsgroups org.kernel.vger.linux-cxl,org.kernel.vger.linux-perf-users
Message-ID <[email protected]>

On 7/29/26 3:25 PM, Jonathan Cameron wrote:
> On Wed, 29 Jul 2026 07:55:48 -0700
> Dave Jiang <[email protected]> wrote:
> 
>> cxl_pmu_event_start() ORs the event group id, event mask, edge and invert
>> selections into a configurable counter's config register without clearing
>> those fields first, and cxl_pmu_event_stop() leaves them set. Reusing a
>> counter for another event therefore ORs the new selection onto the old,
>> counting the wrong events with stale edge/invert behaviour.
>>
>> Clear EVENT_GRP_ID_IDX, EVENTS, EDGE and INVERT before applying the new
>> values.
> 
> Maybe use FIELD_MODIFY() instead of mask then fill?

Will do

DJ

> 
> Otherwise LGTM.
> 
>>
>> 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 | 3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c
>> index e77c0650a7eb..3138514157cd 100644
>> --- a/drivers/perf/cxl_pmu.c
>> +++ b/drivers/perf/cxl_pmu.c
>> @@ -641,6 +641,7 @@ static void cxl_pmu_event_start(struct perf_event *event, int flags)
>>  	}
>>  
>>  	cfg = readq(base + CXL_PMU_COUNTER_CFG_REG(hwc->idx));
>> +	cfg &= ~(CXL_PMU_COUNTER_CFG_EDGE | CXL_PMU_COUNTER_CFG_INVERT);
>>  	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);
>> @@ -651,6 +652,8 @@ static void cxl_pmu_event_start(struct perf_event *event, int flags)
>>  
>>  	/* Fixed purpose counters have next two fields RO */
>>  	if (test_bit(hwc->idx, info->conf_counter_bm)) {
>> +		cfg &= ~(CXL_PMU_COUNTER_CFG_EVENT_GRP_ID_IDX_MSK |
>> +			 CXL_PMU_COUNTER_CFG_EVENTS_MSK);
>>  		cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EVENT_GRP_ID_IDX_MSK,
>>  				  hwc->event_base);
>>  		cfg |= FIELD_PREP(CXL_PMU_COUNTER_CFG_EVENTS_MSK,
>