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 | /* Cache the available counters in a bitmask */ | 100 | /* Cache the available counters in a bitmask */ |
| 101 | static unsigned long cmask; | 101 | static unsigned long cmask; |
| 102 | 102 | ||
| 103 | static int pmu_event_find_cache(u64 config); | ||
| 103 | struct sbi_pmu_event_data { | 104 | struct sbi_pmu_event_data { |
| 104 | union { | 105 | union { |
| 105 | union { | 106 | union { |
| @@ -412,6 +413,71 @@ static bool pmu_sbi_ctr_is_fw(int cidx) · 306 unmodified lines | |||
| 412 | return (info->type == SBI_PMU_CTR_TYPE_FW) ? true : false; | 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 | * Returns the counter width of a programmable counter and number of hardware | 482 | * Returns the counter width of a programmable counter and number of hardware |
| 417 | * counters. As we don't support heterogeneous CPUs yet, it is okay to just | 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 | u32 type = event->attr.type; | 644 | u32 type = event->attr.type; |
| 579 | u64 config = event->attr.config; | 645 | u64 config = event->attr.config; |
| 580 | int ret = -ENOENT; | ||
| 581 | 646 | ||
| 582 | /* | 647 | /* |
| 583 | * Ensure we are finished checking standard hardware events for | 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 | flush_work(&check_std_events_work); | 651 | flush_work(&check_std_events_work); |
| 587 | 652 | ||
| 588 | switch (type) { | 653 | return riscv_pmu_get_event_info(type, config, econfig); |
| 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; | ||
| 642 | } | 654 | } |
| 643 | 655 | ||
| 644 | static void pmu_sbi_snapshot_free(struct riscv_pmu *pmu) | 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 | struct riscv_pmu *riscv_pmu_alloc(void); | 89 | struct riscv_pmu *riscv_pmu_alloc(void); |
| 90 | #ifdef CONFIG_RISCV_PMU_SBI | 90 | #ifdef CONFIG_RISCV_PMU_SBI |
| 91 | int riscv_pmu_get_hpm_info(u32 *hw_ctr_width, u32 *num_hw_ctr); | 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 | #endif | 93 | #endif |
| 93 | 94 | ||
| 94 | #endif /* CONFIG_RISCV_PMU */ | 95 | #endif /* CONFIG_RISCV_PMU */ |