summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Ellerman <mpe@kernel.org>2026-03-24 23:29:20 +1100
committerAnup Patel <anup@brainfault.org>2026-05-11 11:30:22 +0530
commit65bb705f7b59d8f2a5683160f31db15b4e2c64d7 (patch)
treee60b4a558b4240e00a40c79eab3f716794bd612b
parent3d8f1f386479219c4236b5c0fe483442c1bc7461 (diff)
downloadopensbi-65bb705f7b59d8f2a5683160f31db15b4e2c64d7.tar.gz
opensbi-65bb705f7b59d8f2a5683160f31db15b4e2c64d7.zip
lib/sbi_pmu: Don't fallback to fixed counters when sscofpmf && !smcntrpmf
Currently when searching for a hardware counter for an event, if no programmable counter is available, the code falls back to using a fixed counter (mcycle/minstret) if one matches the event. However the fallback is incorrect when sscofpmf is present but smcntrpmf is not. That's because with sscofpmf, programmable counters support mode filtering, but the fixed counters do not (without smcntrpmf). Even if the caller didn't configure mode filtering, by default programmable counters don't count M mode when sscofpmf is present, whereas mcycle/minstret do. Fix the logic to not fallback to a fixed counter if sscofpmf is present but smcntrpmf is not. Fixes: 0c304b661965 ("lib: sbi: Allow programmable counters to monitor cycle/instret events") Signed-off-by: Michael Ellerman <mpe@kernel.org> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20260324-mcycle-fix-v1-1-1444e9fe5c32@kernel.org Signed-off-by: Anup Patel <anup@brainfault.org>
-rw-r--r--lib/sbi/sbi_pmu.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/lib/sbi/sbi_pmu.c b/lib/sbi/sbi_pmu.c
index ae00ad58..8a9021e2 100644
--- a/lib/sbi/sbi_pmu.c
+++ b/lib/sbi/sbi_pmu.c
@@ -830,13 +830,20 @@ static int pmu_ctr_find_hw(struct sbi_pmu_hart_state *phs,
if (ctr_idx == SBI_ENOTSUPP) {
/**
- * We can't find any programmable counters for cycle/instret.
- * Return the fixed counter as they are mandatory anyways.
+ * We can't find a programmable counter, see if we can use a
+ * fixed counter instead if one was found for this event.
+ *
+ * If sscofpmf is present but smcntrpmf is not, we can't
+ * fallback to a fixed counter, because the fixed counter
+ * doesn't support filtering whereas a programmable counter
+ * would.
*/
- if (fixed_ctr >= 0)
- return pmu_fixed_ctr_update_inhibit_bits(fixed_ctr, flags);
- else
+ if (fixed_ctr < 0 ||
+ ((sbi_hart_has_extension(scratch, SBI_HART_EXT_SSCOFPMF) &&
+ !sbi_hart_has_extension(scratch, SBI_HART_EXT_SMCNTRPMF))))
return SBI_EFAIL;
+
+ return pmu_fixed_ctr_update_inhibit_bits(fixed_ctr, flags);
}
ret = pmu_update_hw_mhpmevent(temp, ctr_idx, flags, event_idx, data);