[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 04/13] virtio: add start_ioeventfd and stop_ioeventf
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PATCH 04/13] virtio: add start_ioeventfd and stop_ioeventfd to VirtioDeviceClass |
Date: |
Fri, 21 Oct 2016 22:48:07 +0200 |
Allow customization of the start and stop of ioeventfd. This will
allow direct start of dataplane without passing through the default
ioeventfd handlers, which in turn allows using the dataplane logic
instead of virtio_add_queue_aio. It will also enable some code
simplification, because the sole entry point to ioeventfd setup
will be virtio_bus_set_host_notifier.
Reviewed-by: Stefan Hajnoczi <address@hidden>
Reviewed-by: Cornelia Huck <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
v2->v3: avoid virtio-mmio failures [Cornelia]
hw/virtio/virtio-bus.c | 54 +++++++++++------------------------
hw/virtio/virtio.c | 64 ++++++++++++++++++++++++++++++++++++++++++
include/hw/virtio/virtio-bus.h | 7 ++++-
include/hw/virtio/virtio.h | 4 +++
4 files changed, 91 insertions(+), 38 deletions(-)
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index 97cdb11..a8d2bd8 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -153,8 +153,8 @@ void virtio_bus_set_vdev_config(VirtioBusState *bus,
uint8_t *config)
* assign: register/deregister ioeventfd with the kernel
* set_handler: use the generic ioeventfd handler
*/
-static int set_host_notifier_internal(DeviceState *proxy, VirtioBusState *bus,
- int n, bool assign, bool set_handler)
+int set_host_notifier_internal(DeviceState *proxy, VirtioBusState *bus,
+ int n, bool assign, bool set_handler)
{
VirtIODevice *vdev = virtio_bus_get_device(bus);
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
@@ -185,61 +185,41 @@ static int set_host_notifier_internal(DeviceState *proxy,
VirtioBusState *bus,
return r;
}
-void virtio_bus_start_ioeventfd(VirtioBusState *bus)
+int virtio_bus_start_ioeventfd(VirtioBusState *bus)
{
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus);
DeviceState *proxy = DEVICE(BUS(bus)->parent);
- VirtIODevice *vdev;
- int n, r;
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
+ int r;
if (!k->ioeventfd_assign || k->ioeventfd_disabled(proxy)) {
- return;
+ return -ENOSYS;
}
if (bus->ioeventfd_started || bus->ioeventfd_disabled) {
- return;
+ return 0;
}
- vdev = virtio_bus_get_device(bus);
- for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
- r = set_host_notifier_internal(proxy, bus, n, true, true);
- if (r < 0) {
- goto assign_error;
- }
+ r = vdc->start_ioeventfd(vdev);
+ if (r < 0) {
+ error_report("%s: failed. Fallback to userspace (slower).", __func__);
+ return r;
}
bus->ioeventfd_started = true;
- return;
-
-assign_error:
- while (--n >= 0) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
-
- r = set_host_notifier_internal(proxy, bus, n, false, false);
- assert(r >= 0);
- }
- error_report("%s: failed. Fallback to userspace (slower).", __func__);
+ return 0;
}
void virtio_bus_stop_ioeventfd(VirtioBusState *bus)
{
- DeviceState *proxy = DEVICE(BUS(bus)->parent);
VirtIODevice *vdev;
- int n, r;
+ VirtioDeviceClass *vdc;
if (!bus->ioeventfd_started) {
return;
}
+
vdev = virtio_bus_get_device(bus);
- for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(vdev, n)) {
- continue;
- }
- r = set_host_notifier_internal(proxy, bus, n, false, false);
- assert(r >= 0);
- }
+ vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
+ vdc->stop_ioeventfd(vdev);
bus->ioeventfd_started = false;
}
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index d48d1a9..7740975 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2158,15 +2158,79 @@ static Property virtio_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
+static int virtio_device_start_ioeventfd_impl(VirtIODevice *vdev)
+{
+ VirtioBusState *qbus = VIRTIO_BUS(qdev_get_parent_bus(DEVICE(vdev)));
+ DeviceState *proxy = DEVICE(BUS(qbus)->parent);
+ int n, r, err;
+
+ for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+ r = set_host_notifier_internal(proxy, qbus, n, true, true);
+ if (r < 0) {
+ err = r;
+ goto assign_error;
+ }
+ }
+ return 0;
+
+assign_error:
+ while (--n >= 0) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+
+ r = set_host_notifier_internal(proxy, qbus, n, false, false);
+ assert(r >= 0);
+ }
+ return err;
+}
+
+int virtio_device_start_ioeventfd(VirtIODevice *vdev)
+{
+ BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
+ VirtioBusState *vbus = VIRTIO_BUS(qbus);
+
+ return virtio_bus_start_ioeventfd(vbus);
+}
+
+static void virtio_device_stop_ioeventfd_impl(VirtIODevice *vdev)
+{
+ VirtioBusState *qbus = VIRTIO_BUS(qdev_get_parent_bus(DEVICE(vdev)));
+ DeviceState *proxy = DEVICE(BUS(qbus)->parent);
+ int n, r;
+
+ for (n = 0; n < VIRTIO_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ continue;
+ }
+ r = set_host_notifier_internal(proxy, qbus, n, false, false);
+ assert(r >= 0);
+ }
+}
+
+void virtio_device_stop_ioeventfd(VirtIODevice *vdev)
+{
+ BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
+ VirtioBusState *vbus = VIRTIO_BUS(qbus);
+
+ virtio_bus_stop_ioeventfd(vbus);
+}
+
static void virtio_device_class_init(ObjectClass *klass, void *data)
{
/* Set the default value here. */
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = virtio_device_realize;
dc->unrealize = virtio_device_unrealize;
dc->bus_type = TYPE_VIRTIO_BUS;
dc->props = virtio_properties;
+ vdc->start_ioeventfd = virtio_device_start_ioeventfd_impl;
+ vdc->stop_ioeventfd = virtio_device_stop_ioeventfd_impl;
}
static const TypeInfo virtio_device_info = {
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index f74ef1e..aa326e1 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -132,10 +132,15 @@ static inline VirtIODevice
*virtio_bus_get_device(VirtioBusState *bus)
}
/* Start the ioeventfd. */
-void virtio_bus_start_ioeventfd(VirtioBusState *bus);
+int virtio_bus_start_ioeventfd(VirtioBusState *bus);
/* Stop the ioeventfd. */
void virtio_bus_stop_ioeventfd(VirtioBusState *bus);
/* Switch from/to the generic ioeventfd handler */
int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign);
+/* This is temporary. It is only needed because virtio_bus_set_host_notifier
+ * sets ioeventfd_disabled but we will shortly get rid of it. */
+int set_host_notifier_internal(DeviceState *proxy, VirtioBusState *bus,
+ int n, bool assign, bool set_handler);
+
#endif /* VIRTIO_BUS_H */
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index b913aac..0e70951 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -125,6 +125,8 @@ typedef struct VirtioDeviceClass {
* must mask in frontend instead.
*/
void (*guest_notifier_mask)(VirtIODevice *vdev, int n, bool mask);
+ int (*start_ioeventfd)(VirtIODevice *vdev);
+ void (*stop_ioeventfd)(VirtIODevice *vdev);
void (*save)(VirtIODevice *vdev, QEMUFile *f);
int (*load)(VirtIODevice *vdev, QEMUFile *f, int version_id);
} VirtioDeviceClass;
@@ -265,6 +267,8 @@ uint16_t virtio_get_queue_index(VirtQueue *vq);
EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq);
void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
bool with_irqfd);
+int virtio_device_start_ioeventfd(VirtIODevice *vdev);
+void virtio_device_stop_ioeventfd(VirtIODevice *vdev);
EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq);
void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign,
bool set_handler);
--
1.8.3.1
- [Qemu-devel] [PATCH v3 00/13] virtio: cleanup ioeventfd start/stop, Paolo Bonzini, 2016/10/21
- [Qemu-devel] [PATCH 02/13] virtio: move ioeventfd_disabled flag to VirtioBusState, Paolo Bonzini, 2016/10/21
- [Qemu-devel] [PATCH 03/13] virtio: move ioeventfd_started flag to VirtioBusState, Paolo Bonzini, 2016/10/21
- [Qemu-devel] [PATCH 01/13] virtio: disable ioeventfd as early as possible, Paolo Bonzini, 2016/10/21
- [Qemu-devel] [PATCH 05/13] virtio: introduce virtio_device_ioeventfd_enabled, Paolo Bonzini, 2016/10/21
- [Qemu-devel] [PATCH 04/13] virtio: add start_ioeventfd and stop_ioeventfd to VirtioDeviceClass,
Paolo Bonzini <=
- [Qemu-devel] [PATCH 08/13] Revert "virtio: Introduce virtio_add_queue_aio", Paolo Bonzini, 2016/10/21
- [Qemu-devel] [PATCH 06/13] virtio-blk: always use dataplane path if ioeventfd is active, Paolo Bonzini, 2016/10/21
- [Qemu-devel] [PATCH 07/13] virtio-scsi: always use dataplane path if ioeventfd is active, Paolo Bonzini, 2016/10/21
- [Qemu-devel] [PATCH 09/13] virtio: remove set_handler argument from set_host_notifier_internal, Paolo Bonzini, 2016/10/21
- [Qemu-devel] [PATCH 11/13] virtio: use virtio_bus_set_host_notifier to start/stop ioeventfd, Paolo Bonzini, 2016/10/21
- [Qemu-devel] [PATCH 10/13] virtio: remove ioeventfd_disabled altogether, Paolo Bonzini, 2016/10/21
- [Qemu-devel] [PATCH 13/13] virtio: inline set_host_notifier_internal, Paolo Bonzini, 2016/10/21
- [Qemu-devel] [PATCH 12/13] virtio: inline virtio_queue_set_host_notifier_fd_handler, Paolo Bonzini, 2016/10/21
- [Qemu-devel] [14/13] fixup! virtio: remove set_handler argument from set_host_notifier_internal, Paolo Bonzini, 2016/10/24