diff --git a/platform/generic/platform.c b/platform/generic/platform.c index 79d5230..0787d10 100644 --- a/platform/generic/platform.c +++ b/platform/generic/platform.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -184,6 +185,33 @@ static u64 generic_tlbr_flush_limit(void) return SBI_PLATFORM_TLB_RANGE_FLUSH_LIMIT_DEFAULT; } +static int generic_pmu_init(void) +{ + return fdt_pmu_setup(sbi_scratch_thishart_arg1_ptr()); +} + +static uint64_t generic_pmu_xlate_to_mhpmevent(uint32_t event_idx, + uint64_t data) +{ + uint64_t evt_val = 0; + + /* data is valid only for raw events and is equal to event selector */ + if (event_idx == SBI_PMU_EVENT_RAW_IDX) + evt_val = data; + else { + /** + * Generic platform follows the SBI specification recommendation + * i.e. zero extended event_idx is used as mhpmevent value for + * hardware general/cache events if platform does't define one. + */ + evt_val = fdt_pmu_get_select_value(event_idx); + if (!evt_val) + evt_val = (uint64_t)event_idx; + } + + return evt_val; +} + const struct sbi_platform_operations platform_ops = { .early_init = generic_early_init, .final_init = generic_final_init, @@ -195,6 +223,8 @@ const struct sbi_platform_operations platform_ops = { .irqchip_exit = fdt_irqchip_exit, .ipi_init = fdt_ipi_init, .ipi_exit = fdt_ipi_exit, + .pmu_init = generic_pmu_init, + .pmu_xlate_to_mhpmevent = generic_pmu_xlate_to_mhpmevent, .get_tlbr_flush_limit = generic_tlbr_flush_limit, .timer_init = fdt_timer_init, .timer_exit = fdt_timer_exit,