public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] KVM: enable ioeventfd cookies
@ 2013-07-03  8:56 Cornelia Huck
  2013-07-03  8:56 ` [PATCH 1/2] KVM: kvm-io: support cookies Cornelia Huck
  2013-07-03  8:56 ` [PATCH 2/2] KVM: s390: use cookies for ioeventfd Cornelia Huck
  0 siblings, 2 replies; 9+ messages in thread
From: Cornelia Huck @ 2013-07-03  8:56 UTC (permalink / raw)
  To: Gleb Natapov, Paolo Bonzini
  Cc: Christian Borntraeger, Heiko Carstens, Martin Schwidefsky, KVM,
	linux-s390

Hi,

the following two patches enable cookies to speed up lookups for
virtio-ccw ioeventfds on s390. I originally wrote that code when I
enabled ioeventfds back in March, but wanted to run it through some
testing before submitting it and then promptly forgot to post it again.

As this has been well tested by our internal test team :), I'd like to
see it applied now.

Cornelia Huck (2):
  KVM: kvm-io: support cookies
  KVM: s390: use cookies for ioeventfd

 arch/s390/kvm/diag.c     | 17 ++++++++++++++---
 include/linux/kvm_host.h |  2 ++
 virt/kvm/kvm_main.c      | 44 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 3 deletions(-)

-- 
1.8.2.2


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/2] KVM: kvm-io: support cookies
  2013-07-03  8:56 [PATCH 0/2] KVM: enable ioeventfd cookies Cornelia Huck
@ 2013-07-03  8:56 ` Cornelia Huck
  2013-07-03  9:05   ` Paolo Bonzini
  2013-07-03  8:56 ` [PATCH 2/2] KVM: s390: use cookies for ioeventfd Cornelia Huck
  1 sibling, 1 reply; 9+ messages in thread
From: Cornelia Huck @ 2013-07-03  8:56 UTC (permalink / raw)
  To: Gleb Natapov, Paolo Bonzini
  Cc: Christian Borntraeger, Heiko Carstens, Martin Schwidefsky, KVM,
	linux-s390

Add a new function kvm_io_bus_write_cookie() that allows users of the
kvm io infrastructure to use a cookie value to speed up lookup of a
device on an io bus.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 include/linux/kvm_host.h |  2 ++
 virt/kvm/kvm_main.c      | 44 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index e3aae6d..2d298fc 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -159,6 +159,8 @@ enum kvm_bus {
 
 int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 		     int len, const void *val);
+int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			    int len, const void *val, long *cookie);
 int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len,
 		    void *val);
 int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 1580dd4..222475a 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2891,6 +2891,50 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 	return -EOPNOTSUPP;
 }
 
+/* kvm_io_bus_write_cookie - called under kvm->slots_lock */
+int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			    int len, const void *val, long *cookie)
+{
+	int idx, ret = -EOPNOTSUPP;
+	struct kvm_io_bus *bus;
+	struct kvm_io_range range;
+
+	range = (struct kvm_io_range) {
+		.addr = addr,
+		.len = len,
+	};
+
+	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
+
+	/* First try the device referenced by *cookie. */
+	if ((*cookie >= 0) && (*cookie < bus->dev_count) &&
+	    (kvm_io_bus_sort_cmp(&range, &bus->range[*cookie]) == 0))
+		if (!kvm_iodevice_write(bus->range[*cookie].dev, addr, len,
+					val))
+			return 0;
+
+	/*
+	 * *cookie contained garbage; fall back to search and return the
+	 * correct value in *cookie.
+	 */
+	idx = kvm_io_bus_get_first_dev(bus, addr, len);
+	if (idx < 0)
+		goto out;
+
+	while (idx < bus->dev_count &&
+		kvm_io_bus_sort_cmp(&range, &bus->range[idx]) == 0) {
+		if (!kvm_iodevice_write(bus->range[idx].dev, addr, len, val)) {
+			ret = 0;
+			goto out;
+		}
+		idx++;
+	}
+	idx = -ENOENT;
+out:
+	*cookie = idx;
+	return ret;
+}
+
 /* kvm_io_bus_read - called under kvm->slots_lock */
 int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 		    int len, void *val)
-- 
1.8.2.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/2] KVM: s390: use cookies for ioeventfd
  2013-07-03  8:56 [PATCH 0/2] KVM: enable ioeventfd cookies Cornelia Huck
  2013-07-03  8:56 ` [PATCH 1/2] KVM: kvm-io: support cookies Cornelia Huck
@ 2013-07-03  8:56 ` Cornelia Huck
  1 sibling, 0 replies; 9+ messages in thread
From: Cornelia Huck @ 2013-07-03  8:56 UTC (permalink / raw)
  To: Gleb Natapov, Paolo Bonzini
  Cc: Christian Borntraeger, Heiko Carstens, Martin Schwidefsky, KVM,
	linux-s390

Make use of cookies for the virtio ccw notification hypercall to speed up
lookup of devices on the io bus.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 arch/s390/kvm/diag.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
index 3074475..2a467bf 100644
--- a/arch/s390/kvm/diag.c
+++ b/arch/s390/kvm/diag.c
@@ -108,22 +108,33 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
 static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu)
 {
 	int ret, idx;
+	long cookie;
 
 	/* No virtio-ccw notification? Get out quickly. */
 	if (!vcpu->kvm->arch.css_support ||
 	    (vcpu->run->s.regs.gprs[1] != KVM_S390_VIRTIO_CCW_NOTIFY))
 		return -EOPNOTSUPP;
 
+	cookie = vcpu->run->s.regs.gprs[4];
 	idx = srcu_read_lock(&vcpu->kvm->srcu);
 	/*
 	 * The layout is as follows:
 	 * - gpr 2 contains the subchannel id (passed as addr)
 	 * - gpr 3 contains the virtqueue index (passed as datamatch)
+	 * - gpr 4 contains the index on the bus (optionally)
 	 */
-	ret = kvm_io_bus_write(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS,
-				vcpu->run->s.regs.gprs[2],
-				8, &vcpu->run->s.regs.gprs[3]);
+	ret = kvm_io_bus_write_cookie(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS,
+				      vcpu->run->s.regs.gprs[2],
+				      8, &vcpu->run->s.regs.gprs[3],
+				      &cookie);
 	srcu_read_unlock(&vcpu->kvm->srcu, idx);
+
+	/*
+	 * Return cookie in gpr 2, but don't overwrite the register if the
+	 * diagnose will be handled by userspace.
+	 */
+	if (ret != -EOPNOTSUPP)
+		vcpu->run->s.regs.gprs[2] = cookie;
 	/* kvm_io_bus_write returns -EOPNOTSUPP if it found no match. */
 	return ret < 0 ? ret : 0;
 }
-- 
1.8.2.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] KVM: kvm-io: support cookies
  2013-07-03  8:56 ` [PATCH 1/2] KVM: kvm-io: support cookies Cornelia Huck
@ 2013-07-03  9:05   ` Paolo Bonzini
  2013-07-03  9:21     ` Paolo Bonzini
  0 siblings, 1 reply; 9+ messages in thread
From: Paolo Bonzini @ 2013-07-03  9:05 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: Gleb Natapov, Christian Borntraeger, Heiko Carstens,
	Martin Schwidefsky, KVM, linux-s390

Il 03/07/2013 10:56, Cornelia Huck ha scritto:
> Add a new function kvm_io_bus_write_cookie() that allows users of the
> kvm io infrastructure to use a cookie value to speed up lookup of a
> device on an io bus.
> 
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---
>  include/linux/kvm_host.h |  2 ++
>  virt/kvm/kvm_main.c      | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 46 insertions(+)
> 
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index e3aae6d..2d298fc 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -159,6 +159,8 @@ enum kvm_bus {
>  
>  int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  		     int len, const void *val);
> +int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +			    int len, const void *val, long *cookie);
>  int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len,
>  		    void *val);
>  int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 1580dd4..222475a 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2891,6 +2891,50 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  	return -EOPNOTSUPP;
>  }
>  
> +/* kvm_io_bus_write_cookie - called under kvm->slots_lock */
> +int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +			    int len, const void *val, long *cookie)
> +{
> +	int idx, ret = -EOPNOTSUPP;
> +	struct kvm_io_bus *bus;
> +	struct kvm_io_range range;
> +
> +	range = (struct kvm_io_range) {
> +		.addr = addr,
> +		.len = len,
> +	};
> +
> +	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
> +
> +	/* First try the device referenced by *cookie. */
> +	if ((*cookie >= 0) && (*cookie < bus->dev_count) &&
> +	    (kvm_io_bus_sort_cmp(&range, &bus->range[*cookie]) == 0))
> +		if (!kvm_iodevice_write(bus->range[*cookie].dev, addr, len,
> +					val))
> +			return 0;

Nice idea, though I don't really like the duplication between
kvm_io_bus_write and kvm_io_bus_write_cookie.

Can you make kvm_io_bus_write, and perhaps kvm_io_bus_read too, return
the cookie, and return -EINVAL here if the cookie is garbage?
(Unfortunately, most callers of kvm_io_bus_read/write expect them to
never return a value that is >= 0, but there aren't many so it's easily
solved).

Paolo

> +
> +	/*
> +	 * *cookie contained garbage; fall back to search and return the
> +	 * correct value in *cookie.
> +	 */
> +	idx = kvm_io_bus_get_first_dev(bus, addr, len);
> +	if (idx < 0)
> +		goto out;
> +
> +	while (idx < bus->dev_count &&
> +		kvm_io_bus_sort_cmp(&range, &bus->range[idx]) == 0) {
> +		if (!kvm_iodevice_write(bus->range[idx].dev, addr, len, val)) {
> +			ret = 0;
> +			goto out;
> +		}
> +		idx++;
> +	}
> +	idx = -ENOENT;
> +out:
> +	*cookie = idx;
> +	return ret;
> +}
> +
>  /* kvm_io_bus_read - called under kvm->slots_lock */
>  int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  		    int len, void *val)
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] KVM: kvm-io: support cookies
  2013-07-03  9:05   ` Paolo Bonzini
@ 2013-07-03  9:21     ` Paolo Bonzini
  2013-07-03 10:51       ` Cornelia Huck
  0 siblings, 1 reply; 9+ messages in thread
From: Paolo Bonzini @ 2013-07-03  9:21 UTC (permalink / raw)
  Cc: Cornelia Huck, Gleb Natapov, Christian Borntraeger,
	Heiko Carstens, Martin Schwidefsky, KVM, linux-s390

Il 03/07/2013 11:05, Paolo Bonzini ha scritto:
> Nice idea, though I don't really like the duplication between
> kvm_io_bus_write and kvm_io_bus_write_cookie.
> 
> Can you make kvm_io_bus_write, and perhaps kvm_io_bus_read too, return
> the cookie, and return -EINVAL here if the cookie is garbage?

On second though---no need to return -EINVAL, you can just pass the
cookie by value and tail-call kvm_io_bus_write.  Whatever makes the s390
code look nicer.

Paolo

> (Unfortunately, most callers of kvm_io_bus_read/write expect them to
> never return a value that is >= 0, but there aren't many so it's easily
> solved).


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] KVM: kvm-io: support cookies
  2013-07-03  9:21     ` Paolo Bonzini
@ 2013-07-03 10:51       ` Cornelia Huck
  2013-07-03 10:58         ` Paolo Bonzini
  0 siblings, 1 reply; 9+ messages in thread
From: Cornelia Huck @ 2013-07-03 10:51 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Gleb Natapov, Christian Borntraeger, Heiko Carstens,
	Martin Schwidefsky, KVM, linux-s390

On Wed, 03 Jul 2013 11:21:23 +0200
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Il 03/07/2013 11:05, Paolo Bonzini ha scritto:
> > Nice idea, though I don't really like the duplication between
> > kvm_io_bus_write and kvm_io_bus_write_cookie.
> > 
> > Can you make kvm_io_bus_write, and perhaps kvm_io_bus_read too, return
> > the cookie, and return -EINVAL here if the cookie is garbage?
> 
> On second though---no need to return -EINVAL, you can just pass the
> cookie by value and tail-call kvm_io_bus_write.  Whatever makes the s390
> code look nicer.

It would probably be easier to have the non-cookie functions call the
cookie functions with a negative cookie value, like the following
(untested):

>From 12a6e9821f1a07ecd918e927a4049263ad6f1724 Mon Sep 17 00:00:00 2001
From: Cornelia Huck <cornelia.huck@de.ibm.com>
Date: Tue, 2 Jul 2013 13:30:56 +0200
Subject: [PATCH] KVM: kvm-io: support cookies

Add new functions kvm_io_bus_{read,write}_cookie() that allows users of
the kvm io infrastructure to use a cookie value to speed up lookup of a
device on an io bus.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 include/linux/kvm_host.h |  4 +++
 virt/kvm/kvm_main.c      | 82 ++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 70 insertions(+), 16 deletions(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index e3aae6d..97849fc 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -159,8 +159,12 @@ enum kvm_bus {
 
 int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 		     int len, const void *val);
+int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			    int len, const void *val, long *cookie);
 int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len,
 		    void *val);
+int kvm_io_bus_read_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			   int len, void *val, long *cookie);
 int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 			    int len, struct kvm_io_device *dev);
 int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 1580dd4..21e6d7d 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2863,11 +2863,11 @@ static int kvm_io_bus_get_first_dev(struct kvm_io_bus *bus,
 	return off;
 }
 
-/* kvm_io_bus_write - called under kvm->slots_lock */
-int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
-		     int len, const void *val)
+/* kvm_io_bus_write_cookie - called under kvm->slots_lock */
+int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			    int len, const void *val, long *cookie)
 {
-	int idx;
+	int idx, ret = -EOPNOTSUPP;
 	struct kvm_io_bus *bus;
 	struct kvm_io_range range;
 
@@ -2877,25 +2877,50 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 	};
 
 	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
+
+	/* First try the device referenced by *cookie. */
+	if ((*cookie >= 0) && (*cookie < bus->dev_count) &&
+	    (kvm_io_bus_sort_cmp(&range, &bus->range[*cookie]) == 0))
+		if (!kvm_iodevice_write(bus->range[*cookie].dev, addr, len,
+					val))
+			return 0;
+
+	/*
+	 * *cookie contained garbage; fall back to search and return the
+	 * correct value in *cookie.
+	 */
 	idx = kvm_io_bus_get_first_dev(bus, addr, len);
 	if (idx < 0)
-		return -EOPNOTSUPP;
+		goto out;
 
 	while (idx < bus->dev_count &&
 		kvm_io_bus_sort_cmp(&range, &bus->range[idx]) == 0) {
-		if (!kvm_iodevice_write(bus->range[idx].dev, addr, len, val))
-			return 0;
+		if (!kvm_iodevice_write(bus->range[idx].dev, addr, len, val)) {
+			ret = 0;
+			goto out;
+		}
 		idx++;
 	}
+	idx = -ENOENT;
+out:
+	*cookie = idx;
+	return ret;
+}
+
+/* kvm_io_bus_write - called under kvm->slots_lock */
+int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+		     int len, const void *val)
+{
+	long tmp = -1;
 
-	return -EOPNOTSUPP;
+	return kvm_io_bus_write_cookie(kvm, bus_idx, addr, len, val, &tmp);
 }
 
-/* kvm_io_bus_read - called under kvm->slots_lock */
-int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
-		    int len, void *val)
+/* kvm_io_bus_read_cookie - called under kvm->slots_lock */
+int kvm_io_bus_read_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			   int len, void *val, long *cookie)
 {
-	int idx;
+	int idx, ret = -EOPNOTSUPP;
 	struct kvm_io_bus *bus;
 	struct kvm_io_range range;
 
@@ -2905,18 +2930,43 @@ int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 	};
 
 	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
+
+	/* First try the device referenced by *cookie. */
+	if ((*cookie >= 0) && (*cookie < bus->dev_count) &&
+	    (kvm_io_bus_sort_cmp(&range, &bus->range[*cookie]) == 0))
+		if (!kvm_iodevice_read(bus->range[*cookie].dev, addr, len,
+				       val))
+			return 0;
+
+	/*
+	 * *cookie contained garbage; fall back to search and return the
+	 * correct value in *cookie.
+	 */
 	idx = kvm_io_bus_get_first_dev(bus, addr, len);
 	if (idx < 0)
-		return -EOPNOTSUPP;
+		goto out;
 
 	while (idx < bus->dev_count &&
 		kvm_io_bus_sort_cmp(&range, &bus->range[idx]) == 0) {
-		if (!kvm_iodevice_read(bus->range[idx].dev, addr, len, val))
-			return 0;
+		if (!kvm_iodevice_read(bus->range[idx].dev, addr, len, val)) {
+			ret = 0;
+			goto out;
+		}
 		idx++;
 	}
+	idx = -ENOENT;
+out:
+	*cookie = idx;
+	return ret;
+}
+
+/* kvm_io_bus_read - called under kvm->slots_lock */
+int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+		    int len, void *val)
+{
+	long tmp = -1;
 
-	return -EOPNOTSUPP;
+	return kvm_io_bus_read_cookie(kvm, bus_idx, addr, len, val, &tmp);
 }
 
 /* Caller must hold slots_lock. */
-- 
1.8.2.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] KVM: kvm-io: support cookies
  2013-07-03 10:51       ` Cornelia Huck
@ 2013-07-03 10:58         ` Paolo Bonzini
  2013-07-03 11:45           ` Cornelia Huck
  0 siblings, 1 reply; 9+ messages in thread
From: Paolo Bonzini @ 2013-07-03 10:58 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: Gleb Natapov, Christian Borntraeger, Heiko Carstens,
	Martin Schwidefsky, KVM, linux-s390

Il 03/07/2013 12:51, Cornelia Huck ha scritto:
> On Wed, 03 Jul 2013 11:21:23 +0200
> Paolo Bonzini <pbonzini@redhat.com> wrote:
> 
>> Il 03/07/2013 11:05, Paolo Bonzini ha scritto:
>>> Nice idea, though I don't really like the duplication between
>>> kvm_io_bus_write and kvm_io_bus_write_cookie.
>>>
>>> Can you make kvm_io_bus_write, and perhaps kvm_io_bus_read too, return
>>> the cookie, and return -EINVAL here if the cookie is garbage?
>>
>> On second though---no need to return -EINVAL, you can just pass the
>> cookie by value and tail-call kvm_io_bus_write.  Whatever makes the s390
>> code look nicer.
> 
> It would probably be easier to have the non-cookie functions call the
> cookie functions with a negative cookie value, like the following
> (untested):

That would work too, but it adds a small overhead to the non-cookie
calls.  If Gleb agrees with you, it is fine; otherwise, I'd prefer that
one explicitly requests the cookie on input.

Paolo

> From 12a6e9821f1a07ecd918e927a4049263ad6f1724 Mon Sep 17 00:00:00 2001
> From: Cornelia Huck <cornelia.huck@de.ibm.com>
> Date: Tue, 2 Jul 2013 13:30:56 +0200
> Subject: [PATCH] KVM: kvm-io: support cookies
> 
> Add new functions kvm_io_bus_{read,write}_cookie() that allows users of
> the kvm io infrastructure to use a cookie value to speed up lookup of a
> device on an io bus.
> 
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---
>  include/linux/kvm_host.h |  4 +++
>  virt/kvm/kvm_main.c      | 82 ++++++++++++++++++++++++++++++++++++++----------
>  2 files changed, 70 insertions(+), 16 deletions(-)
> 
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index e3aae6d..97849fc 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -159,8 +159,12 @@ enum kvm_bus {
>  
>  int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  		     int len, const void *val);
> +int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +			    int len, const void *val, long *cookie);
>  int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len,
>  		    void *val);
> +int kvm_io_bus_read_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +			   int len, void *val, long *cookie);
>  int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  			    int len, struct kvm_io_device *dev);
>  int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 1580dd4..21e6d7d 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2863,11 +2863,11 @@ static int kvm_io_bus_get_first_dev(struct kvm_io_bus *bus,
>  	return off;
>  }
>  
> -/* kvm_io_bus_write - called under kvm->slots_lock */
> -int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> -		     int len, const void *val)
> +/* kvm_io_bus_write_cookie - called under kvm->slots_lock */
> +int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +			    int len, const void *val, long *cookie)
>  {
> -	int idx;
> +	int idx, ret = -EOPNOTSUPP;
>  	struct kvm_io_bus *bus;
>  	struct kvm_io_range range;
>  
> @@ -2877,25 +2877,50 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  	};
>  
>  	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
> +
> +	/* First try the device referenced by *cookie. */
> +	if ((*cookie >= 0) && (*cookie < bus->dev_count) &&
> +	    (kvm_io_bus_sort_cmp(&range, &bus->range[*cookie]) == 0))
> +		if (!kvm_iodevice_write(bus->range[*cookie].dev, addr, len,
> +					val))
> +			return 0;
> +
> +	/*
> +	 * *cookie contained garbage; fall back to search and return the
> +	 * correct value in *cookie.
> +	 */
>  	idx = kvm_io_bus_get_first_dev(bus, addr, len);
>  	if (idx < 0)
> -		return -EOPNOTSUPP;
> +		goto out;
>  
>  	while (idx < bus->dev_count &&
>  		kvm_io_bus_sort_cmp(&range, &bus->range[idx]) == 0) {
> -		if (!kvm_iodevice_write(bus->range[idx].dev, addr, len, val))
> -			return 0;
> +		if (!kvm_iodevice_write(bus->range[idx].dev, addr, len, val)) {
> +			ret = 0;
> +			goto out;
> +		}
>  		idx++;
>  	}
> +	idx = -ENOENT;
> +out:
> +	*cookie = idx;
> +	return ret;
> +}
> +
> +/* kvm_io_bus_write - called under kvm->slots_lock */
> +int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +		     int len, const void *val)
> +{
> +	long tmp = -1;
>  
> -	return -EOPNOTSUPP;
> +	return kvm_io_bus_write_cookie(kvm, bus_idx, addr, len, val, &tmp);
>  }
>  
> -/* kvm_io_bus_read - called under kvm->slots_lock */
> -int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> -		    int len, void *val)
> +/* kvm_io_bus_read_cookie - called under kvm->slots_lock */
> +int kvm_io_bus_read_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +			   int len, void *val, long *cookie)
>  {
> -	int idx;
> +	int idx, ret = -EOPNOTSUPP;
>  	struct kvm_io_bus *bus;
>  	struct kvm_io_range range;
>  
> @@ -2905,18 +2930,43 @@ int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  	};
>  
>  	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
> +
> +	/* First try the device referenced by *cookie. */
> +	if ((*cookie >= 0) && (*cookie < bus->dev_count) &&
> +	    (kvm_io_bus_sort_cmp(&range, &bus->range[*cookie]) == 0))
> +		if (!kvm_iodevice_read(bus->range[*cookie].dev, addr, len,
> +				       val))
> +			return 0;
> +
> +	/*
> +	 * *cookie contained garbage; fall back to search and return the
> +	 * correct value in *cookie.
> +	 */
>  	idx = kvm_io_bus_get_first_dev(bus, addr, len);
>  	if (idx < 0)
> -		return -EOPNOTSUPP;
> +		goto out;
>  
>  	while (idx < bus->dev_count &&
>  		kvm_io_bus_sort_cmp(&range, &bus->range[idx]) == 0) {
> -		if (!kvm_iodevice_read(bus->range[idx].dev, addr, len, val))
> -			return 0;
> +		if (!kvm_iodevice_read(bus->range[idx].dev, addr, len, val)) {
> +			ret = 0;
> +			goto out;
> +		}
>  		idx++;
>  	}
> +	idx = -ENOENT;
> +out:
> +	*cookie = idx;
> +	return ret;
> +}
> +
> +/* kvm_io_bus_read - called under kvm->slots_lock */
> +int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +		    int len, void *val)
> +{
> +	long tmp = -1;
>  
> -	return -EOPNOTSUPP;
> +	return kvm_io_bus_read_cookie(kvm, bus_idx, addr, len, val, &tmp);
>  }
>  
>  /* Caller must hold slots_lock. */
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] KVM: kvm-io: support cookies
  2013-07-03 10:58         ` Paolo Bonzini
@ 2013-07-03 11:45           ` Cornelia Huck
  2013-07-03 11:46             ` Paolo Bonzini
  0 siblings, 1 reply; 9+ messages in thread
From: Cornelia Huck @ 2013-07-03 11:45 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Gleb Natapov, Christian Borntraeger, Heiko Carstens,
	Martin Schwidefsky, KVM, linux-s390

On Wed, 03 Jul 2013 12:58:00 +0200
Paolo Bonzini <pbonzini@redhat.com> wrote:

> Il 03/07/2013 12:51, Cornelia Huck ha scritto:
> > On Wed, 03 Jul 2013 11:21:23 +0200
> > Paolo Bonzini <pbonzini@redhat.com> wrote:
> > 
> >> Il 03/07/2013 11:05, Paolo Bonzini ha scritto:
> >>> Nice idea, though I don't really like the duplication between
> >>> kvm_io_bus_write and kvm_io_bus_write_cookie.
> >>>
> >>> Can you make kvm_io_bus_write, and perhaps kvm_io_bus_read too, return
> >>> the cookie, and return -EINVAL here if the cookie is garbage?
> >>
> >> On second though---no need to return -EINVAL, you can just pass the
> >> cookie by value and tail-call kvm_io_bus_write.  Whatever makes the s390
> >> code look nicer.
> > 
> > It would probably be easier to have the non-cookie functions call the
> > cookie functions with a negative cookie value, like the following
> > (untested):
> 
> That would work too, but it adds a small overhead to the non-cookie
> calls.  If Gleb agrees with you, it is fine; otherwise, I'd prefer that
> one explicitly requests the cookie on input.

Just to compare, I also did a patch that returns the index instead
(equally untested). Changing the callers was straightforward; we gain
an extra scu_dereference() in the invalid cookie case.

>From ff45cdc27e47020251f0100759adf372c19a29c4 Mon Sep 17 00:00:00 2001
From: Cornelia Huck <cornelia.huck@de.ibm.com>
Date: Tue, 2 Jul 2013 13:30:56 +0200
Subject: [PATCH 1/2] KVM: kvm-io: support cookies

Add new functions kvm_io_bus_{read,write}_cookie() that allows users of
the kvm io infrastructure to use a cookie value to speed up lookup of a
device on an io bus.

kvm_io_bus_{read,write} now returns the index on the bus; existing callers
have been fixed up to accept return codes > 0.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 arch/ia64/kvm/kvm-ia64.c   |  2 +-
 arch/powerpc/kvm/powerpc.c |  4 ++--
 arch/x86/kvm/x86.c         |  8 ++++---
 include/linux/kvm_host.h   |  4 ++++
 virt/kvm/kvm_main.c        | 58 +++++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 69 insertions(+), 7 deletions(-)

diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 5b2dc0d..465ab54 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -250,7 +250,7 @@ mmio:
 	else
 		r = kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, p->addr,
 				     p->size, &p->data);
-	if (r)
+	if (r < 0)
 		printk(KERN_ERR"kvm: No iodevice found! addr:%lx\n", p->addr);
 	p->state = STATE_IORESP_READY;
 
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 6316ee3..26c44d0 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -649,7 +649,7 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
 	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 
-	if (!ret) {
+	if (ret >= 0) {
 		kvmppc_complete_mmio_load(vcpu, run);
 		vcpu->mmio_needed = 0;
 		return EMULATE_DONE;
@@ -711,7 +711,7 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
 	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 
-	if (!ret) {
+	if (ret >= 0) {
 		vcpu->mmio_needed = 0;
 		return EMULATE_DONE;
 	}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 7d71c0f..62b325c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3860,7 +3860,8 @@ static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
 		n = min(len, 8);
 		if (!(vcpu->arch.apic &&
 		      !kvm_iodevice_write(&vcpu->arch.apic->dev, addr, n, v))
-		    && kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
+		    && (kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, n, v)
+			< 0))
 			break;
 		handled += n;
 		addr += n;
@@ -3880,7 +3881,8 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
 		n = min(len, 8);
 		if (!(vcpu->arch.apic &&
 		      !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, n, v))
-		    && kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
+		    && (kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v)
+			< 0))
 			break;
 		trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v);
 		handled += n;
@@ -4361,7 +4363,7 @@ static int kernel_pio(struct kvm_vcpu *vcpu, void *pd)
 		r = kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS,
 				     vcpu->arch.pio.port, vcpu->arch.pio.size,
 				     pd);
-	return r;
+	return (r >= 0) ? 0 : r;
 }
 
 static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index e3aae6d..60e261c9 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -159,8 +159,12 @@ enum kvm_bus {
 
 int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 		     int len, const void *val);
+int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			    int len, const void *val, long cookie);
 int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len,
 		    void *val);
+int kvm_io_bus_read_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			   int len, void *val, long cookie);
 int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 			    int len, struct kvm_io_device *dev);
 int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 1580dd4..ed34f10 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2884,13 +2884,41 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 	while (idx < bus->dev_count &&
 		kvm_io_bus_sort_cmp(&range, &bus->range[idx]) == 0) {
 		if (!kvm_iodevice_write(bus->range[idx].dev, addr, len, val))
-			return 0;
+			return idx;
 		idx++;
 	}
 
 	return -EOPNOTSUPP;
 }
 
+/* kvm_io_bus_write_cookie - called under kvm->slots_lock */
+int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			    int len, const void *val, long cookie)
+{
+	struct kvm_io_bus *bus;
+	struct kvm_io_range range;
+
+	range = (struct kvm_io_range) {
+		.addr = addr,
+		.len = len,
+	};
+
+	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
+
+	/* First try the device referenced by cookie. */
+	if ((cookie >= 0) && (cookie < bus->dev_count) &&
+	    (kvm_io_bus_sort_cmp(&range, &bus->range[cookie]) == 0))
+		if (!kvm_iodevice_write(bus->range[cookie].dev, addr, len,
+					val))
+			return cookie;
+
+	/*
+	 * cookie contained garbage; fall back to search and return the
+	 * correct cookie value.
+	 */
+	return kvm_io_bus_write(kvm, bus_idx, addr, len, val);
+}
+
 /* kvm_io_bus_read - called under kvm->slots_lock */
 int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 		    int len, void *val)
@@ -2919,6 +2947,34 @@ int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 	return -EOPNOTSUPP;
 }
 
+/* kvm_io_bus_read_cookie - called under kvm->slots_lock */
+int kvm_io_bus_read_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
+			   int len, void *val, long cookie)
+{
+	struct kvm_io_bus *bus;
+	struct kvm_io_range range;
+
+	range = (struct kvm_io_range) {
+		.addr = addr,
+		.len = len,
+	};
+
+	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
+
+	/* First try the device referenced by cookie. */
+	if ((cookie >= 0) && (cookie < bus->dev_count) &&
+	    (kvm_io_bus_sort_cmp(&range, &bus->range[cookie]) == 0))
+		if (!kvm_iodevice_read(bus->range[cookie].dev, addr, len,
+				       val))
+			return cookie;
+
+	/*
+	 * cookie contained garbage; fall back to search and return the
+	 * correct cookie value.
+	 */
+	return kvm_io_bus_read(kvm, bus_idx, addr, len, val);
+}
+
 /* Caller must hold slots_lock. */
 int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
 			    int len, struct kvm_io_device *dev)
-- 
1.8.2.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] KVM: kvm-io: support cookies
  2013-07-03 11:45           ` Cornelia Huck
@ 2013-07-03 11:46             ` Paolo Bonzini
  0 siblings, 0 replies; 9+ messages in thread
From: Paolo Bonzini @ 2013-07-03 11:46 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: Gleb Natapov, Christian Borntraeger, Heiko Carstens,
	Martin Schwidefsky, KVM, linux-s390

Il 03/07/2013 13:45, Cornelia Huck ha scritto:
> On Wed, 03 Jul 2013 12:58:00 +0200
> Paolo Bonzini <pbonzini@redhat.com> wrote:
> 
>> Il 03/07/2013 12:51, Cornelia Huck ha scritto:
>>> On Wed, 03 Jul 2013 11:21:23 +0200
>>> Paolo Bonzini <pbonzini@redhat.com> wrote:
>>>
>>>> Il 03/07/2013 11:05, Paolo Bonzini ha scritto:
>>>>> Nice idea, though I don't really like the duplication between
>>>>> kvm_io_bus_write and kvm_io_bus_write_cookie.
>>>>>
>>>>> Can you make kvm_io_bus_write, and perhaps kvm_io_bus_read too, return
>>>>> the cookie, and return -EINVAL here if the cookie is garbage?
>>>>
>>>> On second though---no need to return -EINVAL, you can just pass the
>>>> cookie by value and tail-call kvm_io_bus_write.  Whatever makes the s390
>>>> code look nicer.
>>>
>>> It would probably be easier to have the non-cookie functions call the
>>> cookie functions with a negative cookie value, like the following
>>> (untested):
>>
>> That would work too, but it adds a small overhead to the non-cookie
>> calls.  If Gleb agrees with you, it is fine; otherwise, I'd prefer that
>> one explicitly requests the cookie on input.
> 
> Just to compare, I also did a patch that returns the index instead
> (equally untested). Changing the callers was straightforward; we gain
> an extra scu_dereference() in the invalid cookie case.

This looks much nicer, thanks for putting up with me!

Paolo

> From ff45cdc27e47020251f0100759adf372c19a29c4 Mon Sep 17 00:00:00 2001
> From: Cornelia Huck <cornelia.huck@de.ibm.com>
> Date: Tue, 2 Jul 2013 13:30:56 +0200
> Subject: [PATCH 1/2] KVM: kvm-io: support cookies
> 
> Add new functions kvm_io_bus_{read,write}_cookie() that allows users of
> the kvm io infrastructure to use a cookie value to speed up lookup of a
> device on an io bus.
> 
> kvm_io_bus_{read,write} now returns the index on the bus; existing callers
> have been fixed up to accept return codes > 0.
> 
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---
>  arch/ia64/kvm/kvm-ia64.c   |  2 +-
>  arch/powerpc/kvm/powerpc.c |  4 ++--
>  arch/x86/kvm/x86.c         |  8 ++++---
>  include/linux/kvm_host.h   |  4 ++++
>  virt/kvm/kvm_main.c        | 58 +++++++++++++++++++++++++++++++++++++++++++++-
>  5 files changed, 69 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
> index 5b2dc0d..465ab54 100644
> --- a/arch/ia64/kvm/kvm-ia64.c
> +++ b/arch/ia64/kvm/kvm-ia64.c
> @@ -250,7 +250,7 @@ mmio:
>  	else
>  		r = kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, p->addr,
>  				     p->size, &p->data);
> -	if (r)
> +	if (r < 0)
>  		printk(KERN_ERR"kvm: No iodevice found! addr:%lx\n", p->addr);
>  	p->state = STATE_IORESP_READY;
>  
> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
> index 6316ee3..26c44d0 100644
> --- a/arch/powerpc/kvm/powerpc.c
> +++ b/arch/powerpc/kvm/powerpc.c
> @@ -649,7 +649,7 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
>  
>  	srcu_read_unlock(&vcpu->kvm->srcu, idx);
>  
> -	if (!ret) {
> +	if (ret >= 0) {
>  		kvmppc_complete_mmio_load(vcpu, run);
>  		vcpu->mmio_needed = 0;
>  		return EMULATE_DONE;
> @@ -711,7 +711,7 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
>  
>  	srcu_read_unlock(&vcpu->kvm->srcu, idx);
>  
> -	if (!ret) {
> +	if (ret >= 0) {
>  		vcpu->mmio_needed = 0;
>  		return EMULATE_DONE;
>  	}
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 7d71c0f..62b325c 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -3860,7 +3860,8 @@ static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
>  		n = min(len, 8);
>  		if (!(vcpu->arch.apic &&
>  		      !kvm_iodevice_write(&vcpu->arch.apic->dev, addr, n, v))
> -		    && kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
> +		    && (kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, n, v)
> +			< 0))
>  			break;
>  		handled += n;
>  		addr += n;
> @@ -3880,7 +3881,8 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
>  		n = min(len, 8);
>  		if (!(vcpu->arch.apic &&
>  		      !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, n, v))
> -		    && kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
> +		    && (kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v)
> +			< 0))
>  			break;
>  		trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v);
>  		handled += n;
> @@ -4361,7 +4363,7 @@ static int kernel_pio(struct kvm_vcpu *vcpu, void *pd)
>  		r = kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS,
>  				     vcpu->arch.pio.port, vcpu->arch.pio.size,
>  				     pd);
> -	return r;
> +	return (r >= 0) ? 0 : r;
>  }
>  
>  static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index e3aae6d..60e261c9 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -159,8 +159,12 @@ enum kvm_bus {
>  
>  int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  		     int len, const void *val);
> +int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +			    int len, const void *val, long cookie);
>  int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len,
>  		    void *val);
> +int kvm_io_bus_read_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +			   int len, void *val, long cookie);
>  int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  			    int len, struct kvm_io_device *dev);
>  int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 1580dd4..ed34f10 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2884,13 +2884,41 @@ int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  	while (idx < bus->dev_count &&
>  		kvm_io_bus_sort_cmp(&range, &bus->range[idx]) == 0) {
>  		if (!kvm_iodevice_write(bus->range[idx].dev, addr, len, val))
> -			return 0;
> +			return idx;
>  		idx++;
>  	}
>  
>  	return -EOPNOTSUPP;
>  }
>  
> +/* kvm_io_bus_write_cookie - called under kvm->slots_lock */
> +int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +			    int len, const void *val, long cookie)
> +{
> +	struct kvm_io_bus *bus;
> +	struct kvm_io_range range;
> +
> +	range = (struct kvm_io_range) {
> +		.addr = addr,
> +		.len = len,
> +	};
> +
> +	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
> +
> +	/* First try the device referenced by cookie. */
> +	if ((cookie >= 0) && (cookie < bus->dev_count) &&
> +	    (kvm_io_bus_sort_cmp(&range, &bus->range[cookie]) == 0))
> +		if (!kvm_iodevice_write(bus->range[cookie].dev, addr, len,
> +					val))
> +			return cookie;
> +
> +	/*
> +	 * cookie contained garbage; fall back to search and return the
> +	 * correct cookie value.
> +	 */
> +	return kvm_io_bus_write(kvm, bus_idx, addr, len, val);
> +}
> +
>  /* kvm_io_bus_read - called under kvm->slots_lock */
>  int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  		    int len, void *val)
> @@ -2919,6 +2947,34 @@ int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  	return -EOPNOTSUPP;
>  }
>  
> +/* kvm_io_bus_read_cookie - called under kvm->slots_lock */
> +int kvm_io_bus_read_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
> +			   int len, void *val, long cookie)
> +{
> +	struct kvm_io_bus *bus;
> +	struct kvm_io_range range;
> +
> +	range = (struct kvm_io_range) {
> +		.addr = addr,
> +		.len = len,
> +	};
> +
> +	bus = srcu_dereference(kvm->buses[bus_idx], &kvm->srcu);
> +
> +	/* First try the device referenced by cookie. */
> +	if ((cookie >= 0) && (cookie < bus->dev_count) &&
> +	    (kvm_io_bus_sort_cmp(&range, &bus->range[cookie]) == 0))
> +		if (!kvm_iodevice_read(bus->range[cookie].dev, addr, len,
> +				       val))
> +			return cookie;
> +
> +	/*
> +	 * cookie contained garbage; fall back to search and return the
> +	 * correct cookie value.
> +	 */
> +	return kvm_io_bus_read(kvm, bus_idx, addr, len, val);
> +}
> +
>  /* Caller must hold slots_lock. */
>  int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  			    int len, struct kvm_io_device *dev)
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2013-07-03 11:47 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-07-03  8:56 [PATCH 0/2] KVM: enable ioeventfd cookies Cornelia Huck
2013-07-03  8:56 ` [PATCH 1/2] KVM: kvm-io: support cookies Cornelia Huck
2013-07-03  9:05   ` Paolo Bonzini
2013-07-03  9:21     ` Paolo Bonzini
2013-07-03 10:51       ` Cornelia Huck
2013-07-03 10:58         ` Paolo Bonzini
2013-07-03 11:45           ` Cornelia Huck
2013-07-03 11:46             ` Paolo Bonzini
2013-07-03  8:56 ` [PATCH 2/2] KVM: s390: use cookies for ioeventfd Cornelia Huck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox