* [PATCH v2 1/2] RISC-V: KVM: Introduce make_xfence_request_nodata for FENCE.I requests
2026-07-07 12:50 [PATCH v2 0/2] RISC-V: KVM: Optimize hfence request handling for SMP guests Wang Yechao
@ 2026-07-07 12:50 ` Wang Yechao
2026-07-07 13:03 ` sashiko-bot
2026-07-07 12:50 ` [PATCH v2 2/2] RISC-V: KVM: Separate req and fallback_req masks in make_xfence_request Wang Yechao
1 sibling, 1 reply; 4+ messages in thread
From: Wang Yechao @ 2026-07-07 12:50 UTC (permalink / raw)
To: Anup Patel, kvm, kvm-riscv, linux-riscv, linux-kernel
Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Atish Patra,
Alexandre Ghiti, Wang Yechao
FENCE.I does not need hfence data, but it currently goes through the
generic make_xfence_request() path with NULL data, incurring unnecessary
per-VCPU checks.
Split out a separate make_xfence_request_nodata() function to handle
FENCE.I directly, and move the data validity check to the top of the
generic function to avoid redundant checks.
Signed-off-by: Wang Yechao <wang.yechao255@zte.com.cn>
---
arch/riscv/kvm/tlb.c | 32 +++++++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 5 deletions(-)
diff --git a/arch/riscv/kvm/tlb.c b/arch/riscv/kvm/tlb.c
index 993b25ea94d67..5a9c75e458013 100644
--- a/arch/riscv/kvm/tlb.c
+++ b/arch/riscv/kvm/tlb.c
@@ -325,6 +325,29 @@ void kvm_riscv_hfence_process(struct kvm_vcpu *vcpu)
}
}
+static void make_xfence_request_nodata(struct kvm *kvm, unsigned long hbase,
+ unsigned long hmask, unsigned int req)
+{
+ unsigned long i;
+ struct kvm_vcpu *vcpu;
+ DECLARE_BITMAP(vcpu_mask, KVM_MAX_VCPUS);
+
+ bitmap_zero(vcpu_mask, KVM_MAX_VCPUS);
+ kvm_for_each_vcpu(i, vcpu, kvm) {
+ if (hbase != -1UL) {
+ if (vcpu->vcpu_id < hbase ||
+ vcpu->vcpu_id >= hbase + BITS_PER_LONG)
+ continue;
+ if (!(hmask & (1UL << (vcpu->vcpu_id - hbase))))
+ continue;
+ }
+
+ bitmap_set(vcpu_mask, i, 1);
+ }
+
+ kvm_make_vcpus_request_mask(kvm, req, vcpu_mask);
+}
+
static void make_xfence_request(struct kvm *kvm,
unsigned long hbase, unsigned long hmask,
unsigned int req, unsigned int fallback_req,
@@ -335,6 +358,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 +373,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
@@ -365,8 +388,7 @@ static void make_xfence_request(struct kvm *kvm,
void kvm_riscv_fence_i(struct kvm *kvm,
unsigned long hbase, unsigned long hmask)
{
- make_xfence_request(kvm, hbase, hmask, KVM_REQ_FENCE_I,
- KVM_REQ_FENCE_I, NULL);
+ make_xfence_request_nodata(kvm, hbase, hmask, KVM_REQ_FENCE_I);
}
void kvm_riscv_hfence_gvma_vmid_gpa(struct kvm *kvm,
--
2.43.5
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH v2 2/2] RISC-V: KVM: Separate req and fallback_req masks in make_xfence_request
2026-07-07 12:50 [PATCH v2 0/2] RISC-V: KVM: Optimize hfence request handling for SMP guests Wang Yechao
2026-07-07 12:50 ` [PATCH v2 1/2] RISC-V: KVM: Introduce make_xfence_request_nodata for FENCE.I requests Wang Yechao
@ 2026-07-07 12:50 ` Wang Yechao
1 sibling, 0 replies; 4+ messages in thread
From: Wang Yechao @ 2026-07-07 12:50 UTC (permalink / raw)
To: Anup Patel, kvm, kvm-riscv, linux-riscv, linux-kernel
Cc: Paul Walmsley, Palmer Dabbelt, Albert Ou, Atish Patra,
Alexandre Ghiti, Wang Yechao
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>
---
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 5a9c75e458013..fd445e9fa3f94 100644
--- a/arch/riscv/kvm/tlb.c
+++ b/arch/riscv/kvm/tlb.c
@@ -355,13 +355,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 ||
@@ -371,18 +372,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,
--
2.43.5
^ permalink raw reply related [flat|nested] 4+ messages in thread