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

drivers/perf: riscv: Export PMU event info function

The event mapping function can be used in event info function to find out
the corresponding SBI PMU event encoding during the get_event_info function
as well. Refactor and export it so that it can be invoked from kvm and
internal driver.

Signed-off-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Acked-by: Paul Walmsley <pjw@kernel.org>
Link: https://lore.kernel.org/r/20250909-pmu_event_info-v6-5-d8f80cacb884@rivosinc.com
Signed-off-by: Anup Patel <anup@brainfault.org>

authored by

Atish Patra and committed by
Anup Patel
880fcc32 adffbd06

+68 -55
+67 -55
drivers/perf/riscv_pmu_sbi.c
··· 100 100 /* Cache the available counters in a bitmask */ 101 101 static unsigned long cmask; 102 102 103 + static int pmu_event_find_cache(u64 config); 103 104 struct sbi_pmu_event_data { 104 105 union { 105 106 union { ··· 413 412 return (info->type == SBI_PMU_CTR_TYPE_FW) ? true : false; 414 413 } 415 414 415 + int riscv_pmu_get_event_info(u32 type, u64 config, u64 *econfig) 416 + { 417 + int ret = -ENOENT; 418 + 419 + switch (type) { 420 + case PERF_TYPE_HARDWARE: 421 + if (config >= PERF_COUNT_HW_MAX) 422 + return -EINVAL; 423 + ret = pmu_hw_event_map[config].event_idx; 424 + break; 425 + case PERF_TYPE_HW_CACHE: 426 + ret = pmu_event_find_cache(config); 427 + break; 428 + case PERF_TYPE_RAW: 429 + /* 430 + * As per SBI v0.3 specification, 431 + * -- the upper 16 bits must be unused for a hardware raw event. 432 + * As per SBI v2.0 specification, 433 + * -- the upper 8 bits must be unused for a hardware raw event. 434 + * Bits 63:62 are used to distinguish between raw events 435 + * 00 - Hardware raw event 436 + * 10 - SBI firmware events 437 + * 11 - Risc-V platform specific firmware event 438 + */ 439 + switch (config >> 62) { 440 + case 0: 441 + if (sbi_v3_available) { 442 + /* Return error any bits [56-63] is set as it is not allowed by the spec */ 443 + if (!(config & ~RISCV_PMU_RAW_EVENT_V2_MASK)) { 444 + if (econfig) 445 + *econfig = config & RISCV_PMU_RAW_EVENT_V2_MASK; 446 + ret = RISCV_PMU_RAW_EVENT_V2_IDX; 447 + } 448 + /* Return error any bits [48-63] is set as it is not allowed by the spec */ 449 + } else if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) { 450 + if (econfig) 451 + *econfig = config & RISCV_PMU_RAW_EVENT_MASK; 452 + ret = RISCV_PMU_RAW_EVENT_IDX; 453 + } 454 + break; 455 + case 2: 456 + ret = (config & 0xFFFF) | (SBI_PMU_EVENT_TYPE_FW << 16); 457 + break; 458 + case 3: 459 + /* 460 + * For Risc-V platform specific firmware events 461 + * Event code - 0xFFFF 462 + * Event data - raw event encoding 463 + */ 464 + ret = SBI_PMU_EVENT_TYPE_FW << 16 | RISCV_PLAT_FW_EVENT; 465 + if (econfig) 466 + *econfig = config & RISCV_PMU_PLAT_FW_EVENT_MASK; 467 + break; 468 + default: 469 + break; 470 + } 471 + break; 472 + default: 473 + break; 474 + } 475 + 476 + return ret; 477 + } 478 + EXPORT_SYMBOL_GPL(riscv_pmu_get_event_info); 479 + 416 480 /* 417 481 * Returns the counter width of a programmable counter and number of hardware 418 482 * counters. As we don't support heterogeneous CPUs yet, it is okay to just ··· 643 577 { 644 578 u32 type = event->attr.type; 645 579 u64 config = event->attr.config; 646 - int ret = -ENOENT; 647 580 648 581 /* 649 582 * Ensure we are finished checking standard hardware events for ··· 650 585 */ 651 586 flush_work(&check_std_events_work); 652 587 653 - switch (type) { 654 - case PERF_TYPE_HARDWARE: 655 - if (config >= PERF_COUNT_HW_MAX) 656 - return -EINVAL; 657 - ret = pmu_hw_event_map[event->attr.config].event_idx; 658 - break; 659 - case PERF_TYPE_HW_CACHE: 660 - ret = pmu_event_find_cache(config); 661 - break; 662 - case PERF_TYPE_RAW: 663 - /* 664 - * As per SBI v0.3 specification, 665 - * -- the upper 16 bits must be unused for a hardware raw event. 666 - * As per SBI v2.0 specification, 667 - * -- the upper 8 bits must be unused for a hardware raw event. 668 - * Bits 63:62 are used to distinguish between raw events 669 - * 00 - Hardware raw event 670 - * 10 - SBI firmware events 671 - * 11 - Risc-V platform specific firmware event 672 - */ 673 - 674 - switch (config >> 62) { 675 - case 0: 676 - if (sbi_v3_available) { 677 - if (!(config & ~RISCV_PMU_RAW_EVENT_V2_MASK)) { 678 - *econfig = config & RISCV_PMU_RAW_EVENT_V2_MASK; 679 - ret = RISCV_PMU_RAW_EVENT_V2_IDX; 680 - } 681 - } else if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) { 682 - *econfig = config & RISCV_PMU_RAW_EVENT_MASK; 683 - ret = RISCV_PMU_RAW_EVENT_IDX; 684 - } 685 - break; 686 - case 2: 687 - ret = (config & 0xFFFF) | (SBI_PMU_EVENT_TYPE_FW << 16); 688 - break; 689 - case 3: 690 - /* 691 - * For Risc-V platform specific firmware events 692 - * Event code - 0xFFFF 693 - * Event data - raw event encoding 694 - */ 695 - ret = SBI_PMU_EVENT_TYPE_FW << 16 | RISCV_PLAT_FW_EVENT; 696 - *econfig = config & RISCV_PMU_PLAT_FW_EVENT_MASK; 697 - break; 698 - default: 699 - break; 700 - } 701 - break; 702 - default: 703 - break; 704 - } 705 - 706 - return ret; 588 + return riscv_pmu_get_event_info(type, config, econfig); 707 589 } 708 590 709 591 static void pmu_sbi_snapshot_free(struct riscv_pmu *pmu)
+1
include/linux/perf/riscv_pmu.h
··· 89 89 struct riscv_pmu *riscv_pmu_alloc(void); 90 90 #ifdef CONFIG_RISCV_PMU_SBI 91 91 int riscv_pmu_get_hpm_info(u32 *hw_ctr_width, u32 *num_hw_ctr); 92 + int riscv_pmu_get_event_info(u32 type, u64 config, u64 *econfig); 92 93 #endif 93 94 94 95 #endif /* CONFIG_RISCV_PMU */