mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 12:21:22 -05:00
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:
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user