[patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-06-04 Thread Marcelo Tosatti
Move coalesced_mmio locking to its own device, instead of relying on
kvm-lock.

Signed-off-by: Marcelo Tosatti mtosa...@redhat.com

Index: kvm/virt/kvm/coalesced_mmio.c
===
--- kvm.orig/virt/kvm/coalesced_mmio.c
+++ kvm/virt/kvm/coalesced_mmio.c
@@ -31,10 +31,6 @@ static int coalesced_mmio_in_range(struc
if (!is_write)
return 0;
 
-   /* kvm-lock is taken by the caller and must be not released before
- * dev.read/write
- */
-
/* Are we able to batch it ? */
 
/* last is the first free entry
@@ -70,7 +66,7 @@ static void coalesced_mmio_write(struct 
struct kvm_coalesced_mmio_dev *dev = to_mmio(this);
struct kvm_coalesced_mmio_ring *ring = dev-kvm-coalesced_mmio_ring;
 
-   /* kvm-lock must be taken by caller before call to in_range()*/
+   spin_lock(dev-lock);
 
/* copy data in first free entry of the ring */
 
@@ -79,6 +75,7 @@ static void coalesced_mmio_write(struct 
memcpy(ring-coalesced_mmio[ring-last].data, val, len);
smp_wmb();
ring-last = (ring-last + 1) % KVM_COALESCED_MMIO_MAX;
+   spin_unlock(dev-lock);
 }
 
 static void coalesced_mmio_destructor(struct kvm_io_device *this)
@@ -101,6 +98,7 @@ int kvm_coalesced_mmio_init(struct kvm *
dev = kzalloc(sizeof(struct kvm_coalesced_mmio_dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
+   spin_lock_init(dev-lock);
kvm_iodevice_init(dev-dev, coalesced_mmio_ops);
dev-kvm = kvm;
kvm-coalesced_mmio_dev = dev;
Index: kvm/virt/kvm/coalesced_mmio.h
===
--- kvm.orig/virt/kvm/coalesced_mmio.h
+++ kvm/virt/kvm/coalesced_mmio.h
@@ -12,6 +12,7 @@
 struct kvm_coalesced_mmio_dev {
struct kvm_io_device dev;
struct kvm *kvm;
+   spinlock_t lock;
int nb_zones;
struct kvm_coalesced_mmio_zone zone[KVM_COALESCED_MMIO_ZONE_MAX];
 };

-- 

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-06-01 Thread Avi Kivity

Marcelo Tosatti wrote:

On Sun, May 31, 2009 at 03:14:36PM +0300, Avi Kivity wrote:
  

Marcelo Tosatti wrote:


Move coalesced_mmio locking to its own device, instead of relying on
kvm-lock.

Signed-off-by: Marcelo Tosatti mtosa...@redhat.com

Index: kvm-irqlock/virt/kvm/coalesced_mmio.c
===
--- kvm-irqlock.orig/virt/kvm/coalesced_mmio.c
+++ kvm-irqlock/virt/kvm/coalesced_mmio.c
@@ -26,9 +26,7 @@ static int coalesced_mmio_in_range(struc
if (!is_write)
return 0;
 -  /* kvm-lock is taken by the caller and must be not released before
- * dev.read/write
- */
+   spin_lock(dev-lock);
  
  
This unbalanced locking is still very displeasing.  At a minimum you  
need a sparse annotation to indicate it.


But I think it really indicates a problem with the io_device API.

Potential solutions:
- fold in_range() into -write and -read.  Make those functions  
responsible for both determining whether they can handle the range and  
performing the I/O.

- have a separate rwlock for the device list.



IMO the problem is the coalesced_mmio device. The unbalanced locking is
a result of the abuse of the in_range() and read/write() methods.

  


Okay, the penny has dropped.  I understand now.


Normally you'd expect parallel accesses to in_range() to be allowed,
since its just checking whether (aha) the access is in range, returning
a pointer to the device if positive. Now read/write() are the ones who
need serialization, since they touch the device internal state.

coalesced_mmio abuses in_range() to do more things than it should.

Ideally we should fix coalesced_mmio, but i'm not going to do that now
(sorry, not confident in changing it without seeing go through intense
torture testing).
  


It's not trivial since it's userspace that clears the ring, and we can't 
wait on userspace.



That said, is sparse annotation enough the convince you?
  


Let me have a look at fixing coalesced_mmio first.  We might allow 
-write to fail, causing a fallback to userspace.  Or we could fail if 
n_avail  MAX_VCPUS, so even the worst-case race leaves us one entry.


--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-27 Thread Marcelo Tosatti
Move coalesced_mmio locking to its own device, instead of relying on
kvm-lock.

Signed-off-by: Marcelo Tosatti mtosa...@redhat.com

Index: kvm-irqlock/virt/kvm/coalesced_mmio.c
===
--- kvm-irqlock.orig/virt/kvm/coalesced_mmio.c
+++ kvm-irqlock/virt/kvm/coalesced_mmio.c
@@ -26,9 +26,7 @@ static int coalesced_mmio_in_range(struc
if (!is_write)
return 0;
 
-   /* kvm-lock is taken by the caller and must be not released before
- * dev.read/write
- */
+   spin_lock(dev-lock);
 
/* Are we able to batch it ? */
 
@@ -41,7 +39,7 @@ static int coalesced_mmio_in_range(struc
KVM_COALESCED_MMIO_MAX;
if (next == dev-kvm-coalesced_mmio_ring-first) {
/* full */
-   return 0;
+   goto out_denied;
}
 
/* is it in a batchable area ? */
@@ -57,6 +55,8 @@ static int coalesced_mmio_in_range(struc
addr + len = zone-addr + zone-size)
return 1;
}
+out_denied:
+   spin_unlock(dev-lock);
return 0;
 }
 
@@ -67,8 +67,6 @@ static void coalesced_mmio_write(struct 
(struct kvm_coalesced_mmio_dev*)this-private;
struct kvm_coalesced_mmio_ring *ring = dev-kvm-coalesced_mmio_ring;
 
-   /* kvm-lock must be taken by caller before call to in_range()*/
-
/* copy data in first free entry of the ring */
 
ring-coalesced_mmio[ring-last].phys_addr = addr;
@@ -76,6 +74,7 @@ static void coalesced_mmio_write(struct 
memcpy(ring-coalesced_mmio[ring-last].data, val, len);
smp_wmb();
ring-last = (ring-last + 1) % KVM_COALESCED_MMIO_MAX;
+   spin_unlock(dev-lock);
 }
 
 static void coalesced_mmio_destructor(struct kvm_io_device *this)
@@ -90,6 +89,8 @@ int kvm_coalesced_mmio_init(struct kvm *
dev = kzalloc(sizeof(struct kvm_coalesced_mmio_dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
+   spin_lock_init(dev-lock);
+
dev-dev.write  = coalesced_mmio_write;
dev-dev.in_range  = coalesced_mmio_in_range;
dev-dev.destructor  = coalesced_mmio_destructor;
Index: kvm-irqlock/virt/kvm/coalesced_mmio.h
===
--- kvm-irqlock.orig/virt/kvm/coalesced_mmio.h
+++ kvm-irqlock/virt/kvm/coalesced_mmio.h
@@ -12,6 +12,7 @@
 struct kvm_coalesced_mmio_dev {
struct kvm_io_device dev;
struct kvm *kvm;
+   spinlock_t lock;
int nb_zones;
struct kvm_coalesced_mmio_zone zone[KVM_COALESCED_MMIO_ZONE_MAX];
 };

-- 

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-26 Thread Avi Kivity

Marcelo Tosatti wrote:

===
--- kvm-irqlock.orig/virt/kvm/coalesced_mmio.c
+++ kvm-irqlock/virt/kvm/coalesced_mmio.c
@@ -26,9 +26,12 @@ static int coalesced_mmio_in_range(struc
if (!is_write)
return 0;
 -  /* kvm-lock is taken by the caller and must be not released before
- * dev.read/write
- */
+   /*
+* Some other vcpu might be batching data into the ring,
+* fallback to userspace. Ordering not our problem.
+*/
+   if (!atomic_add_unless(dev-in_use, 1, 1))
+   return 0;
   
  
Ordering with simultaneous writes is indeed not our problem, but the  
ring may contain ordered writes (even by the same vcpu!)



You mean writes by a vcpu should maintain ordering even when that vcpu
migrates to a different pcpu? 
  


No.  Writes by a single vcpu need to preserve their ordering relative to 
each other.  If a write by vcpu A completes before a write by vcpu B 
starts, then they need to be ordered, since the vcpus may have 
synchronized in between.


Hm, I don't thimk you broke these rules.


The smp_wmb in coalesced_write guarantees that.

  
Suggest our own lock here.  in_use is basically a homemade lock, better  
to use the factory made ones which come with a warranty.



The first submission had a mutex but was considered unorthodox. Although
i agree with your argument made then, i don't see a way around that.

Some pseudocode please? 
  


Why not use slots_lock to protect the entire iodevice list (rcu one 
day), and an internal spinlock for coalesced mmio?


--
error compiling committee.c: too many arguments to function

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-26 Thread Marcelo Tosatti
On Tue, May 26, 2009 at 02:24:33PM +0300, Avi Kivity wrote:
 Marcelo Tosatti wrote:
 ===
 --- kvm-irqlock.orig/virt/kvm/coalesced_mmio.c
 +++ kvm-irqlock/virt/kvm/coalesced_mmio.c
 @@ -26,9 +26,12 @@ static int coalesced_mmio_in_range(struc
if (!is_write)
return 0;
  - /* kvm-lock is taken by the caller and must be not released before
 - * dev.read/write
 - */
 +  /*
 +   * Some other vcpu might be batching data into the ring,
 +   * fallback to userspace. Ordering not our problem.
 +   */
 +  if (!atomic_add_unless(dev-in_use, 1, 1))
 +  return 0;
  
 Ordering with simultaneous writes is indeed not our problem, but the  
 ring may contain ordered writes (even by the same vcpu!)
 

 You mean writes by a vcpu should maintain ordering even when that vcpu
 migrates to a different pcpu?   

 No.  Writes by a single vcpu need to preserve their ordering relative to  
 each other.  If a write by vcpu A completes before a write by vcpu B  
 starts, then they need to be ordered, since the vcpus may have  
 synchronized in between.

 Hm, I don't thimk you broke these rules.

 The smp_wmb in coalesced_write guarantees that.

   
 Suggest our own lock here.  in_use is basically a homemade lock, 
 better  to use the factory made ones which come with a warranty.
 

 The first submission had a mutex but was considered unorthodox. Although
 i agree with your argument made then, i don't see a way around that.

 Some pseudocode please?   

 Why not use slots_lock to protect the entire iodevice list (rcu one  
 day), and an internal spinlock for coalesced mmio?

Don't like using slots_lock to protect the entire iodevice list, its
reverse progress in my opinion. The PIO/MMIO device lists are data
structures used in hot path, they are not directly related to the
memslots, and therefore deserve a separate lock. Whenever slots_lock
becomes an issue, you'll have to entangle the mess, so better start
doing it now.

Sure can switch to a internal spinlock for coalesced_mmio, but breaking
out if spin_trylock fails. You're OK with that?



--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-26 Thread Avi Kivity

Marcelo Tosatti wrote:


Why not use slots_lock to protect the entire iodevice list (rcu one  
day), and an internal spinlock for coalesced mmio?



Don't like using slots_lock to protect the entire iodevice list, its
reverse progress in my opinion. The PIO/MMIO device lists are data
structures used in hot path, they are not directly related to the
memslots, and therefore deserve a separate lock. Whenever slots_lock
becomes an issue, you'll have to entangle the mess, so better start
doing it now.
  


It's a reader/writer lock, so you'll never have contention.

I'm okay with a new lock though.


Sure can switch to a internal spinlock for coalesced_mmio, but breaking
out if spin_trylock fails. You're OK with that?
  


Why not do a normal spin_lock()?  It's not like you'll wait years for 
the store to complete.


--
error compiling committee.c: too many arguments to function

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-25 Thread Marcelo Tosatti
On Sun, May 24, 2009 at 05:04:52PM +0300, Avi Kivity wrote:
 Marcelo Tosatti wrote:
 Get rid of kvm-lock dependency on coalesced_mmio methods. Use an  
 atomic variable instead to guarantee only one vcpu is batching
 data into the ring at a given time.

 Signed-off-by: Marcelo Tosatti mtosa...@redhat.com

 Index: kvm-irqlock/virt/kvm/coalesced_mmio.c
 ===
 --- kvm-irqlock.orig/virt/kvm/coalesced_mmio.c
 +++ kvm-irqlock/virt/kvm/coalesced_mmio.c
 @@ -26,9 +26,12 @@ static int coalesced_mmio_in_range(struc
  if (!is_write)
  return 0;
  -   /* kvm-lock is taken by the caller and must be not released before
 - * dev.read/write
 - */
 +/*
 + * Some other vcpu might be batching data into the ring,
 + * fallback to userspace. Ordering not our problem.
 + */
 +if (!atomic_add_unless(dev-in_use, 1, 1))
 +return 0;


 Ordering with simultaneous writes is indeed not our problem, but the  
 ring may contain ordered writes (even by the same vcpu!)

You mean writes by a vcpu should maintain ordering even when that vcpu
migrates to a different pcpu? 

The smp_wmb in coalesced_write guarantees that.

 Suggest our own lock here.  in_use is basically a homemade lock, better  
 to use the factory made ones which come with a warranty.

The first submission had a mutex but was considered unorthodox. Although
i agree with your argument made then, i don't see a way around that.

Some pseudocode please? 

Agree with the suggestion on patch 3, will fix the commentary on
kvm_host.h.

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-24 Thread Avi Kivity

Marcelo Tosatti wrote:
Get rid of kvm-lock dependency on coalesced_mmio methods. Use an 
atomic variable instead to guarantee only one vcpu is batching

data into the ring at a given time.

Signed-off-by: Marcelo Tosatti mtosa...@redhat.com

Index: kvm-irqlock/virt/kvm/coalesced_mmio.c
===
--- kvm-irqlock.orig/virt/kvm/coalesced_mmio.c
+++ kvm-irqlock/virt/kvm/coalesced_mmio.c
@@ -26,9 +26,12 @@ static int coalesced_mmio_in_range(struc
if (!is_write)
return 0;
 
-	/* kvm-lock is taken by the caller and must be not released before

- * dev.read/write
- */
+   /*
+* Some other vcpu might be batching data into the ring,
+* fallback to userspace. Ordering not our problem.
+*/
+   if (!atomic_add_unless(dev-in_use, 1, 1))
+   return 0;
 
  


Ordering with simultaneous writes is indeed not our problem, but the 
ring may contain ordered writes (even by the same vcpu!)


Suggest our own lock here.  in_use is basically a homemade lock, better 
to use the factory made ones which come with a warranty.



--
error compiling committee.c: too many arguments to function

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-20 Thread Avi Kivity

Marcelo Tosatti wrote:

Signed-off-by: Marcelo Tosatti mtosa...@redhat.com

Index: kvm/virt/kvm/coalesced_mmio.c
===
--- kvm.orig/virt/kvm/coalesced_mmio.c
+++ kvm/virt/kvm/coalesced_mmio.c
@@ -26,9 +26,10 @@ static int coalesced_mmio_in_range(struc
if (!is_write)
return 0;
 
-	/* kvm-lock is taken by the caller and must be not released before

- * dev.read/write
- */
+   /*
+* dev-lock must not be released before coalesced_mmio_write.
+*/
+   mutex_lock(dev-lock);
 
 	/* Are we able to batch it ? */
 
@@ -41,6 +42,7 @@ static int coalesced_mmio_in_range(struc

KVM_COALESCED_MMIO_MAX;
if (next == dev-kvm-coalesced_mmio_ring-first) {
/* full */
+   mutex_unlock(dev-lock);
return 0;
}
 
@@ -57,6 +59,7 @@ static int coalesced_mmio_in_range(struc

addr + len = zone-addr + zone-size)
return 1;
}
+   mutex_unlock(dev-lock);
return 0;
 }
  


So we have a function that takes a lock and conditionally releases it?


--
error compiling committee.c: too many arguments to function

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-20 Thread Marcelo Tosatti
On Wed, May 20, 2009 at 03:06:26PM +0300, Avi Kivity wrote:
 Marcelo Tosatti wrote:
 Signed-off-by: Marcelo Tosatti mtosa...@redhat.com

 Index: kvm/virt/kvm/coalesced_mmio.c
 ===
 --- kvm.orig/virt/kvm/coalesced_mmio.c
 +++ kvm/virt/kvm/coalesced_mmio.c
 @@ -26,9 +26,10 @@ static int coalesced_mmio_in_range(struc
  if (!is_write)
  return 0;
  -   /* kvm-lock is taken by the caller and must be not released before
 - * dev.read/write
 - */
 +/*
 + * dev-lock must not be released before coalesced_mmio_write.
 + */
 +mutex_lock(dev-lock);
  /* Are we able to batch it ? */
  @@ -41,6 +42,7 @@ static int coalesced_mmio_in_range(struc
  KVM_COALESCED_MMIO_MAX;
  if (next == dev-kvm-coalesced_mmio_ring-first) {
  /* full */
 +mutex_unlock(dev-lock);
  return 0;
  }
  @@ -57,6 +59,7 @@ static int coalesced_mmio_in_range(struc
  addr + len = zone-addr + zone-size)
  return 1;
  }
 +mutex_unlock(dev-lock);
  return 0;
  }
   

 So we have a function that takes a lock and conditionally releases it?

Yes, but it is correct: it will only return with the lock held in case
it returns 1, in which case its guaranteed -write will be called (which
will unlock it).

It should check the range first and/or use some smarter synchronization,
but one thing at a time.

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-20 Thread Avi Kivity

Marcelo Tosatti wrote:

 


So we have a function that takes a lock and conditionally releases it?



Yes, but it is correct: it will only return with the lock held in case
it returns 1, in which case its guaranteed -write will be called (which
will unlock it).

It should check the range first and/or use some smarter synchronization,
but one thing at a time.
  


Yes it's correct but we'll get an endless stream of patches to 'fix' it 
because it is so unorthodox.


--
error compiling committee.c: too many arguments to function

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-20 Thread Marcelo Tosatti
On Wed, May 20, 2009 at 05:29:23PM +0300, Avi Kivity wrote:
 Marcelo Tosatti wrote:

  

 So we have a function that takes a lock and conditionally releases it?
 

 Yes, but it is correct: it will only return with the lock held in case
 it returns 1, in which case its guaranteed -write will be called (which
 will unlock it).

 It should check the range first and/or use some smarter synchronization,
 but one thing at a time.
   

 Yes it's correct but we'll get an endless stream of patches to 'fix' it  
 because it is so unorthodox.

Does it have to guarantee any kind of ordering in case of parallel
writes by distincting vcpus? This is what it does now (so if a vcpu
arrives first, the second will wait until the first is finished
processing).

I suppose that is the responsability of the guest (if it does MMIO
writes to a device in parallel it'll screwup in real HW too).

Because in such case, you can drop the mutex and protect only the kvm
data.


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-20 Thread Avi Kivity

Marcelo Tosatti wrote:

 

Yes it's correct but we'll get an endless stream of patches to 'fix' it  
because it is so unorthodox.



Does it have to guarantee any kind of ordering in case of parallel
writes by distincting vcpus? This is what it does now (so if a vcpu
arrives first, the second will wait until the first is finished
processing).
  


No.


I suppose that is the responsability of the guest (if it does MMIO
writes to a device in parallel it'll screwup in real HW too).
  


Yes.


Because in such case, you can drop the mutex and protect only the kvm
data.
  


One has to be before the other.  The order doesn't matter, but both have 
to be there.


--
error compiling committee.c: too many arguments to function

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-20 Thread Marcelo Tosatti
On Wed, May 20, 2009 at 12:13:03PM -0300, Marcelo Tosatti wrote:
 On Wed, May 20, 2009 at 05:29:23PM +0300, Avi Kivity wrote:
  Marcelo Tosatti wrote:
 
   
 
  So we have a function that takes a lock and conditionally releases it?
  
 
  Yes, but it is correct: it will only return with the lock held in case
  it returns 1, in which case its guaranteed -write will be called (which
  will unlock it).
 
  It should check the range first and/or use some smarter synchronization,
  but one thing at a time.

 
  Yes it's correct but we'll get an endless stream of patches to 'fix' it  
  because it is so unorthodox.
 
 Does it have to guarantee any kind of ordering in case of parallel
 writes by distincting vcpus? This is what it does now (so if a vcpu
 arrives first, the second will wait until the first is finished
 processing).
 
 I suppose that is the responsability of the guest (if it does MMIO
 writes to a device in parallel it'll screwup in real HW too).
 
 Because in such case, you can drop the mutex and protect only the kvm
 data.

If you want it to provide ordering (as in process the MMIO writes, by
multiple vcpus, in the order they happen), you need a mutex or spinlock.

And in that case, I don't see any other way around this given the way
-in_range / -read/-write work.

Even if you change the order in which the full mmio buffer check and 
coalesced-allowed-in-this-range happen you still need a spinlock/mutex 
in this unorthodox way. 
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-20 Thread Marcelo Tosatti
Get rid of kvm-lock dependency on coalesced_mmio methods. Use an 
atomic variable instead to guarantee only one vcpu is batching
data into the ring at a given time.

Signed-off-by: Marcelo Tosatti mtosa...@redhat.com

Index: kvm-irqlock/virt/kvm/coalesced_mmio.c
===
--- kvm-irqlock.orig/virt/kvm/coalesced_mmio.c
+++ kvm-irqlock/virt/kvm/coalesced_mmio.c
@@ -26,9 +26,12 @@ static int coalesced_mmio_in_range(struc
if (!is_write)
return 0;
 
-   /* kvm-lock is taken by the caller and must be not released before
- * dev.read/write
- */
+   /*
+* Some other vcpu might be batching data into the ring,
+* fallback to userspace. Ordering not our problem.
+*/
+   if (!atomic_add_unless(dev-in_use, 1, 1))
+   return 0;
 
/* Are we able to batch it ? */
 
@@ -41,7 +44,7 @@ static int coalesced_mmio_in_range(struc
KVM_COALESCED_MMIO_MAX;
if (next == dev-kvm-coalesced_mmio_ring-first) {
/* full */
-   return 0;
+   goto out_denied;
}
 
/* is it in a batchable area ? */
@@ -57,6 +60,8 @@ static int coalesced_mmio_in_range(struc
addr + len = zone-addr + zone-size)
return 1;
}
+out_denied:
+   atomic_set(dev-in_use, 0);
return 0;
 }
 
@@ -67,15 +72,14 @@ static void coalesced_mmio_write(struct 
(struct kvm_coalesced_mmio_dev*)this-private;
struct kvm_coalesced_mmio_ring *ring = dev-kvm-coalesced_mmio_ring;
 
-   /* kvm-lock must be taken by caller before call to in_range()*/
-
/* copy data in first free entry of the ring */
 
ring-coalesced_mmio[ring-last].phys_addr = addr;
ring-coalesced_mmio[ring-last].len = len;
memcpy(ring-coalesced_mmio[ring-last].data, val, len);
-   smp_wmb();
ring-last = (ring-last + 1) % KVM_COALESCED_MMIO_MAX;
+   smp_wmb();
+   atomic_set(dev-in_use, 0);
 }
 
 static void coalesced_mmio_destructor(struct kvm_io_device *this)
@@ -90,6 +94,8 @@ int kvm_coalesced_mmio_init(struct kvm *
dev = kzalloc(sizeof(struct kvm_coalesced_mmio_dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
+   atomic_set(dev-in_use, 0);
+
dev-dev.write  = coalesced_mmio_write;
dev-dev.in_range  = coalesced_mmio_in_range;
dev-dev.destructor  = coalesced_mmio_destructor;
Index: kvm-irqlock/virt/kvm/coalesced_mmio.h
===
--- kvm-irqlock.orig/virt/kvm/coalesced_mmio.h
+++ kvm-irqlock/virt/kvm/coalesced_mmio.h
@@ -12,6 +12,7 @@
 struct kvm_coalesced_mmio_dev {
struct kvm_io_device dev;
struct kvm *kvm;
+   atomic_t in_use;
int nb_zones;
struct kvm_coalesced_mmio_zone zone[KVM_COALESCED_MMIO_ZONE_MAX];
 };

-- 

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[patch 2/4] KVM: move coalesced_mmio locking to its own device

2009-05-18 Thread Marcelo Tosatti
Signed-off-by: Marcelo Tosatti mtosa...@redhat.com

Index: kvm/virt/kvm/coalesced_mmio.c
===
--- kvm.orig/virt/kvm/coalesced_mmio.c
+++ kvm/virt/kvm/coalesced_mmio.c
@@ -26,9 +26,10 @@ static int coalesced_mmio_in_range(struc
if (!is_write)
return 0;
 
-   /* kvm-lock is taken by the caller and must be not released before
- * dev.read/write
- */
+   /*
+* dev-lock must not be released before coalesced_mmio_write.
+*/
+   mutex_lock(dev-lock);
 
/* Are we able to batch it ? */
 
@@ -41,6 +42,7 @@ static int coalesced_mmio_in_range(struc
KVM_COALESCED_MMIO_MAX;
if (next == dev-kvm-coalesced_mmio_ring-first) {
/* full */
+   mutex_unlock(dev-lock);
return 0;
}
 
@@ -57,6 +59,7 @@ static int coalesced_mmio_in_range(struc
addr + len = zone-addr + zone-size)
return 1;
}
+   mutex_unlock(dev-lock);
return 0;
 }
 
@@ -67,8 +70,6 @@ static void coalesced_mmio_write(struct 
(struct kvm_coalesced_mmio_dev*)this-private;
struct kvm_coalesced_mmio_ring *ring = dev-kvm-coalesced_mmio_ring;
 
-   /* kvm-lock must be taken by caller before call to in_range()*/
-
/* copy data in first free entry of the ring */
 
ring-coalesced_mmio[ring-last].phys_addr = addr;
@@ -76,6 +77,7 @@ static void coalesced_mmio_write(struct 
memcpy(ring-coalesced_mmio[ring-last].data, val, len);
smp_wmb();
ring-last = (ring-last + 1) % KVM_COALESCED_MMIO_MAX;
+   mutex_unlock(dev-lock);
 }
 
 static void coalesced_mmio_destructor(struct kvm_io_device *this)
@@ -90,6 +92,8 @@ int kvm_coalesced_mmio_init(struct kvm *
dev = kzalloc(sizeof(struct kvm_coalesced_mmio_dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
+   mutex_init(dev-lock);
+
dev-dev.write  = coalesced_mmio_write;
dev-dev.in_range  = coalesced_mmio_in_range;
dev-dev.destructor  = coalesced_mmio_destructor;
@@ -109,16 +113,16 @@ int kvm_vm_ioctl_register_coalesced_mmio
if (dev == NULL)
return -EINVAL;
 
-   mutex_lock(kvm-lock);
+   mutex_lock(dev-lock);
if (dev-nb_zones = KVM_COALESCED_MMIO_ZONE_MAX) {
-   mutex_unlock(kvm-lock);
+   mutex_unlock(dev-lock);
return -ENOBUFS;
}
 
dev-zone[dev-nb_zones] = *zone;
dev-nb_zones++;
 
-   mutex_unlock(kvm-lock);
+   mutex_unlock(dev-lock);
return 0;
 }
 
@@ -132,7 +136,7 @@ int kvm_vm_ioctl_unregister_coalesced_mm
if (dev == NULL)
return -EINVAL;
 
-   mutex_lock(kvm-lock);
+   mutex_lock(dev-lock);
 
i = dev-nb_zones;
while(i) {
@@ -150,7 +154,7 @@ int kvm_vm_ioctl_unregister_coalesced_mm
i--;
}
 
-   mutex_unlock(kvm-lock);
+   mutex_unlock(dev-lock);
 
return 0;
 }
Index: kvm/virt/kvm/coalesced_mmio.h
===
--- kvm.orig/virt/kvm/coalesced_mmio.h
+++ kvm/virt/kvm/coalesced_mmio.h
@@ -12,6 +12,7 @@
 struct kvm_coalesced_mmio_dev {
struct kvm_io_device dev;
struct kvm *kvm;
+   struct mutex lock;
int nb_zones;
struct kvm_coalesced_mmio_zone zone[KVM_COALESCED_MMIO_ZONE_MAX];
 };

-- 

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html