KVM: MMIO: Lock coalesced device when checking for available entry
authorSasha Levin <levinsasha928@gmail.com>
Mon, 18 Jul 2011 14:17:14 +0000 (17:17 +0300)
committerAvi Kivity <avi@redhat.com>
Sun, 25 Sep 2011 16:17:18 +0000 (19:17 +0300)
Move the check whether there are available entries to within the spinlock.
This allows working with larger amount of VCPUs and reduces premature
exits when using a large number of VCPUs.

Cc: Avi Kivity <avi@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
virt/kvm/coalesced_mmio.c

index fc84875..ae075dc 100644 (file)
@@ -25,23 +25,8 @@ static int coalesced_mmio_in_range(struct kvm_coalesced_mmio_dev *dev,
                                   gpa_t addr, int len)
 {
        struct kvm_coalesced_mmio_zone *zone;
-       struct kvm_coalesced_mmio_ring *ring;
-       unsigned avail;
        int i;
 
-       /* Are we able to batch it ? */
-
-       /* last is the first free entry
-        * check if we don't meet the first used entry
-        * there is always one unused entry in the buffer
-        */
-       ring = dev->kvm->coalesced_mmio_ring;
-       avail = (ring->first - ring->last - 1) % KVM_COALESCED_MMIO_MAX;
-       if (avail < KVM_MAX_VCPUS) {
-               /* full */
-               return 0;
-       }
-
        /* is it in a batchable area ? */
 
        for (i = 0; i < dev->nb_zones; i++) {
@@ -58,16 +43,43 @@ static int coalesced_mmio_in_range(struct kvm_coalesced_mmio_dev *dev,
        return 0;
 }
 
+static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev)
+{
+       struct kvm_coalesced_mmio_ring *ring;
+       unsigned avail;
+
+       /* Are we able to batch it ? */
+
+       /* last is the first free entry
+        * check if we don't meet the first used entry
+        * there is always one unused entry in the buffer
+        */
+       ring = dev->kvm->coalesced_mmio_ring;
+       avail = (ring->first - ring->last - 1) % KVM_COALESCED_MMIO_MAX;
+       if (avail == 0) {
+               /* full */
+               return 0;
+       }
+
+       return 1;
+}
+
 static int coalesced_mmio_write(struct kvm_io_device *this,
                                gpa_t addr, int len, const void *val)
 {
        struct kvm_coalesced_mmio_dev *dev = to_mmio(this);
        struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring;
+
        if (!coalesced_mmio_in_range(dev, addr, len))
                return -EOPNOTSUPP;
 
        spin_lock(&dev->lock);
 
+       if (!coalesced_mmio_has_room(dev)) {
+               spin_unlock(&dev->lock);
+               return -EOPNOTSUPP;
+       }
+
        /* copy data in first free entry of the ring */
 
        ring->coalesced_mmio[ring->last].phys_addr = addr;