From: Wanpeng Li Add a minimal two-round fallback mechanism in kvm_vcpu_on_spin() to avoid pathological stalls when the first round finds no eligible target. Round 1 applies strict IPI-aware candidate selection (existing behavior). Round 2 provides a relaxed scan gated only by preempted state as a safety net, addressing cases where IPI context is missed or the runnable set is transient. The second round is controlled by module parameter enable_relaxed_boost (bool, 0644, default on) to allow easy disablement by distributions if needed. Introduce the enable_relaxed_boost parameter, add a first_round flag, retry label, and reset of yielded counter. Gate the IPI-aware check in round 1 and use preempted-only gating in round 2. Keep churn minimal by reusing the same scan logic while preserving all existing heuristics, tracing, and bookkeeping. Signed-off-by: Wanpeng Li --- virt/kvm/kvm_main.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 9cf44b6b396d..b03be8d9ae4c 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -101,6 +101,9 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(halt_poll_ns_shrink); static bool allow_unsafe_mappings; module_param(allow_unsafe_mappings, bool, 0444); +static bool enable_relaxed_boost = true; +module_param(enable_relaxed_boost, bool, 0644); + /* * Ordering of locks: * @@ -4015,6 +4018,7 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode) struct kvm *kvm = me->kvm; struct kvm_vcpu *vcpu; int try = 3; + bool first_round = true; nr_vcpus = atomic_read(&kvm->online_vcpus); if (nr_vcpus < 2) @@ -4025,6 +4029,9 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode) kvm_vcpu_set_in_spin_loop(me, true); +retry: + yielded = 0; + /* * The current vCPU ("me") is spinning in kernel mode, i.e. is likely * waiting for a resource to become available. Attempt to yield to a @@ -4057,7 +4064,12 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode) continue; /* IPI-aware candidate selection */ - if (!kvm_vcpu_is_good_yield_candidate(me, vcpu, yield_to_kernel_mode)) + if (first_round && + !kvm_vcpu_is_good_yield_candidate(me, vcpu, yield_to_kernel_mode)) + continue; + + /* Minimal preempted gate for second round */ + if (!first_round && !READ_ONCE(vcpu->preempted)) continue; if (!kvm_vcpu_eligible_for_directed_yield(vcpu)) @@ -4071,6 +4083,16 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode) break; } } + + /* + * Second round: relaxed boost as safety net, with preempted gate. + * Only execute when enabled and when the first round yielded nothing. + */ + if (enable_relaxed_boost && first_round && yielded <= 0) { + first_round = false; + goto retry; + } + kvm_vcpu_set_in_spin_loop(me, false); /* Ensure vcpu is not eligible during next spinloop */ -- 2.43.0