[PATCH] lib/sbi_pmu: Don't fallback to fixed counters when sscofpmf && !smcntrpmf

Anup Patel anup at brainfault.org
Mon May 11 00:52:52 PDT 2026


On Tue, Mar 24, 2026 at 5:59 PM Michael Ellerman <mpe at kernel.org> wrote:
>
> 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.
>
> Signed-off-by: Michael Ellerman <mpe at kernel.org>

Fixes tag is missing but I will add this at the time of merging.

Reviewed-by: Anup Patel <anup at brainfault.org>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup


> ---
> Hi folks,
>
> I noticed this while testing Linux perf with more events than
> programmable counters.
>
> Sometimes cycles gets counted using a mhpmcounter, and sometimes with
> mcycle, and the cycle count differs between the two.
>
> The count differs because mcycle doesn't support filtering when
> smcntrpmf is not present.
>
> It can be reproduced by running perf stat and specifying `cycles:u` N+1
> times where N is the number of mhpmcounters, eg:
>
>     $ perf stat -e cycles:u,cycles:u,...
>     ...
>                 392860      cycles:u
>               61101120      cycles:u
>
> The first cycles got an mhpmcounter and only counted userspace cycles.
> The second used mcycle and counted everything.
>
> cheers
> ---
>  lib/sbi/sbi_pmu.c | 17 ++++++++++++-----
>  1 file changed, 12 insertions(+), 5 deletions(-)
>
> diff --git a/lib/sbi/sbi_pmu.c b/lib/sbi/sbi_pmu.c
> index ae00ad5844b1fe92a8eebfb618902a5eef218a9e..8a9021e2e5bac2d71a0f07d3f81600ff370ee2fc 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);
>
>
> ---
> base-commit: 4813a2042096b7860655761aad973723293a552e
> change-id: 20260324-mcycle-fix-3fc5682eee9c
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi



More information about the opensbi mailing list