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.
Unified · Split
| @@ -100,6 +100,7 @@ static unsigned int riscv_pmu_irq; · 99 unmodified lines | ||
| 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 { |
| @@ -412,6 +413,71 @@ static bool pmu_sbi_ctr_is_fw(int cidx) · 306 unmodified lines | ||
| 412 | 413 | return (info->type == SBI_PMU_CTR_TYPE_FW) ? true : false; |
| 413 | 414 | } |
| 414 | 415 | |
| 416 | +int riscv_pmu_get_event_info(u32 type, u64 config, u64 *econfig) | |
| 417 | +{ | |
| 418 | + int ret = -ENOENT; | |
| 419 | + | |
| 420 | + switch (type) { | |
| 421 | + case PERF_TYPE_HARDWARE: | |
| 422 | + if (config >= PERF_COUNT_HW_MAX) | |
| 423 | + return -EINVAL; | |
| 424 | + ret = pmu_hw_event_map[config].event_idx; | |
| 425 | + break; | |
| 426 | + case PERF_TYPE_HW_CACHE: | |
| 427 | + ret = pmu_event_find_cache(config); | |
| 428 | + break; | |
| 429 | + case PERF_TYPE_RAW: | |
| 430 | + /* | |
| 431 | + * As per SBI v0.3 specification, | |
| 432 | + * -- the upper 16 bits must be unused for a hardware raw event. | |
| 433 | + * As per SBI v2.0 specification, | |
| 434 | + * -- the upper 8 bits must be unused for a hardware raw event. | |
| 435 | + * Bits 63:62 are used to distinguish between raw events | |
| 436 | + * 00 - Hardware raw event | |
| 437 | + * 10 - SBI firmware events | |
| 438 | + * 11 - Risc-V platform specific firmware event | |
| 439 | + */ | |
| 440 | + switch (config >> 62) { | |
| 441 | + case 0: | |
| 442 | + if (sbi_v3_available) { | |
| 443 | + /* Return error any bits [56-63] is set as it is not allowed by the spec */ | |
| 444 | + if (!(config & ~RISCV_PMU_RAW_EVENT_V2_MASK)) { | |
| 445 | + if (econfig) | |
| 446 | + *econfig = config & RISCV_PMU_RAW_EVENT_V2_MASK; | |
| 447 | + ret = RISCV_PMU_RAW_EVENT_V2_IDX; | |
| 448 | + } | |
| 449 | + /* Return error any bits [48-63] is set as it is not allowed by the spec */ | |
| 450 | + } else if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) { | |
| 451 | + if (econfig) | |
| 452 | + *econfig = config & RISCV_PMU_RAW_EVENT_MASK; | |
| 453 | + ret = RISCV_PMU_RAW_EVENT_IDX; | |
| 454 | + } | |
| 455 | + break; | |
| 456 | + case 2: | |
| 457 | + ret = (config & 0xFFFF) | (SBI_PMU_EVENT_TYPE_FW << 16); | |
| 458 | + break; | |
| 459 | + case 3: | |
| 460 | + /* | |
| 461 | + * For Risc-V platform specific firmware events | |
| 462 | + * Event code - 0xFFFF | |
| 463 | + * Event data - raw event encoding | |
| 464 | + */ | |
| 465 | + ret = SBI_PMU_EVENT_TYPE_FW << 16 | RISCV_PLAT_FW_EVENT; | |
| 466 | + if (econfig) | |
| 467 | + *econfig = config & RISCV_PMU_PLAT_FW_EVENT_MASK; | |
| 468 | + break; | |
| 469 | + default: | |
| 470 | + break; | |
| 471 | + } | |
| 472 | + break; | |
| 473 | + default: | |
| 474 | + break; | |
| 475 | + } | |
| 476 | + | |
| 477 | + return ret; | |
| 478 | +} | |
| 479 | +EXPORT_SYMBOL_GPL(riscv_pmu_get_event_info); | |
| 480 | + | |
| 415 | 481 | /* |
| 416 | 482 | * Returns the counter width of a programmable counter and number of hardware |
| 417 | 483 | * counters. As we don't support heterogeneous CPUs yet, it is okay to just |
| @@ -577,7 +643,6 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig) · 159 unmodified lines | ||
| 577 | 643 | { |
| 578 | 644 | u32 type = event->attr.type; |
| 579 | 645 | u64 config = event->attr.config; |
| 580 | − int ret = -ENOENT; | |
| 581 | 646 | |
| 582 | 647 | /* |
| 583 | 648 | * Ensure we are finished checking standard hardware events for |
| @@ -585,60 +650,7 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig) · 1 unmodified line | ||
| 585 | 650 | */ |
| 586 | 651 | flush_work(&check_std_events_work); |
| 587 | 652 | |
| 588 | − switch (type) { | |
| 589 | − case PERF_TYPE_HARDWARE: | |
| 590 | − if (config >= PERF_COUNT_HW_MAX) | |
| 591 | − return -EINVAL; | |
| 592 | − ret = pmu_hw_event_map[event->attr.config].event_idx; | |
| 593 | − break; | |
| 594 | − case PERF_TYPE_HW_CACHE: | |
| 595 | − ret = pmu_event_find_cache(config); | |
| 596 | − break; | |
| 597 | − case PERF_TYPE_RAW: | |
| 598 | − /* | |
| 599 | − * As per SBI v0.3 specification, | |
| 600 | − * -- the upper 16 bits must be unused for a hardware raw event. | |
| 601 | − * As per SBI v2.0 specification, | |
| 602 | − * -- the upper 8 bits must be unused for a hardware raw event. | |
| 603 | − * Bits 63:62 are used to distinguish between raw events | |
| 604 | − * 00 - Hardware raw event | |
| 605 | − * 10 - SBI firmware events | |
| 606 | − * 11 - Risc-V platform specific firmware event | |
| 607 | − */ | |
| 608 | − | |
| 609 | − switch (config >> 62) { | |
| 610 | − case 0: | |
| 611 | − if (sbi_v3_available) { | |
| 612 | − if (!(config & ~RISCV_PMU_RAW_EVENT_V2_MASK)) { | |
| 613 | − *econfig = config & RISCV_PMU_RAW_EVENT_V2_MASK; | |
| 614 | − ret = RISCV_PMU_RAW_EVENT_V2_IDX; | |
| 615 | − } | |
| 616 | − } else if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) { | |
| 617 | − *econfig = config & RISCV_PMU_RAW_EVENT_MASK; | |
| 618 | − ret = RISCV_PMU_RAW_EVENT_IDX; | |
| 619 | − } | |
| 620 | − break; | |
| 621 | − case 2: | |
| 622 | − ret = (config & 0xFFFF) | (SBI_PMU_EVENT_TYPE_FW << 16); | |
| 623 | − break; | |
| 624 | − case 3: | |
| 625 | − /* | |
| 626 | − * For Risc-V platform specific firmware events | |
| 627 | − * Event code - 0xFFFF | |
| 628 | − * Event data - raw event encoding | |
| 629 | − */ | |
| 630 | − ret = SBI_PMU_EVENT_TYPE_FW << 16 | RISCV_PLAT_FW_EVENT; | |
| 631 | − *econfig = config & RISCV_PMU_PLAT_FW_EVENT_MASK; | |
| 632 | − break; | |
| 633 | − default: | |
| 634 | − break; | |
| 635 | − } | |
| 636 | − break; | |
| 637 | − default: | |
| 638 | − break; | |
| 639 | − } | |
| 640 | − | |
| 641 | − return ret; | |
| 653 | + return riscv_pmu_get_event_info(type, config, econfig); | |
| 642 | 654 | } |
| 643 | 655 | |
| 644 | 656 | static void pmu_sbi_snapshot_free(struct riscv_pmu *pmu) |
| @@ -89,6 +89,7 @@ static inline void riscv_pmu_legacy_skip_init(void) {}; · 88 unmodified lines | ||
| 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 */ |