[PATCH] KVM: riscv: PMU: Bound counter mask scan to BITS_PER_LONG
Anup Patel
anup at brainfault.org
Mon Jul 13 05:03:16 PDT 2026
On Fri, Jun 26, 2026 at 11:11 AM Shengwen Cheng
<shengwen1997.tw at gmail.com> wrote:
>
> The PMU SBI handler passes the guest argument registers directly to the
> PMU start/stop helpers:
>
> kvm_riscv_vcpu_pmu_ctr_start(vcpu, cp->a0, cp->a1, cp->a2, ...)
> kvm_riscv_vcpu_pmu_ctr_stop(vcpu, cp->a0, cp->a1, cp->a2, ...)
>
> which map to:
>
> unsigned long ctr_base
> unsigned long ctr_mask
> unsigned long flags
>
> Thus cp->a1 is a single unsigned long ctr_mask, not a bitmap array sized
> for RISCV_MAX_COUNTERS.
>
> On RV32, RISCV_MAX_COUNTERS is 64 while BITS_PER_LONG is 32. Using
> for_each_set_bit() with RISCV_MAX_COUNTERS can therefore make
> find_next_bit() access bits beyond the storage of ctr_mask on RV32.
>
> Limit the scan to BITS_PER_LONG. The requested counter range is already
> validated by kvm_pmu_validate_counter_mask(), so this preserves RV64
> behavior and avoids an out-of-bounds bitmap read on RV32.
>
> Signed-off-by: Shengwen Cheng <shengwen1997.tw at gmail.com>
LGTM.
Reviewed-by: Anup Patel <anup at brainfault.org>
Queued this patch as a fix for Linux-7.2-rcX
Thanks,
Anup
> ---
> arch/riscv/kvm/vcpu_pmu.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/riscv/kvm/vcpu_pmu.c b/arch/riscv/kvm/vcpu_pmu.c
> index bb46dcbfb..2025b6649 100644
> --- a/arch/riscv/kvm/vcpu_pmu.c
> +++ b/arch/riscv/kvm/vcpu_pmu.c
> @@ -586,7 +586,7 @@ int kvm_riscv_vcpu_pmu_ctr_start(struct kvm_vcpu *vcpu, unsigned long ctr_base,
> }
> }
> /* Start the counters that have been configured and requested by the guest */
> - for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) {
> + for_each_set_bit(i, &ctr_mask, BITS_PER_LONG) {
> pmc_index = array_index_nospec(i + ctr_base,
> RISCV_KVM_MAX_COUNTERS);
> if (!test_bit(pmc_index, kvpmu->pmc_in_use))
> @@ -658,7 +658,7 @@ int kvm_riscv_vcpu_pmu_ctr_stop(struct kvm_vcpu *vcpu, unsigned long ctr_base,
> }
>
> /* Stop the counters that have been configured and requested by the guest */
> - for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) {
> + for_each_set_bit(i, &ctr_mask, BITS_PER_LONG) {
> pmc_index = array_index_nospec(i + ctr_base,
> RISCV_KVM_MAX_COUNTERS);
> if (!test_bit(pmc_index, kvpmu->pmc_in_use))
> --
> 2.43.0
>
More information about the linux-riscv
mailing list