KVM: Fix race between timer migration and vcpu migration
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>
This commit is contained in:
parent
62786b9e81
commit
d4acf7e7ab
1 changed files with 3 additions and 12 deletions
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue