[PATCH v8 13/22] RISC-V: perf: Add a mechanism to defined legacy event encoding

Yicong Yang yang.yicong at picoheart.com
Tue Jul 7 00:51:09 PDT 2026


On 7/1/26 4:47 PM, Atish Patra wrote:
> From: Atish Patra <atishp at rivosinc.com>
> 
> RISC-V ISA doesn't define any standard event encodings or specify
> any event to counter mapping. Thus, event encoding information
> and corresponding counter mapping fot those events needs to be
> provided in the driver for each vendor.
> 
> Add a framework to support that. The individual platform events
> will be added later.
> 
> Signed-off-by: Atish Patra <atishp at rivosinc.com>
> ---
>  drivers/perf/riscv_pmu_sbi.c | 70 +++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 69 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
> index c20f1e33c65d..2568c6808f5d 100644
> --- a/drivers/perf/riscv_pmu_sbi.c
> +++ b/drivers/perf/riscv_pmu_sbi.c
> @@ -10,6 +10,7 @@
>  
>  #define pr_fmt(fmt) "riscv-pmu-sbi: " fmt
>  
> +#include <linux/limits.h>
>  #include <linux/mod_devicetable.h>
>  #include <linux/perf/riscv_pmu.h>
>  #include <linux/platform_device.h>
> @@ -379,6 +380,71 @@ static int pmu_sbi_check_event_info(void)
>  	return result;
>  }
>  
> +/*
> + * Vendor specific PMU events.
> + */
> +struct riscv_pmu_event {
> +	u64 event_id;
> +	u32 counter_mask;

could we name it as counterid_mask to match to the PMU format
name (introduced in patch 16/22)?

thanks.

> +};
> +
> +#define HW_OP_UNSUPPORTED		U64_MAX
> +#define CACHE_OP_UNSUPPORTED		U64_MAX
> +
> +#define PERF_MAP_ALL_UNSUPPORTED					\
> +	[0 ... PERF_COUNT_HW_MAX - 1] = {HW_OP_UNSUPPORTED, 0x0}
> +
> +#define PERF_CACHE_MAP_ALL_UNSUPPORTED					\
> +[0 ... PERF_COUNT_HW_CACHE_MAX - 1] = {					\
> +	[0 ... PERF_COUNT_HW_CACHE_OP_MAX - 1] = {			\
> +		[0 ... PERF_COUNT_HW_CACHE_RESULT_MAX - 1] = {		\
> +			CACHE_OP_UNSUPPORTED, 0x0			\
> +		},							\
> +	},								\
> +}
> +
> +struct riscv_vendor_pmu_events {
> +	unsigned long vendorid;
> +	unsigned long archid;
> +	unsigned long implid;
> +	const struct riscv_pmu_event *hw_event_map;
> +	const struct riscv_pmu_event (*cache_event_map)[PERF_COUNT_HW_CACHE_OP_MAX]
> +						       [PERF_COUNT_HW_CACHE_RESULT_MAX];
> +};
> +
> +#define RISCV_VENDOR_PMU_EVENTS(_vendorid, _archid, _implid, _hw_event_map, _cache_event_map) \
> +	{ .vendorid = _vendorid, .archid = _archid, .implid = _implid, \
> +	  .hw_event_map = _hw_event_map, .cache_event_map = _cache_event_map },
> +
> +static struct riscv_vendor_pmu_events pmu_vendor_events_table[] = {
> +};
> +
> +static const struct riscv_pmu_event *current_pmu_hw_event_map;
> +static const struct riscv_pmu_event (*current_pmu_cache_event_map)[PERF_COUNT_HW_CACHE_OP_MAX]
> +							   [PERF_COUNT_HW_CACHE_RESULT_MAX];
> +
> +static void __init rvpmu_vendor_register_events(void)
> +{
> +	int cpu = raw_smp_processor_id();
> +	unsigned long vendor_id = riscv_cached_mvendorid(cpu);
> +	unsigned long impl_id = riscv_cached_mimpid(cpu);
> +	unsigned long arch_id = riscv_cached_marchid(cpu);
> +
> +	for (int i = 0; i < ARRAY_SIZE(pmu_vendor_events_table); i++) {
> +		if (pmu_vendor_events_table[i].vendorid == vendor_id &&
> +		    pmu_vendor_events_table[i].implid == impl_id &&
> +		    pmu_vendor_events_table[i].archid == arch_id) {
> +			current_pmu_hw_event_map = pmu_vendor_events_table[i].hw_event_map;
> +			current_pmu_cache_event_map = pmu_vendor_events_table[i].cache_event_map;
> +			break;
> +		}
> +	}
> +
> +	if (!current_pmu_hw_event_map || !current_pmu_cache_event_map) {
> +		pr_info("No default PMU events found\n");
> +	}
> +}
> +
>  static void rvpmu_sbi_check_event(struct sbi_pmu_event_data *edata)
>  {
>  	struct sbiret ret;
> @@ -1670,8 +1736,10 @@ static int __init rvpmu_devinit(void)
>  	 */
>  	if (riscv_isa_extension_available(NULL, SSCCFG) &&
>  	    riscv_isa_extension_available(NULL, SMCDELEG) &&
> -	    riscv_isa_extension_available(NULL, SSCSRIND))
> +	    riscv_isa_extension_available(NULL, SSCSRIND)) {
>  		static_branch_enable(&riscv_pmu_cdeleg_available);
> +		rvpmu_vendor_register_events();
> +	}
>  
>  	if (!(riscv_pmu_sbi_available_boot() || riscv_pmu_cdeleg_available_boot()))
>  		return 0;



More information about the linux-arm-kernel mailing list