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>
This commit is contained in:
Atish Patra
2025-09-09 00:03:24 -07:00
committed by Anup Patel
parent adffbd06d0
commit 880fcc329e
2 changed files with 68 additions and 55 deletions

View File

@@ -100,6 +100,7 @@ static unsigned int riscv_pmu_irq;
/* Cache the available counters in a bitmask */
static unsigned long cmask;
static int pmu_event_find_cache(u64 config);
struct sbi_pmu_event_data {
union {
union {
@@ -412,6 +413,71 @@ static bool pmu_sbi_ctr_is_fw(int cidx)
return (info->type == SBI_PMU_CTR_TYPE_FW) ? true : false;
}
int riscv_pmu_get_event_info(u32 type, u64 config, u64 *econfig)
{
int ret = -ENOENT;
switch (type) {
case PERF_TYPE_HARDWARE:
if (config >= PERF_COUNT_HW_MAX)
return -EINVAL;
ret = pmu_hw_event_map[config].event_idx;
break;
case PERF_TYPE_HW_CACHE:
ret = pmu_event_find_cache(config);
break;
case PERF_TYPE_RAW:
/*
* As per SBI v0.3 specification,
* -- the upper 16 bits must be unused for a hardware raw event.
* As per SBI v2.0 specification,
* -- the upper 8 bits must be unused for a hardware raw event.
* Bits 63:62 are used to distinguish between raw events
* 00 - Hardware raw event
* 10 - SBI firmware events
* 11 - Risc-V platform specific firmware event
*/
switch (config >> 62) {
case 0:
if (sbi_v3_available) {
/* Return error any bits [56-63] is set as it is not allowed by the spec */
if (!(config & ~RISCV_PMU_RAW_EVENT_V2_MASK)) {
if (econfig)
*econfig = config & RISCV_PMU_RAW_EVENT_V2_MASK;
ret = RISCV_PMU_RAW_EVENT_V2_IDX;
}
/* Return error any bits [48-63] is set as it is not allowed by the spec */
} else if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) {
if (econfig)
*econfig = config & RISCV_PMU_RAW_EVENT_MASK;
ret = RISCV_PMU_RAW_EVENT_IDX;
}
break;
case 2:
ret = (config & 0xFFFF) | (SBI_PMU_EVENT_TYPE_FW << 16);
break;
case 3:
/*
* For Risc-V platform specific firmware events
* Event code - 0xFFFF
* Event data - raw event encoding
*/
ret = SBI_PMU_EVENT_TYPE_FW << 16 | RISCV_PLAT_FW_EVENT;
if (econfig)
*econfig = config & RISCV_PMU_PLAT_FW_EVENT_MASK;
break;
default:
break;
}
break;
default:
break;
}
return ret;
}
EXPORT_SYMBOL_GPL(riscv_pmu_get_event_info);
/*
* Returns the counter width of a programmable counter and number of hardware
* 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)
{
u32 type = event->attr.type;
u64 config = event->attr.config;
int ret = -ENOENT;
/*
* 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)
*/
flush_work(&check_std_events_work);
switch (type) {
case PERF_TYPE_HARDWARE:
if (config >= PERF_COUNT_HW_MAX)
return -EINVAL;
ret = pmu_hw_event_map[event->attr.config].event_idx;
break;
case PERF_TYPE_HW_CACHE:
ret = pmu_event_find_cache(config);
break;
case PERF_TYPE_RAW:
/*
* As per SBI v0.3 specification,
* -- the upper 16 bits must be unused for a hardware raw event.
* As per SBI v2.0 specification,
* -- the upper 8 bits must be unused for a hardware raw event.
* Bits 63:62 are used to distinguish between raw events
* 00 - Hardware raw event
* 10 - SBI firmware events
* 11 - Risc-V platform specific firmware event
*/
switch (config >> 62) {
case 0:
if (sbi_v3_available) {
if (!(config & ~RISCV_PMU_RAW_EVENT_V2_MASK)) {
*econfig = config & RISCV_PMU_RAW_EVENT_V2_MASK;
ret = RISCV_PMU_RAW_EVENT_V2_IDX;
}
} else if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) {
*econfig = config & RISCV_PMU_RAW_EVENT_MASK;
ret = RISCV_PMU_RAW_EVENT_IDX;
}
break;
case 2:
ret = (config & 0xFFFF) | (SBI_PMU_EVENT_TYPE_FW << 16);
break;
case 3:
/*
* For Risc-V platform specific firmware events
* Event code - 0xFFFF
* Event data - raw event encoding
*/
ret = SBI_PMU_EVENT_TYPE_FW << 16 | RISCV_PLAT_FW_EVENT;
*econfig = config & RISCV_PMU_PLAT_FW_EVENT_MASK;
break;
default:
break;
}
break;
default:
break;
}
return ret;
return riscv_pmu_get_event_info(type, config, econfig);
}
static void pmu_sbi_snapshot_free(struct riscv_pmu *pmu)

View File

@@ -89,6 +89,7 @@ static inline void riscv_pmu_legacy_skip_init(void) {};
struct riscv_pmu *riscv_pmu_alloc(void);
#ifdef CONFIG_RISCV_PMU_SBI
int riscv_pmu_get_hpm_info(u32 *hw_ctr_width, u32 *num_hw_ctr);
int riscv_pmu_get_event_info(u32 type, u64 config, u64 *econfig);
#endif
#endif /* CONFIG_RISCV_PMU */