diff mbox

[18/18] virtio-gpu: start/stop the data-plane

Message ID 20160904222039.11460-19-marcandre.lureau@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Marc-André Lureau Sept. 4, 2016, 10:20 p.m. UTC
Use aio thread context to dispatch the queues.

This code has been written based on virtio-blk data-plane setup.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/display/virtio-gpu.c        | 138 ++++++++++++++++++++++++++++++++++++++++-
 include/hw/virtio/virtio-gpu.h |   1 +
 2 files changed, 137 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index a37d5f2..c732607 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -22,12 +22,18 @@ 
 #include "migration/migration.h"
 #include "qemu/log.h"
 #include "qapi/error.h"
+#include "ui/egl-context.h"
 
 #define VIRTIO_GPU_VM_VERSION 1
 
 static struct virtio_gpu_simple_resource*
 virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
 
+static void
+virtio_gpu_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq);
+static void
+virtio_gpu_handle_cursor(VirtIODevice *vdev, VirtQueue *vq);
+
 #ifdef CONFIG_VIRGL
 #include <virglrenderer.h>
 #define VIRGL(_g, _virgl, _simple, ...)                     \
@@ -824,9 +830,129 @@  static void virtio_gpu_simple_process_cmd(VirtIOGPU *g,
     }
 }
 
+static void data_plane_handle_ctrl_cb(VirtIODevice *vdev, VirtQueue *q)
+{
+    VirtIOGPU *g = VIRTIO_GPU(vdev);
+    virtio_gpu_handle_ctrl(&g->parent_obj, q);
+}
+
+static void data_plane_handle_cursor_cb(VirtIODevice *vdev, VirtQueue *q)
+{
+    VirtIOGPU *g = VIRTIO_GPU(vdev);
+    virtio_gpu_handle_cursor(&g->parent_obj, q);
+}
+
+static void virtio_gpu_data_plane_start(VirtIODevice *vdev)
+{
+    VirtIOGPU *g = VIRTIO_GPU(vdev);
+    VirtIOGPUDataPlane *dp = g->dp;
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+    int i, r;
+
+    if (dp->started || dp->starting) {
+        return;
+    }
+
+    dp->starting = true;
+
+    /* Set up guest notifier (irq) */
+    r = k->set_guest_notifiers(qbus->parent, 2, true);
+    if (r != 0) {
+        fprintf(stderr, "virtio-gpu failed to set guest notifier (%d), "
+                "ensure -enable-kvm is set\n", r);
+        goto fail_guest_notifiers;
+    }
+
+    /* Set up virtqueue notify */
+    for (i = 0; i < 2; i++) {
+        r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, true);
+        if (r != 0) {
+            fprintf(stderr, "virtio-gpu failed to set host notifier (%d)\n", r);
+            while (i--) {
+                virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
+            }
+            goto fail_guest_notifiers;
+        }
+    }
+
+    dp->starting = false;
+    dp->started = true;
+
+    /* Kick right away to begin processing requests already in vring */
+    for (i = 0; i < 2; i++) {
+        VirtQueue *vq = virtio_get_queue(vdev, i);
+
+        event_notifier_set(virtio_queue_get_host_notifier(vq));
+    }
+
+    AioContext *ctx = iothread_get_aio_context(g->iothread);
+    /* Get this show started by hooking up our callbacks */
+    aio_context_acquire(ctx);
+    virtio_queue_aio_set_host_notifier_handler(virtio_get_queue(vdev, 0), ctx,
+                                               data_plane_handle_ctrl_cb);
+    virtio_queue_aio_set_host_notifier_handler(virtio_get_queue(vdev, 1), ctx,
+                                               data_plane_handle_cursor_cb);
+    aio_context_release(ctx);
+    return;
+
+fail_guest_notifiers:
+    dp->disabled = true;
+    dp->starting = false;
+    dp->started = true;
+}
+
+void virtio_gpu_data_plane_stop(VirtIOGPUDataPlane *dp)
+{
+    VirtIOGPU *g = dp->gpu;
+    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(g)));
+    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+    AioContext *ctx = iothread_get_aio_context(g->iothread);
+    unsigned i;
+
+    if (!dp->started || dp->stopping) {
+        return;
+    }
+
+    if (dp->disabled) {
+        dp->disabled = false;
+        dp->started = false;
+        return;
+    }
+    dp->stopping = true;
+
+    /* Get this show started by hooking up our callbacks */
+    aio_context_acquire(ctx);
+    /* Stop notifications for new requests from guest */
+    for (i = 0; i < 2; i++) {
+        VirtQueue *vq = virtio_get_queue(VIRTIO_DEVICE(g), i);
+
+        virtio_queue_aio_set_host_notifier_handler(vq, ctx, NULL);
+    }
+    aio_context_release(ctx);
+
+    for (i = 0; i < 2; i++) {
+        virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
+    }
+
+    /* Clean up guest notifier (irq) */
+    k->set_guest_notifiers(qbus->parent, 2, false);
+
+    dp->started = false;
+    dp->stopping = false;
+}
+
 static void virtio_gpu_handle_ctrl_cb(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIOGPU *g = VIRTIO_GPU(vdev);
+
+    if (g->dp) {
+        virtio_gpu_data_plane_start(vdev);
+        if (!g->dp->disabled) {
+            return;
+        }
+    }
+
     qemu_bh_schedule(g->ctrl_bh);
 }
 
@@ -1210,9 +1336,13 @@  static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
     }
 
     if (virtio_gpu_virgl_enabled(g->conf)) {
+        VirtQueue *(*add_queue)(VirtIODevice *vdev, int queue_size,
+                                  VirtIOHandleOutput handle_output) =
+            g->iothread ? virtio_add_queue_aio : virtio_add_queue;
+
         /* use larger control queue in 3d mode */
-        g->ctrl_vq   = virtio_add_queue(vdev, 256, virtio_gpu_handle_ctrl_cb);
-        g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb);
+        g->ctrl_vq   = add_queue(vdev, 256, virtio_gpu_handle_ctrl_cb);
+        g->cursor_vq = add_queue(vdev, 16, virtio_gpu_handle_cursor_cb);
         g->virtio_config.num_capsets = 1;
 #if defined(CONFIG_VIRGL)
         {
@@ -1290,6 +1420,10 @@  static void virtio_gpu_reset(VirtIODevice *vdev)
     struct virtio_gpu_simple_resource *res, *tmp;
     int i;
 
+    if (g->dp) {
+        virtio_gpu_data_plane_stop(g->dp);
+    }
+
     g->enable = 0;
 
     QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) {
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 82d1e45..26ff9d1 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -217,5 +217,6 @@  void virtio_gpu_virgl_reset(VirtIOGPU *g);
 int virtio_gpu_virgl_init(VirtIOGPU *g);
 int virtio_gpu_virgl_dp_create(VirtIOGPU *g, Error **errp);
 void virtio_gpu_virgl_dp_destroy(VirtIOGPU *g);
+void virtio_gpu_data_plane_stop(VirtIOGPUDataPlane *dp);
 
 #endif