diff options
| author | Gleb Natapov <gleb@redhat.com> | 2013-06-03 04:30:02 -0400 |
|---|---|---|
| committer | Gleb Natapov <gleb@redhat.com> | 2013-06-03 04:32:39 -0400 |
| commit | 299018f44ac553dce3caf84df1d14c4764faa279 (patch) | |
| tree | 75c178b1c2767697e2bef132aea84a8c04c1b156 | |
| parent | 8acb42070ec4c87a9baab5c7bac626030d5bef28 (diff) | |
KVM: Fix race in apic->pending_events processing
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>
| -rw-r--r-- | arch/x86/kvm/lapic.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index e1adbb4aca75..0eee2c8b64d1 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
| @@ -1861,11 +1861,14 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu) | |||
| 1861 | { | 1861 | { |
| 1862 | struct kvm_lapic *apic = vcpu->arch.apic; | 1862 | struct kvm_lapic *apic = vcpu->arch.apic; |
| 1863 | unsigned int sipi_vector; | 1863 | unsigned int sipi_vector; |
| 1864 | unsigned long pe; | ||
| 1864 | 1865 | ||
| 1865 | if (!kvm_vcpu_has_lapic(vcpu)) | 1866 | if (!kvm_vcpu_has_lapic(vcpu) || !apic->pending_events) |
| 1866 | return; | 1867 | return; |
| 1867 | 1868 | ||
| 1868 | if (test_and_clear_bit(KVM_APIC_INIT, &apic->pending_events)) { | 1869 | pe = xchg(&apic->pending_events, 0); |
| 1870 | |||
| 1871 | if (test_bit(KVM_APIC_INIT, &pe)) { | ||
| 1869 | kvm_lapic_reset(vcpu); | 1872 | kvm_lapic_reset(vcpu); |
| 1870 | kvm_vcpu_reset(vcpu); | 1873 | kvm_vcpu_reset(vcpu); |
| 1871 | if (kvm_vcpu_is_bsp(apic->vcpu)) | 1874 | if (kvm_vcpu_is_bsp(apic->vcpu)) |
| @@ -1873,7 +1876,7 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu) | |||
| 1873 | else | 1876 | else |
| 1874 | vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED; | 1877 | vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED; |
| 1875 | } | 1878 | } |
| 1876 | if (test_and_clear_bit(KVM_APIC_SIPI, &apic->pending_events) && | 1879 | if (test_bit(KVM_APIC_SIPI, &pe) && |
| 1877 | vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { | 1880 | vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { |
| 1878 | /* evaluate pending_events before reading the vector */ | 1881 | /* evaluate pending_events before reading the vector */ |
| 1879 | smp_rmb(); | 1882 | smp_rmb(); |
