Re: [PATCH v2 3/4] KVM: add io services to xinterface

2009-10-04 Thread Avi Kivity

On 10/02/2009 10:19 PM, Gregory Haskins wrote:

We want to add a more efficient way to get PIO signals out of the guest,
so we add an xioevent interface.  This allows a client to register
for notifications when a specific MMIO/PIO address is touched by
the guest.  This is an alternative interface to ioeventfd, which is
performance limited by io-bus scaling and eventfd wait-queue based
notification mechanism.  This also has the advantage of retaining
the full PIO data payload and passing it to the recipient.

   


Can you detail the problems with io-bus scaling and eventfd 
wait-queues?  Maybe we should fix these instead.


--
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


[PATCH v2 3/4] KVM: add io services to xinterface

2009-10-02 Thread Gregory Haskins
We want to add a more efficient way to get PIO signals out of the guest,
so we add an xioevent interface.  This allows a client to register
for notifications when a specific MMIO/PIO address is touched by
the guest.  This is an alternative interface to ioeventfd, which is
performance limited by io-bus scaling and eventfd wait-queue based
notification mechanism.  This also has the advantage of retaining
the full PIO data payload and passing it to the recipient.

Signed-off-by: Gregory Haskins ghask...@novell.com
---

 include/linux/kvm_xinterface.h |   47 ++
 virt/kvm/xinterface.c  |  106 
 2 files changed, 153 insertions(+), 0 deletions(-)

diff --git a/include/linux/kvm_xinterface.h b/include/linux/kvm_xinterface.h
index 01f092b..684b6f8 100644
--- a/include/linux/kvm_xinterface.h
+++ b/include/linux/kvm_xinterface.h
@@ -12,6 +12,16 @@
 
 struct kvm_xinterface;
 struct kvm_xvmap;
+struct kvm_xioevent;
+
+enum {
+   kvm_xioevent_flag_nr_pio,
+   kvm_xioevent_flag_nr_max,
+};
+
+#define KVM_XIOEVENT_FLAG_PIO   (1  kvm_xioevent_flag_nr_pio)
+
+#define KVM_XIOEVENT_VALID_FLAG_MASK  ((1  kvm_xioevent_flag_nr_max) - 1)
 
 struct kvm_xinterface_ops {
unsigned long (*copy_to)(struct kvm_xinterface *intf,
@@ -22,6 +32,10 @@ struct kvm_xinterface_ops {
struct kvm_xvmap* (*vmap)(struct kvm_xinterface *intf,
  unsigned long gpa,
  unsigned long len);
+   struct kvm_xioevent* (*ioevent)(struct kvm_xinterface *intf,
+   u64 addr,
+   unsigned long len,
+   unsigned long flags);
void (*release)(struct kvm_xinterface *);
 };
 
@@ -109,6 +123,39 @@ kvm_xvmap_put(struct kvm_xvmap *vmap)
kref_put(vmap-kref, _kvm_xvmap_release);
 }
 
+struct kvm_xioevent_ops {
+   void (*deassign)(struct kvm_xioevent *ioevent);
+};
+
+struct kvm_xioevent {
+   const struct kvm_xioevent_ops *ops;
+   struct kvm_xinterface *intf;
+   void (*signal)(struct kvm_xioevent *ioevent, const void *val);
+   void  *priv;
+};
+
+static inline void
+kvm_xioevent_init(struct kvm_xioevent *ioevent,
+ const struct kvm_xioevent_ops *ops,
+ struct kvm_xinterface *intf)
+{
+   memset(ioevent, 0, sizeof(vmap));
+   ioevent-ops = ops;
+   ioevent-intf = intf;
+
+   kvm_xinterface_get(intf);
+}
+
+static inline void
+kvm_xioevent_deassign(struct kvm_xioevent *ioevent)
+{
+   struct kvm_xinterface *intf = ioevent-intf;
+   rmb();
+
+   ioevent-ops-deassign(ioevent);
+   kvm_xinterface_put(intf);
+}
+
 struct kvm_xinterface *kvm_xinterface_bind(int fd);
 
 #endif /* __KVM_XINTERFACE_H */
diff --git a/virt/kvm/xinterface.c b/virt/kvm/xinterface.c
index 3b586c5..c356835 100644
--- a/virt/kvm/xinterface.c
+++ b/virt/kvm/xinterface.c
@@ -28,6 +28,8 @@
 #include linux/kvm_host.h
 #include linux/kvm_xinterface.h
 
+#include iodev.h
+
 struct _xinterface {
struct kvm *kvm;
struct task_struct *task;
@@ -42,6 +44,14 @@ struct _xvmap {
struct kvm_xvmap   vmap;
 };
 
+struct _ioevent {
+   u64   addr;
+   int   length;
+   struct kvm_io_bus*bus;
+   struct kvm_io_device  dev;
+   struct kvm_xioevent   ioevent;
+};
+
 static struct _xinterface *
 to_intf(struct kvm_xinterface *intf)
 {
@@ -362,6 +372,101 @@ fail:
return ERR_PTR(ret);
 }
 
+/* MMIO/PIO writes trigger an event if the addr/val match */
+static int
+ioevent_write(struct kvm_io_device *dev, gpa_t addr, int len, const void *val)
+{
+   struct _ioevent *p = container_of(dev, struct _ioevent, dev);
+   struct kvm_xioevent *ioevent = p-ioevent;
+
+   if (!(addr == p-addr  len == p-length))
+   return -EOPNOTSUPP;
+
+   if (!ioevent-signal)
+   return 0;
+
+   ioevent-signal(ioevent, val);
+   return 0;
+}
+
+static const struct kvm_io_device_ops ioevent_device_ops = {
+   .write = ioevent_write,
+};
+
+static void
+ioevent_deassign(struct kvm_xioevent *ioevent)
+{
+   struct _ioevent*p = container_of(ioevent, struct _ioevent, ioevent);
+   struct _xinterface *_intf = to_intf(ioevent-intf);
+   struct kvm *kvm = _intf-kvm;
+
+   kvm_io_bus_unregister_dev(kvm, p-bus, p-dev);
+   kfree(p);
+}
+
+static const struct kvm_xioevent_ops ioevent_intf_ops = {
+   .deassign = ioevent_deassign,
+};
+
+static struct kvm_xioevent*
+xinterface_ioevent(struct kvm_xinterface *intf,
+  u64 addr,
+  unsigned long len,
+  unsigned long flags)
+{
+   struct _xinterface *_intf = to_intf(intf);
+   struct kvm *kvm = _intf-kvm;
+   int pio = flags