2e83913
Support host/guest notifiers in virtio-pci.
2e83913
The last one only with kvm, that's okay
2e83913
because vhost relies on kvm anyway.
2e83913
2e83913
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2e83913
---
2e83913
 hw/virtio-pci.c |   62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2e83913
 1 files changed, 62 insertions(+), 0 deletions(-)
2e83913
2e83913
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
2e83913
index 05898c8..c454093 100644
2e83913
--- a/hw/virtio-pci.c
2e83913
+++ b/hw/virtio-pci.c
2e83913
@@ -23,6 +23,7 @@
2e83913
 #include "msix.h"
2e83913
 #include "net.h"
2e83913
 #include "loader.h"
2e83913
+#include "kvm.h"
2e83913
 
2e83913
 /* from Linux's linux/virtio_pci.h */
2e83913
 
2e83913
@@ -394,6 +395,65 @@ static unsigned virtio_pci_get_features(void *opaque)
2e83913
     return proxy->host_features;
2e83913
 }
2e83913
 
2e83913
+static void virtio_pci_guest_notifier_read(void *opaque)
2e83913
+{
2e83913
+    VirtQueue *vq = opaque;
2e83913
+    EventNotifier *n = virtio_queue_guest_notifier(vq);
2e83913
+    if (event_notifier_test_and_clear(n)) {
2e83913
+        virtio_irq(vq);
2e83913
+    }
2e83913
+}
2e83913
+
2e83913
+static int virtio_pci_guest_notifier(void *opaque, int n, bool assign)
2e83913
+{
2e83913
+    VirtIOPCIProxy *proxy = opaque;
2e83913
+    VirtQueue *vq = virtio_queue(proxy->vdev, n);
2e83913
+    EventNotifier *notifier = virtio_queue_guest_notifier(vq);
2e83913
+
2e83913
+    if (assign) {
2e83913
+        int r = event_notifier_init(notifier, 0);
2e83913
+	if (r < 0)
2e83913
+		return r;
2e83913
+        qemu_set_fd_handler(event_notifier_get_fd(notifier),
2e83913
+                            virtio_pci_guest_notifier_read, NULL, vq);
2e83913
+    } else {
2e83913
+        qemu_set_fd_handler(event_notifier_get_fd(notifier),
2e83913
+                            NULL, NULL, vq);
2e83913
+        event_notifier_cleanup(notifier);
2e83913
+    }
2e83913
+
2e83913
+    return 0;
2e83913
+}
2e83913
+
2e83913
+static int virtio_pci_host_notifier(void *opaque, int n, bool assign)
2e83913
+{
2e83913
+    VirtIOPCIProxy *proxy = opaque;
2e83913
+    VirtQueue *vq = virtio_queue(proxy->vdev, n);
2e83913
+    EventNotifier *notifier = virtio_queue_host_notifier(vq);
2e83913
+    int r;
2e83913
+    if (assign) {
2e83913
+	r = event_notifier_init(notifier, 1);
2e83913
+	if (r < 0) {
2e83913
+		return r;
2e83913
+        }
2e83913
+        r = kvm_set_ioeventfd(proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
2e83913
+                              n, event_notifier_get_fd(notifier),
2e83913
+                              assign);
2e83913
+        if (r < 0) {
2e83913
+            event_notifier_cleanup(notifier);
2e83913
+        }
2e83913
+    } else {
2e83913
+        r = kvm_set_ioeventfd(proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
2e83913
+                              n, event_notifier_get_fd(notifier),
2e83913
+                              assign);
2e83913
+	if (r < 0) {
2e83913
+		return r;
2e83913
+        }
2e83913
+        event_notifier_cleanup(notifier);
2e83913
+    }
2e83913
+    return r;
2e83913
+}
2e83913
+
2e83913
 static const VirtIOBindings virtio_pci_bindings = {
2e83913
     .notify = virtio_pci_notify,
2e83913
     .save_config = virtio_pci_save_config,
2e83913
@@ -401,6 +461,8 @@ static const VirtIOBindings virtio_pci_bindings = {
2e83913
     .save_queue = virtio_pci_save_queue,
2e83913
     .load_queue = virtio_pci_load_queue,
2e83913
     .get_features = virtio_pci_get_features,
2e83913
+    .host_notifier = virtio_pci_host_notifier,
2e83913
+    .guest_notifier = virtio_pci_guest_notifier,
2e83913
 };
2e83913
 
2e83913
 static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
2e83913
-- 
2e83913
1.6.6.144.g5c3af