KVM: Fix race between APIC TMR and IRR
When we queue an interrupt to the local apic, we set the IRR before the TMR. The vcpu can pick up the IRR and inject the interrupt before setting the TMR, and perhaps even EOI it, causing incorrect behaviour. The race is really insignificant since it can only occur on the first interrupt (usually following interrupts will not change TMR), but it's better closed than open. Fixed by reordering setting the TMR vs IRR. Cc: stable@kernel.org Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
This commit is contained in:
parent
f6760aa024
commit
a5d36f82c4
1 changed files with 6 additions and 5 deletions
|
@ -373,6 +373,12 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
|
|||
if (unlikely(!apic_enabled(apic)))
|
||||
break;
|
||||
|
||||
if (trig_mode) {
|
||||
apic_debug("level trig mode for vector %d", vector);
|
||||
apic_set_vector(vector, apic->regs + APIC_TMR);
|
||||
} else
|
||||
apic_clear_vector(vector, apic->regs + APIC_TMR);
|
||||
|
||||
result = !apic_test_and_set_irr(vector, apic);
|
||||
trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
|
||||
trig_mode, vector, !result);
|
||||
|
@ -383,11 +389,6 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
|
|||
break;
|
||||
}
|
||||
|
||||
if (trig_mode) {
|
||||
apic_debug("level trig mode for vector %d", vector);
|
||||
apic_set_vector(vector, apic->regs + APIC_TMR);
|
||||
} else
|
||||
apic_clear_vector(vector, apic->regs + APIC_TMR);
|
||||
kvm_vcpu_kick(vcpu);
|
||||
break;
|
||||
|
||||
|
|
Reference in a new issue