Skip to content

Commit

Permalink
KVM: Fix race between timer migration and vcpu migration
Browse files Browse the repository at this point in the history
A guest vcpu instance can be scheduled to a different physical CPU
between the test for KVM_REQ_MIGRATE_TIMER and local_irq_disable().

If that happens, the timer will only be migrated to the current pCPU on
the next exit, meaning that guest LAPIC timer event can be delayed until
a host interrupt is triggered.

Fix it by cancelling guest entry if any vcpu request is pending.  This
has the side effect of nicely consolidating vcpu->requests checks.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
  • Loading branch information
Marcelo Tosatti authored and Avi Kivity committed Jun 24, 2008
1 parent 62786b9 commit d4acf7e
Showing 1 changed file with 3 additions and 12 deletions.
15 changes: 3 additions & 12 deletions arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -2759,6 +2759,8 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
if (vcpu->requests) {
if (test_and_clear_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests))
__kvm_migrate_timers(vcpu);
if (test_and_clear_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests))
kvm_x86_ops->tlb_flush(vcpu);
if (test_and_clear_bit(KVM_REQ_REPORT_TPR_ACCESS,
&vcpu->requests)) {
kvm_run->exit_reason = KVM_EXIT_TPR_ACCESS;
Expand All @@ -2781,21 +2783,13 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)

local_irq_disable();

if (need_resched()) {
if (vcpu->requests || need_resched()) {
local_irq_enable();
preempt_enable();
r = 1;
goto out;
}

if (vcpu->requests)
if (test_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests)) {
local_irq_enable();
preempt_enable();
r = 1;
goto out;
}

if (signal_pending(current)) {
local_irq_enable();
preempt_enable();
Expand Down Expand Up @@ -2825,9 +2819,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)

kvm_guest_enter();

if (vcpu->requests)
if (test_and_clear_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests))
kvm_x86_ops->tlb_flush(vcpu);

KVMTRACE_0D(VMENTRY, vcpu, entryexit);
kvm_x86_ops->run(vcpu, kvm_run);
Expand Down

0 comments on commit d4acf7e

Please sign in to comment.