Skip to content

Commit

Permalink
KVM: Fix race in apic->pending_events processing
Browse files Browse the repository at this point in the history
apic->pending_events processing has a race that may cause INIT and
SIPI
processing to be reordered:

vpu0:                            vcpu1:
set INIT
                               test_and_clear_bit(KVM_APIC_INIT)
                                  process INIT
set INIT
set SIPI
                               test_and_clear_bit(KVM_APIC_SIPI)
                                  process SIPI

At the end INIT is left pending in pending_events. The following patch
fixes this by latching pending event before processing them.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
  • Loading branch information
Gleb Natapov committed Jun 3, 2013
1 parent 8acb420 commit 299018f
Showing 1 changed file with 6 additions and 3 deletions.
9 changes: 6 additions & 3 deletions arch/x86/kvm/lapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1861,19 +1861,22 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu)
{
struct kvm_lapic *apic = vcpu->arch.apic;
unsigned int sipi_vector;
unsigned long pe;

if (!kvm_vcpu_has_lapic(vcpu))
if (!kvm_vcpu_has_lapic(vcpu) || !apic->pending_events)
return;

if (test_and_clear_bit(KVM_APIC_INIT, &apic->pending_events)) {
pe = xchg(&apic->pending_events, 0);

if (test_bit(KVM_APIC_INIT, &pe)) {
kvm_lapic_reset(vcpu);
kvm_vcpu_reset(vcpu);
if (kvm_vcpu_is_bsp(apic->vcpu))
vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
else
vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
}
if (test_and_clear_bit(KVM_APIC_SIPI, &apic->pending_events) &&
if (test_bit(KVM_APIC_SIPI, &pe) &&
vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
/* evaluate pending_events before reading the vector */
smp_rmb();
Expand Down

0 comments on commit 299018f

Please sign in to comment.