KVM: add missing memory barrier in kvm_{make,check}_request
authorPaolo Bonzini <pbonzini@redhat.com>
Thu, 10 Mar 2016 15:30:22 +0000 (16:30 +0100)
committerRadim Krčmář <rkrcmar@redhat.com>
Wed, 20 Apr 2016 13:29:17 +0000 (15:29 +0200)
kvm_make_request and kvm_check_request imply a producer-consumer
relationship; add implicit memory barriers to them.  There was indeed
already a place that was adding an explicit smp_mb() to order between
kvm_check_request and the processing of the request.  That memory
barrier can be removed (as an added benefit, kvm_check_request can use
smp_mb__after_atomic which is free on x86).

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/irq_comm.c
include/linux/kvm_host.h

index 54ead79e444b55e80a28d1dd201f1ee2ddf11a18..dfb4c64768771f8fa21f622eb6046e27e1ab3ed6 100644 (file)
@@ -382,9 +382,6 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu,
        u32 i, nr_ioapic_pins;
        int idx;
 
-       /* kvm->irq_routing must be read after clearing
-        * KVM_SCAN_IOAPIC. */
-       smp_mb();
        idx = srcu_read_lock(&kvm->irq_srcu);
        table = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
        nr_ioapic_pins = min_t(u32, table->nr_rt_entries,
index 5276fe0916fcc63a8944af0a288b1afeccc100b0..ad40d44784c7e7a122cd0aef879a5883a7e340ae 100644 (file)
@@ -1091,6 +1091,11 @@ static inline bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; }
 
 static inline void kvm_make_request(int req, struct kvm_vcpu *vcpu)
 {
+       /*
+        * Ensure the rest of the request is published to kvm_check_request's
+        * caller.  Paired with the smp_mb__after_atomic in kvm_check_request.
+        */
+       smp_wmb();
        set_bit(req, &vcpu->requests);
 }
 
@@ -1098,6 +1103,12 @@ static inline bool kvm_check_request(int req, struct kvm_vcpu *vcpu)
 {
        if (test_bit(req, &vcpu->requests)) {
                clear_bit(req, &vcpu->requests);
+
+               /*
+                * Ensure the rest of the request is visible to kvm_check_request's
+                * caller.  Paired with the smp_wmb in kvm_make_request.
+                */
+               smp_mb__after_atomic();
                return true;
        } else {
                return false;