From 0e6a17356549f82b8c71141e135502fd1107007e Mon Sep 17 00:00:00 2001 From: Wang Yechao Date: Tue, 7 Jul 2026 19:37:06 +0800 Subject: [PATCH 1/2] RISC-V: KVM: Move hfence type check out of loop Currently, the check for `data` and `data->type` is performed inside the loop iterating over each VCPU. Since these values are invariant during the loop, this check is redundant and adds unnecessary overhead. Move the validation to the beginning of the function, returning early if the hfence data or its type is invalid. This avoids repeated checks and reduces CPU cycles, which is particularly beneficial for SMP guests with a large number of VCPUs. Signed-off-by: Wang Yechao Signed-off-by: Linux RISC-V bot --- arch/riscv/kvm/tlb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/riscv/kvm/tlb.c b/arch/riscv/kvm/tlb.c index 993b25ea94d674..a67b44a4d1d7ab 100644 --- a/arch/riscv/kvm/tlb.c +++ b/arch/riscv/kvm/tlb.c @@ -335,6 +335,9 @@ static void make_xfence_request(struct kvm *kvm, unsigned int actual_req = req; DECLARE_BITMAP(vcpu_mask, KVM_MAX_VCPUS); + if (!data || !data->type) + return; + bitmap_zero(vcpu_mask, KVM_MAX_VCPUS); kvm_for_each_vcpu(i, vcpu, kvm) { if (hbase != -1UL) { @@ -347,9 +350,6 @@ static void make_xfence_request(struct kvm *kvm, bitmap_set(vcpu_mask, i, 1); - if (!data || !data->type) - continue; - /* * Enqueue hfence data to VCPU hfence queue. If we don't * have space in the VCPU hfence queue then fallback to From e8751fd1e25de208a1c031064f616877f96d7de9 Mon Sep 17 00:00:00 2001 From: Wang Yechao Date: Tue, 7 Jul 2026 19:37:07 +0800 Subject: [PATCH 2/2] RISC-V: KVM: Separate req and fallback_req masks in make_xfence_request When handling hfence requests in make_xfence_request(), the current code uses a single 'actual_req' variable and a single vcpu_mask. If any VCPU fails to enqueue the hfence data (because its queue is full), the request falls back to 'fallback_req' for all VCPUs, even if other VCPUs still have available queue space. This can cause unnecessary fallback for healthy VCPUs, and more seriously, those healthy VCPUs will not process their already-enqueued hfence requests because no 'req' is set for them. As a result, their queues will quickly become full as well, degrading performance for SMP guests. Fix this by maintaining two separate bitmaps: one for VCPUs that successfully enqueued the hfence data (req_vcpu_mask) and another for those that failed (fallback_req_vcpu_mask). Then send the appropriate requests to each group. This ensures that fallback is only applied to VCPUs that actually need it, preserving the efficiency of the normal path for others. Fixes: 13acfec2dbcc ("RISC-V: KVM: Add remote HFENCE functions based on VCPU requests") Signed-off-by: Wang Yechao Signed-off-by: Linux RISC-V bot --- arch/riscv/kvm/tlb.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/riscv/kvm/tlb.c b/arch/riscv/kvm/tlb.c index a67b44a4d1d7ab..916e2b1e0b366d 100644 --- a/arch/riscv/kvm/tlb.c +++ b/arch/riscv/kvm/tlb.c @@ -332,13 +332,14 @@ static void make_xfence_request(struct kvm *kvm, { unsigned long i; struct kvm_vcpu *vcpu; - unsigned int actual_req = req; - DECLARE_BITMAP(vcpu_mask, KVM_MAX_VCPUS); + DECLARE_BITMAP(req_vcpu_mask, KVM_MAX_VCPUS); + DECLARE_BITMAP(fallback_req_vcpu_mask, KVM_MAX_VCPUS); if (!data || !data->type) return; - bitmap_zero(vcpu_mask, KVM_MAX_VCPUS); + bitmap_zero(req_vcpu_mask, KVM_MAX_VCPUS); + bitmap_zero(fallback_req_vcpu_mask, KVM_MAX_VCPUS); kvm_for_each_vcpu(i, vcpu, kvm) { if (hbase != -1UL) { if (vcpu->vcpu_id < hbase || @@ -348,18 +349,19 @@ static void make_xfence_request(struct kvm *kvm, continue; } - bitmap_set(vcpu_mask, i, 1); - /* * Enqueue hfence data to VCPU hfence queue. If we don't * have space in the VCPU hfence queue then fallback to * a more conservative hfence request. */ if (!vcpu_hfence_enqueue(vcpu, data)) - actual_req = fallback_req; + bitmap_set(fallback_req_vcpu_mask, i, 1); + else + bitmap_set(req_vcpu_mask, i, 1); } - kvm_make_vcpus_request_mask(kvm, actual_req, vcpu_mask); + kvm_make_vcpus_request_mask(kvm, req, req_vcpu_mask); + kvm_make_vcpus_request_mask(kvm, fallback_req, fallback_req_vcpu_mask); } void kvm_riscv_fence_i(struct kvm *kvm,