@@ -414,6 +414,65 @@ 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 v3.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 (econfig)
+ *econfig = config & RISCV_PMU_RAW_EVENT_V2_MASK;
+ ret = RISCV_PMU_RAW_EVENT_V2_IDX;
+ } else {
+ 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;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(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
@@ -579,7 +638,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;
/*
* Ensure we are finished checking standard hardware events for
@@ -587,56 +645,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 v3.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) {
- *econfig = config & RISCV_PMU_RAW_EVENT_V2_MASK;
- ret = RISCV_PMU_RAW_EVENT_V2_IDX;
- } else {
- *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;
- }
- break;
- default:
- ret = -ENOENT;
- break;
- }
-
- return ret;
+ return riscv_pmu_get_event_info(type, config, econfig);
}
static void pmu_sbi_snapshot_free(struct riscv_pmu *pmu)
@@ -91,6 +91,8 @@ struct riscv_pmu *riscv_pmu_alloc(void);
int riscv_pmu_get_hpm_info(u32 *hw_ctr_width, u32 *num_hw_ctr);
#endif
+int riscv_pmu_get_event_info(u32 type, u64 config, u64 *econfig);
+
#endif /* CONFIG_RISCV_PMU */
#endif /* _RISCV_PMU_H */
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> --- drivers/perf/riscv_pmu_sbi.c | 111 ++++++++++++++++++++++------------------- include/linux/perf/riscv_pmu.h | 2 + 2 files changed, 62 insertions(+), 51 deletions(-)