From c1bc73280fb28f024442e1aa9725b6858bafc37b Mon Sep 17 00:00:00 2001 From: Wang Yechao Date: Fri, 31 Jul 2026 17:38:27 +0800 Subject: [PATCH] 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 Reviewed-by: Anup Patel Link: https://lore.kernel.org/r/20260731093833.1551341-2-wang.yechao255@zte.com.cn Signed-off-by: Anup Patel --- arch/riscv/kvm/tlb.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/arch/riscv/kvm/tlb.c b/arch/riscv/kvm/tlb.c index 993b25ea94d6..c54522decaa6 100644 --- a/arch/riscv/kvm/tlb.c +++ b/arch/riscv/kvm/tlb.c @@ -332,10 +332,11 @@ 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); - 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 || @@ -345,10 +346,10 @@ static void make_xfence_request(struct kvm *kvm, continue; } - bitmap_set(vcpu_mask, i, 1); - - if (!data || !data->type) + if (!data || !data->type) { + bitmap_set(req_vcpu_mask, i, 1); continue; + } /* * Enqueue hfence data to VCPU hfence queue. If we don't @@ -356,10 +357,13 @@ static void make_xfence_request(struct kvm *kvm, * 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,