Skip to content

Commit 175d5dc

Browse files
dmatlackbonzini
authored andcommitted
KVM: Avoid re-reading kvm->max_halt_poll_ns during halt-polling
Avoid re-reading kvm->max_halt_poll_ns multiple times during halt-polling except when it is explicitly useful, e.g. to check if the max time changed across a halt. kvm->max_halt_poll_ns can be changed at any time by userspace via KVM_CAP_HALT_POLL. This bug is unlikely to cause any serious side-effects. In the worst case one halt polls for shorter or longer than it should, and then is fixed up on the next halt. Furthmore, this is still possible since kvm->max_halt_poll_ns are not synchronized with halts. Fixes: acd0578 ("kvm: add capability for halt polling") Signed-off-by: David Matlack <dmatlack@google.com> Message-Id: <20221117001657.1067231-3-dmatlack@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 97b6847 commit 175d5dc

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

virt/kvm/kvm_main.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3480,6 +3480,11 @@ static inline void update_halt_poll_stats(struct kvm_vcpu *vcpu, ktime_t start,
34803480
}
34813481
}
34823482

3483+
static unsigned int kvm_vcpu_max_halt_poll_ns(struct kvm_vcpu *vcpu)
3484+
{
3485+
return READ_ONCE(vcpu->kvm->max_halt_poll_ns);
3486+
}
3487+
34833488
/*
34843489
* Emulate a vCPU halt condition, e.g. HLT on x86, WFI on arm, etc... If halt
34853490
* polling is enabled, busy wait for a short time before blocking to avoid the
@@ -3488,14 +3493,15 @@ static inline void update_halt_poll_stats(struct kvm_vcpu *vcpu, ktime_t start,
34883493
*/
34893494
void kvm_vcpu_halt(struct kvm_vcpu *vcpu)
34903495
{
3496+
unsigned int max_halt_poll_ns = kvm_vcpu_max_halt_poll_ns(vcpu);
34913497
bool halt_poll_allowed = !kvm_arch_no_poll(vcpu);
34923498
ktime_t start, cur, poll_end;
34933499
bool waited = false;
34943500
bool do_halt_poll;
34953501
u64 halt_ns;
34963502

3497-
if (vcpu->halt_poll_ns > vcpu->kvm->max_halt_poll_ns)
3498-
vcpu->halt_poll_ns = vcpu->kvm->max_halt_poll_ns;
3503+
if (vcpu->halt_poll_ns > max_halt_poll_ns)
3504+
vcpu->halt_poll_ns = max_halt_poll_ns;
34993505

35003506
do_halt_poll = halt_poll_allowed && vcpu->halt_poll_ns;
35013507

@@ -3537,18 +3543,21 @@ void kvm_vcpu_halt(struct kvm_vcpu *vcpu)
35373543
update_halt_poll_stats(vcpu, start, poll_end, !waited);
35383544

35393545
if (halt_poll_allowed) {
3546+
/* Recompute the max halt poll time in case it changed. */
3547+
max_halt_poll_ns = kvm_vcpu_max_halt_poll_ns(vcpu);
3548+
35403549
if (!vcpu_valid_wakeup(vcpu)) {
35413550
shrink_halt_poll_ns(vcpu);
3542-
} else if (vcpu->kvm->max_halt_poll_ns) {
3551+
} else if (max_halt_poll_ns) {
35433552
if (halt_ns <= vcpu->halt_poll_ns)
35443553
;
35453554
/* we had a long block, shrink polling */
35463555
else if (vcpu->halt_poll_ns &&
3547-
halt_ns > vcpu->kvm->max_halt_poll_ns)
3556+
halt_ns > max_halt_poll_ns)
35483557
shrink_halt_poll_ns(vcpu);
35493558
/* we had a short halt and our poll time is too small */
3550-
else if (vcpu->halt_poll_ns < vcpu->kvm->max_halt_poll_ns &&
3551-
halt_ns < vcpu->kvm->max_halt_poll_ns)
3559+
else if (vcpu->halt_poll_ns < max_halt_poll_ns &&
3560+
halt_ns < max_halt_poll_ns)
35523561
grow_halt_poll_ns(vcpu);
35533562
} else {
35543563
vcpu->halt_poll_ns = 0;

0 commit comments

Comments
 (0)