From patchwork Sun Oct 30 21:23:35 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Michael S. Tsirkin" X-Patchwork-Id: 689073 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3t6Vt24YY1z9t15 for ; Mon, 31 Oct 2016 08:26:18 +1100 (AEDT) Received: from localhost ([::1]:60053 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1c0xcM-0004uX-Rg for incoming@patchwork.ozlabs.org; Sun, 30 Oct 2016 17:26:15 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54819) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1c0xZu-0002oY-3A for qemu-devel@nongnu.org; Sun, 30 Oct 2016 17:23:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1c0xZq-0006aZ-TZ for qemu-devel@nongnu.org; Sun, 30 Oct 2016 17:23:42 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56190) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1c0xZq-0006aS-Lr for qemu-devel@nongnu.org; Sun, 30 Oct 2016 17:23:38 -0400 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F40AEF11A5; Sun, 30 Oct 2016 21:23:37 +0000 (UTC) Received: from redhat.com (ovpn-112-24.rdu2.redhat.com [10.10.112.24]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id u9ULNZL1024253; Sun, 30 Oct 2016 17:23:36 -0400 Date: Sun, 30 Oct 2016 23:23:35 +0200 From: "Michael S. Tsirkin" To: qemu-devel@nongnu.org Message-ID: <1477850917-1214-7-git-send-email-mst@redhat.com> References: <1477850917-1214-1-git-send-email-mst@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1477850917-1214-1-git-send-email-mst@redhat.com> X-Mutt-Fcc: =sent X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Sun, 30 Oct 2016 21:23:38 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 06/47] virtio: add start_ioeventfd and stop_ioeventfd to VirtioDeviceClass X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Cornelia Huck , Peter Maydell , Stefan Hajnoczi , Paolo Bonzini Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Paolo Bonzini 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 Reviewed-by: Cornelia Huck Signed-off-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/virtio/virtio-bus.h | 7 ++++- include/hw/virtio/virtio.h | 4 +++ hw/virtio/virtio-bus.c | 54 +++++++++++------------------------ hw/virtio/virtio.c | 64 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 38 deletions(-) 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 52d4b55..27e5151 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); /* Saving and loading of a device; trying to deprecate save/load * use vmsd for new devices. */ @@ -269,6 +271,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); 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 3e318e4..e228518 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -2172,15 +2172,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 = {