[PATCH v5 15/21] RISC-V: perf: Skip PMU SBI extension when not implemented

From: Atish Patra
Date: Thu Mar 27 2025 - 15:42:48 EST


From: Charlie Jenkins <charlie@xxxxxxxxxxxx>

When the PMU SBI extension is not implemented, sbi_v2_available should
not be set to true. The SBI implementation for counter config matching
and firmware counter read should also be skipped when the SBI extension
is not implemented.

Signed-off-by: Atish Patra <atishp@xxxxxxxxxxxx>
Signed-off-by: Charlie Jenkins <charlie@xxxxxxxxxxxx>
---
drivers/perf/riscv_pmu_dev.c | 38 +++++++++++++++++++++++---------------
1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/drivers/perf/riscv_pmu_dev.c b/drivers/perf/riscv_pmu_dev.c
index 7c4a1ef15866..d1cc8310423f 100644
--- a/drivers/perf/riscv_pmu_dev.c
+++ b/drivers/perf/riscv_pmu_dev.c
@@ -417,18 +417,22 @@ static void rvpmu_sbi_check_event(struct sbi_pmu_event_data *edata)
}
}

-static void rvpmu_sbi_check_std_events(struct work_struct *work)
+static void rvpmu_check_std_events(struct work_struct *work)
{
- for (int i = 0; i < ARRAY_SIZE(pmu_hw_event_sbi_map); i++)
- rvpmu_sbi_check_event(&pmu_hw_event_sbi_map[i]);
-
- for (int i = 0; i < ARRAY_SIZE(pmu_cache_event_sbi_map); i++)
- for (int j = 0; j < ARRAY_SIZE(pmu_cache_event_sbi_map[i]); j++)
- for (int k = 0; k < ARRAY_SIZE(pmu_cache_event_sbi_map[i][j]); k++)
- rvpmu_sbi_check_event(&pmu_cache_event_sbi_map[i][j][k]);
+ if (riscv_pmu_sbi_available()) {
+ for (int i = 0; i < ARRAY_SIZE(pmu_hw_event_sbi_map); i++)
+ rvpmu_sbi_check_event(&pmu_hw_event_sbi_map[i]);
+
+ for (int i = 0; i < ARRAY_SIZE(pmu_cache_event_sbi_map); i++)
+ for (int j = 0; j < ARRAY_SIZE(pmu_cache_event_sbi_map[i]); j++)
+ for (int k = 0; k < ARRAY_SIZE(pmu_cache_event_sbi_map[i][j]); k++)
+ rvpmu_sbi_check_event(&pmu_cache_event_sbi_map[i][j][k]);
+ } else {
+ DO_ONCE_LITE_IF(1, pr_err, "Boot time config matching not required for smcdeleg\n");
+ }
}

-static DECLARE_WORK(check_std_events_work, rvpmu_sbi_check_std_events);
+static DECLARE_WORK(check_std_events_work, rvpmu_check_std_events);

static ssize_t rvpmu_format_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -556,6 +560,9 @@ static int rvpmu_sbi_ctr_get_idx(struct perf_event *event)

cflags = rvpmu_sbi_get_filter_flags(event);

+ if (!riscv_pmu_sbi_available())
+ return -ENOENT;
+
/*
* In legacy mode, we have to force the fixed counters for those events
* but not in the user access mode as we want to use the other counters
@@ -878,7 +885,7 @@ static u64 rvpmu_ctr_read(struct perf_event *event)
return val;
}

- if (pmu_sbi_is_fw_event(event)) {
+ if (pmu_sbi_is_fw_event(event) && riscv_pmu_sbi_available()) {
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_FW_READ,
hwc->idx, 0, 0, 0, 0, 0);
if (ret.error)
@@ -1945,12 +1952,13 @@ static int __init rvpmu_devinit(void)
int ret;
struct platform_device *pdev;

- if (sbi_spec_version >= sbi_mk_version(0, 3) &&
- sbi_probe_extension(SBI_EXT_PMU))
- static_branch_enable(&riscv_pmu_sbi_available);
+ if (sbi_probe_extension(SBI_EXT_PMU)) {
+ if (sbi_spec_version >= sbi_mk_version(0, 3))
+ static_branch_enable(&riscv_pmu_sbi_available);
+ if (sbi_spec_version >= sbi_mk_version(2, 0))
+ sbi_v2_available = true;
+ }

- if (sbi_spec_version >= sbi_mk_version(2, 0))
- sbi_v2_available = true;
/*
* We need all three extensions to be present to access the counters
* in S-mode via Supervisor Counter delegation.

--
2.43.0