summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWang Yechao <wang.yechao255@zte.com.cn>2026-07-31 17:38:27 +0800
committerAnup Patel <anup@brainfault.org>2026-08-01 13:58:33 +0530
commitc1bc73280fb28f024442e1aa9725b6858bafc37b (patch)
treefe5e1620d41395eb93b466be478b05719b1e6d0c
parent98a1e65ca455d6366ca171dacdf1e3737f6fea14 (diff)
downloadlinux-next-c1bc73280fb28f024442e1aa9725b6858bafc37b.tar.gz
linux-next-c1bc73280fb28f024442e1aa9725b6858bafc37b.zip
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 <wang.yechao255@zte.com.cn> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20260731093833.1551341-2-wang.yechao255@zte.com.cn Signed-off-by: Anup Patel <anup@brainfault.org>
-rw-r--r--arch/riscv/kvm/tlb.c20
1 files 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,