]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drivers/perf: riscv: Export PMU event info function
authorAtish Patra <atishp@rivosinc.com>
Tue, 9 Sep 2025 07:03:24 +0000 (00:03 -0700)
committerAnup Patel <anup@brainfault.org>
Tue, 16 Sep 2025 06:19:31 +0000 (11:49 +0530)
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>
drivers/perf/riscv_pmu_sbi.c
include/linux/perf/riscv_pmu.h

index a6c479f853e1ad8e992428e6b8967ff2dbd5f9c2..0392900d828eeac9b0e5bc79cde301ab69c83a20 100644 (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)
index 701974639ff2ca12c00d93fa2c4989d7520833ae..f82a28040594bd872ffc17e281f463c00a97d0b4 100644 (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 */