Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drivers/perf: apple_m1: Refactor event select/filter configuration

Supporting guest mode events will necessitate programming two event
filters. Prepare by splitting up the programming of the event selector +
event filter into separate headers.

Opportunistically replace RMW patterns with sysreg_clear_set_s().

Tested-by: Janne Grunau <j@jannau.net>
Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250305202641.428114-2-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>

+32 -20
+32 -20
drivers/perf/apple_m1_cpu_pmu.c
··· 327 327 __m1_pmu_enable_counter_interrupt(index, false); 328 328 } 329 329 330 - static void m1_pmu_configure_counter(unsigned int index, u8 event, 331 - bool user, bool kernel) 330 + static void __m1_pmu_configure_event_filter(unsigned int index, bool user, 331 + bool kernel) 332 332 { 333 - u64 val, user_bit, kernel_bit; 334 - int shift; 333 + u64 clear, set, user_bit, kernel_bit; 335 334 336 335 switch (index) { 337 336 case 0 ... 7: ··· 345 346 BUG(); 346 347 } 347 348 348 - val = read_sysreg_s(SYS_IMP_APL_PMCR1_EL1); 349 - 349 + clear = set = 0; 350 350 if (user) 351 - val |= user_bit; 351 + set |= user_bit; 352 352 else 353 - val &= ~user_bit; 353 + clear |= user_bit; 354 354 355 355 if (kernel) 356 - val |= kernel_bit; 356 + set |= kernel_bit; 357 357 else 358 - val &= ~kernel_bit; 358 + clear |= kernel_bit; 359 359 360 - write_sysreg_s(val, SYS_IMP_APL_PMCR1_EL1); 360 + sysreg_clear_set_s(SYS_IMP_APL_PMCR1_EL1, clear, set); 361 + } 362 + 363 + static void __m1_pmu_configure_eventsel(unsigned int index, u8 event) 364 + { 365 + u64 clear = 0, set = 0; 366 + int shift; 361 367 362 368 /* 363 369 * Counters 0 and 1 have fixed events. For anything else, ··· 375 371 break; 376 372 case 2 ... 5: 377 373 shift = (index - 2) * 8; 378 - val = read_sysreg_s(SYS_IMP_APL_PMESR0_EL1); 379 - val &= ~((u64)0xff << shift); 380 - val |= (u64)event << shift; 381 - write_sysreg_s(val, SYS_IMP_APL_PMESR0_EL1); 374 + clear |= (u64)0xff << shift; 375 + set |= (u64)event << shift; 376 + sysreg_clear_set_s(SYS_IMP_APL_PMESR0_EL1, clear, set); 382 377 break; 383 378 case 6 ... 9: 384 379 shift = (index - 6) * 8; 385 - val = read_sysreg_s(SYS_IMP_APL_PMESR1_EL1); 386 - val &= ~((u64)0xff << shift); 387 - val |= (u64)event << shift; 388 - write_sysreg_s(val, SYS_IMP_APL_PMESR1_EL1); 380 + clear |= (u64)0xff << shift; 381 + set |= (u64)event << shift; 382 + sysreg_clear_set_s(SYS_IMP_APL_PMESR1_EL1, clear, set); 389 383 break; 390 384 } 385 + } 386 + 387 + static void m1_pmu_configure_counter(unsigned int index, unsigned long config_base) 388 + { 389 + bool kernel = config_base & M1_PMU_CFG_COUNT_KERNEL; 390 + bool user = config_base & M1_PMU_CFG_COUNT_USER; 391 + u8 evt = config_base & M1_PMU_CFG_EVENT; 392 + 393 + __m1_pmu_configure_event_filter(index, user, kernel); 394 + __m1_pmu_configure_eventsel(index, evt); 391 395 } 392 396 393 397 /* arm_pmu backend */ ··· 412 400 m1_pmu_disable_counter(event->hw.idx); 413 401 isb(); 414 402 415 - m1_pmu_configure_counter(event->hw.idx, evt, user, kernel); 403 + m1_pmu_configure_counter(event->hw.idx, event->hw.config_base); 416 404 m1_pmu_enable_counter(event->hw.idx); 417 405 m1_pmu_enable_counter_interrupt(event->hw.idx); 418 406 isb();