diff options
Diffstat (limited to 'hw/virtio/virtio.c')
-rw-r--r-- | hw/virtio/virtio.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 18153d5a39..752b2715d0 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -95,8 +95,9 @@ struct VirtQueue int inuse; uint16_t vector; - void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq); - void (*handle_aio_output)(VirtIODevice *vdev, VirtQueue *vq); + VirtIOHandleOutput handle_output; + VirtIOHandleOutput handle_aio_output; + bool use_aio; VirtIODevice *vdev; EventNotifier guest_notifier; EventNotifier host_notifier; @@ -1130,8 +1131,9 @@ void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector) } } -VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, - void (*handle_output)(VirtIODevice *, VirtQueue *)) +static VirtQueue *virtio_add_queue_internal(VirtIODevice *vdev, int queue_size, + VirtIOHandleOutput handle_output, + bool use_aio) { int i; @@ -1148,10 +1150,28 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN; vdev->vq[i].handle_output = handle_output; vdev->vq[i].handle_aio_output = NULL; + vdev->vq[i].use_aio = use_aio; return &vdev->vq[i]; } +/* Add a virt queue and mark AIO. + * An AIO queue will use the AioContext based event interface instead of the + * default IOHandler and EventNotifier interface. + */ +VirtQueue *virtio_add_queue_aio(VirtIODevice *vdev, int queue_size, + VirtIOHandleOutput handle_output) +{ + return virtio_add_queue_internal(vdev, queue_size, handle_output, true); +} + +/* Add a normal virt queue (on the contrary to the AIO version above. */ +VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, + VirtIOHandleOutput handle_output) +{ + return virtio_add_queue_internal(vdev, queue_size, handle_output, false); +} + void virtio_del_queue(VirtIODevice *vdev, int n) { if (n < 0 || n >= VIRTIO_QUEUE_MAX) { @@ -1444,6 +1464,12 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) vmstate_save_state(f, &vmstate_virtio, vdev, NULL); } +/* A wrapper for use as a VMState .put function */ +void virtio_vmstate_save(QEMUFile *f, void *opaque, size_t size) +{ + virtio_save(VIRTIO_DEVICE(opaque), f); +} + static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val) { VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); @@ -1804,8 +1830,7 @@ static void virtio_queue_host_notifier_aio_read(EventNotifier *n) } void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, - void (*handle_output)(VirtIODevice *, - VirtQueue *)) + VirtIOHandleOutput handle_output) { if (handle_output) { vq->handle_aio_output = handle_output; @@ -1831,11 +1856,21 @@ static void virtio_queue_host_notifier_read(EventNotifier *n) void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign, bool set_handler) { + AioContext *ctx = qemu_get_aio_context(); if (assign && set_handler) { - event_notifier_set_handler(&vq->host_notifier, true, + if (vq->use_aio) { + aio_set_event_notifier(ctx, &vq->host_notifier, true, virtio_queue_host_notifier_read); + } else { + event_notifier_set_handler(&vq->host_notifier, true, + virtio_queue_host_notifier_read); + } } else { - event_notifier_set_handler(&vq->host_notifier, true, NULL); + if (vq->use_aio) { + aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL); + } else { + event_notifier_set_handler(&vq->host_notifier, true, NULL); + } } if (!assign) { /* Test and clear notifier before after disabling event, |