[PATCH] RISC-V: KVM: Avoid one-word masks for SBI v0.1 all-harts

Pengpeng Hou posted 1 patch 6 days, 23 hours ago
arch/riscv/kvm/vcpu_sbi_v01.c | 52 ++++++++++++++++++++---------------
1 file changed, 30 insertions(+), 22 deletions(-)
[PATCH] RISC-V: KVM: Avoid one-word masks for SBI v0.1 all-harts
Posted by Pengpeng Hou 6 days, 23 hours ago
KVM already treats a NULL hart-mask pointer in SBI v0.1 calls as all
harts, matching OpenSBI's legacy handling. The current handler builds that
target set as (1UL << online_vcpus) - 1 before iterating the mask.

That expression shifts by the type width once the VM has BITS_PER_LONG
online vCPUs, and a single word cannot represent larger VMs. A count-based
mask also selects the wrong IDs when vCPU IDs are sparse.

Handle SEND_IPI with a NULL hart-mask by iterating all online vCPUs
directly. For remote fence calls, use the existing hbase == -1UL
convention so the common fence request helper targets the whole VM
without consulting hmask.

Non-NULL guest hart masks keep the existing v0.1 behavior.

Fixes: a046c2d8578c ("RISC-V: KVM: Reorganize SBI code by moving SBI v0.1 to its own file")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
 arch/riscv/kvm/vcpu_sbi_v01.c | 52 ++++++++++++++++++++---------------
 1 file changed, 30 insertions(+), 22 deletions(-)

diff --git a/arch/riscv/kvm/vcpu_sbi_v01.c b/arch/riscv/kvm/vcpu_sbi_v01.c
index c9c323d4577a9..de544ea3f28dc 100644
--- a/arch/riscv/kvm/vcpu_sbi_v01.c
+++ b/arch/riscv/kvm/vcpu_sbi_v01.c
@@ -16,8 +16,9 @@
 static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
 				   struct kvm_vcpu_sbi_return *retdata)
 {
-	ulong hmask;
-	int i, ret = 0;
+	ulong hbase = 0, hmask;
+	unsigned long i;
+	int ret = 0;
 	u64 next_cycle;
 	struct kvm_vcpu *rvcpu;
 	struct kvm *kvm = vcpu->kvm;
@@ -46,20 +47,25 @@ static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		ret = kvm_riscv_vcpu_unset_interrupt(vcpu, IRQ_VS_SOFT);
 		break;
 	case SBI_EXT_0_1_SEND_IPI:
-		if (cp->a0)
+		if (cp->a0) {
 			hmask = kvm_riscv_vcpu_unpriv_read(vcpu, false, cp->a0, utrap);
-		else
-			hmask = (1UL << atomic_read(&kvm->online_vcpus)) - 1;
-		if (utrap->scause)
-			break;
-
-		for_each_set_bit(i, &hmask, BITS_PER_LONG) {
-			rvcpu = kvm_get_vcpu_by_id(vcpu->kvm, i);
-			if (!rvcpu)
-				continue;
-			ret = kvm_riscv_vcpu_set_interrupt(rvcpu, IRQ_VS_SOFT);
-			if (ret < 0)
+			if (utrap->scause)
 				break;
+
+			for_each_set_bit(i, &hmask, BITS_PER_LONG) {
+				rvcpu = kvm_get_vcpu_by_id(vcpu->kvm, i);
+				if (!rvcpu)
+					continue;
+				ret = kvm_riscv_vcpu_set_interrupt(rvcpu, IRQ_VS_SOFT);
+				if (ret < 0)
+					break;
+			}
+		} else {
+			kvm_for_each_vcpu(i, rvcpu, kvm) {
+				ret = kvm_riscv_vcpu_set_interrupt(rvcpu, IRQ_VS_SOFT);
+				if (ret < 0)
+					break;
+			}
 		}
 		break;
 	case SBI_EXT_0_1_SHUTDOWN:
@@ -70,29 +76,31 @@ static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
 	case SBI_EXT_0_1_REMOTE_FENCE_I:
 	case SBI_EXT_0_1_REMOTE_SFENCE_VMA:
 	case SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID:
-		if (cp->a0)
+		if (cp->a0) {
 			hmask = kvm_riscv_vcpu_unpriv_read(vcpu, false, cp->a0, utrap);
-		else
-			hmask = (1UL << atomic_read(&kvm->online_vcpus)) - 1;
+		} else {
+			hbase = -1UL;
+			hmask = 0;
+		}
 		if (utrap->scause)
 			break;
 
 		if (cp->a7 == SBI_EXT_0_1_REMOTE_FENCE_I)
-			kvm_riscv_fence_i(vcpu->kvm, 0, hmask);
+			kvm_riscv_fence_i(vcpu->kvm, hbase, hmask);
 		else if (cp->a7 == SBI_EXT_0_1_REMOTE_SFENCE_VMA) {
 			vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid);
 			if (cp->a1 == 0 && cp->a2 == 0)
-				kvm_riscv_hfence_vvma_all(vcpu->kvm, 0, hmask, vmid);
+				kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase, hmask, vmid);
 			else
-				kvm_riscv_hfence_vvma_gva(vcpu->kvm, 0, hmask, cp->a1,
+				kvm_riscv_hfence_vvma_gva(vcpu->kvm, hbase, hmask, cp->a1,
 							  cp->a2, PAGE_SHIFT, vmid);
 		} else {
 			vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid);
 			if (cp->a1 == 0 && cp->a2 == 0)
-				kvm_riscv_hfence_vvma_asid_all(vcpu->kvm, 0, hmask,
+				kvm_riscv_hfence_vvma_asid_all(vcpu->kvm, hbase, hmask,
 							       cp->a3, vmid);
 			else
-				kvm_riscv_hfence_vvma_asid_gva(vcpu->kvm, 0, hmask,
+				kvm_riscv_hfence_vvma_asid_gva(vcpu->kvm, hbase, hmask,
 							       cp->a1, cp->a2, PAGE_SHIFT,
 							       cp->a3, vmid);
 		}
-- 
2.43.0