[PATCH] RISC-V: KVM: Fix IPI delivery for out-of-order vcpu_id

Nutty.Liu nutty.liu at hotmail.com
Thu Sep 24 03:31:05 PDT 2026


On 9/17/2026 8:20 PM, Xiaofeng Yuan wrote:
> The SBI IPI handler walks vCPUs with kvm_for_each_vcpu(), which
> iterates by vcpu_idx (creation order) rather than vcpu_id order.
> Since vcpu_id can be assigned out of order by userspace, a vCPU whose
> hart_bit falls outside the XLEN-bit hart_mask range may be reached
> before vCPUs the mask actually targets. In that case the handler jumps
> to "done" and stops sending IPIs, leaving valid target vCPUs without
> an interrupt.
>
> Replace the early "goto done" with "continue" so vCPUs outside the
> hart_mask range are skipped without aborting the loop.
>
> Reproduced with a minimal userspace VMM driving KVM inside a QEMU
> (RISC-V virt) guest: three vCPUs are created with ids 100, 0, 1 (in
> creation order) and sbi_send_ipi(hart_mask=bit0, hbase=0) is called
> from vcpu_id 1. Before this change the IPI is dropped and the ecall
> returns SBI_ERR_INVALID_PARAM; with this change the IPI is delivered
> and the ecall returns SBI_SUCCESS.
>
> Fixes: 0611f78f83c9 ("riscv: KVM: Fix SBI IPI error generation")
> Cc: stable at vger.kernel.org
> Suggested-by: Andrew Jones <ajones at ventanamicro.com>
> Signed-off-by: Xiaofeng Yuan <yuanxiaofeng at eswincomputing.com>
> ---
>   arch/riscv/kvm/vcpu_sbi_replace.c | 12 ++++++++++--
>   1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/arch/riscv/kvm/vcpu_sbi_replace.c b/arch/riscv/kvm/vcpu_sbi_replace.c
> index 506a510b6..c2f1f7f26 100644
> --- a/arch/riscv/kvm/vcpu_sbi_replace.c
> +++ b/arch/riscv/kvm/vcpu_sbi_replace.c
> @@ -64,8 +64,17 @@ static int kvm_sbi_ext_ipi_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
>   			if (tmp->vcpu_id < hbase)
>   				continue;
>   			hart_bit = tmp->vcpu_id - hbase;
> +			/*
> +			 * kvm_for_each_vcpu() walks kvm->vcpus[] by
> +			 * vcpu_idx, i.e. the creation order, which has
> +			 * nothing to do with the vcpu_id (hart id) space
> +			 * that the SBI IPI operates on. vcpu_ids need not
> +			 * increase along the iteration, so harts outside
> +			 * the hart_mask window must be skipped instead of
> +			 * aborting the loop.
> +			 */
>   			if (hart_bit >= __riscv_xlen)
> -				goto done;
> +				continue;
>   			if (!(hmask & (1UL << hart_bit)))
>   				continue;
Seems the above two 'if' statements can be combined.
Otherwise,

Reviewed-by: Nutty Liu <nutty.liu at hotmail.com>

Thanks,
Nutty
>   		}
> @@ -76,7 +85,6 @@ static int kvm_sbi_ext_ipi_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
>   		kvm_riscv_vcpu_pmu_incr_fw(tmp, SBI_PMU_FW_IPI_RCVD);
>   	}
>   
> -done:
>   	if (hbase != -1UL && (hmask ^ sentmask))
>   		retdata->err_val = SBI_ERR_INVALID_PARAM;
>   



More information about the linux-riscv mailing list