From patchwork Mon Dec 17 21:40:42 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Michael S. Tsirkin" X-Patchwork-Id: 207002 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B7A382C0093 for ; Tue, 18 Dec 2012 08:38:21 +1100 (EST) Received: from localhost ([::1]:35391 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TkiOB-0007th-VW for incoming@patchwork.ozlabs.org; Mon, 17 Dec 2012 16:38:19 -0500 Received: from eggs.gnu.org ([208.118.235.92]:34216) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TkiO1-0007l4-Qd for qemu-devel@nongnu.org; Mon, 17 Dec 2012 16:38:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TkiNy-00049M-Ap for qemu-devel@nongnu.org; Mon, 17 Dec 2012 16:38:09 -0500 Received: from mx1.redhat.com ([209.132.183.28]:8215) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TkiNy-000494-0S for qemu-devel@nongnu.org; Mon, 17 Dec 2012 16:38:06 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id qBHLbYTj015935 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 17 Dec 2012 16:37:34 -0500 Received: from redhat.com (vpn1-6-198.ams2.redhat.com [10.36.6.198]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id qBHLbU1g014024; Mon, 17 Dec 2012 16:37:30 -0500 Date: Mon, 17 Dec 2012 23:40:42 +0200 From: "Michael S. Tsirkin" To: qemu-devel@nongnu.org, afaerber@suse.de, pbonzini@redhat.com Message-ID: <20121217214042.GA11926@redhat.com> MIME-Version: 1.0 Content-Disposition: inline X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-MIME-Autoconverted: from 8bit to quoted-printable by mx1.redhat.com id qBHLbYTj015935 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Anthony Liguori , Stefan Hajnoczi , "Michael S. Tsirkin" , Jan Kiszka , Alexander Graf , Christian Borntraeger , Paolo Bonzini , Andreas =?iso-8859-1?Q?F=E4rber?= Subject: [Qemu-devel] [PATCHv2] virtio: make bindings typesafe X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Move bindings from opaque to DeviceState. This gives us better type safety with no performance cost. Add macros to make future QOM work easier, document which ones are data-path sensitive. Signed-off-by: Michael S. Tsirkin --- Changes from v1: - Address comment by Anreas Färber: wrap container_of macros to make future QOM work easier - make a couple of bindings that v1 missed typesafe: virtio doesn't use any void * now diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c index e0ac2d1..8c693b4 100644 --- a/hw/s390-virtio-bus.c +++ b/hw/s390-virtio-bus.c @@ -137,7 +137,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev) bus->dev_offs += dev_len; - virtio_bind_device(vdev, &virtio_s390_bindings, dev); + virtio_bind_device(vdev, &virtio_s390_bindings, VIRTIO_S390_TO_QDEV(dev)); dev->host_features = vdev->get_features(vdev, dev->host_features); s390_virtio_device_sync(dev); s390_virtio_reset_idx(dev); @@ -364,9 +364,17 @@ VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem) return NULL; } -static void virtio_s390_notify(void *opaque, uint16_t vector) +/* VirtIOS390Device to DeviceState */ +#define VIRTIO_S390_TO_QDEV(dev) (&(dev)->qdev) + +/* DeviceState to VirtIOS390Device. Note: used on datapath, + * be careful and test performance if you change this. + */ +#define VIRTIO_S390_DEVICE(d) container_of(d, VirtIOS390Device, qdev) + +static void virtio_s390_notify(DeviceState *d, uint16_t vector) { - VirtIOS390Device *dev = (VirtIOS390Device*)opaque; + VirtIOS390Device *dev = VIRTIO_S390_DEVICE(d); uint64_t token = s390_virtio_device_vq_token(dev, vector); S390CPU *cpu = s390_cpu_addr2state(0); CPUS390XState *env = &cpu->env; @@ -374,9 +382,9 @@ static void virtio_s390_notify(void *opaque, uint16_t vector) s390_virtio_irq(env, 0, token); } -static unsigned virtio_s390_get_features(void *opaque) +static unsigned virtio_s390_get_features(DeviceState *d) { - VirtIOS390Device *dev = (VirtIOS390Device*)opaque; + VirtIOS390Device *dev = VIRTIO_S390_DEVICE(d); return dev->host_features; } diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 3ea4140..1e9566a 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -97,35 +97,42 @@ bool virtio_is_big_endian(void); /* virtio device */ +/* VirtIOPCIProxy to DeviceState. */ +#define VIRTIO_PCI_TO_QDEV(proxy) (&(proxy)->pci_dev.qdev) -static void virtio_pci_notify(void *opaque, uint16_t vector) +/* DeviceState to VirtIOPCIProxy. Note: used on datapath, + * be careful and test performance if you change this. + */ +#define VIRTIO_PCI_PROXY(d) container_of(d, VirtIOPCIProxy, pci_dev.qdev) + +static void virtio_pci_notify(DeviceState *d, uint16_t vector) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = VIRTIO_PCI_PROXY(d); if (msix_enabled(&proxy->pci_dev)) msix_notify(&proxy->pci_dev, vector); else qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1); } -static void virtio_pci_save_config(void * opaque, QEMUFile *f) +static void virtio_pci_save_config(DeviceState *d, QEMUFile *f) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = VIRTIO_PCI_PROXY(d); pci_device_save(&proxy->pci_dev, f); msix_save(&proxy->pci_dev, f); if (msix_present(&proxy->pci_dev)) qemu_put_be16(f, proxy->vdev->config_vector); } -static void virtio_pci_save_queue(void * opaque, int n, QEMUFile *f) +static void virtio_pci_save_queue(DeviceState *d, int n, QEMUFile *f) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = VIRTIO_PCI_PROXY(d); if (msix_present(&proxy->pci_dev)) qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n)); } -static int virtio_pci_load_config(void * opaque, QEMUFile *f) +static int virtio_pci_load_config(DeviceState *d, QEMUFile *f) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = VIRTIO_PCI_PROXY(d); int ret; ret = pci_device_load(&proxy->pci_dev, f); if (ret) { @@ -144,9 +151,9 @@ static int virtio_pci_load_config(void * opaque, QEMUFile *f) return 0; } -static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f) +static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = VIRTIO_PCI_PROXY(d); uint16_t vector; if (msix_present(&proxy->pci_dev)) { qemu_get_be16s(f, &vector); @@ -244,7 +251,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy) void virtio_pci_reset(DeviceState *d) { - VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev); + VirtIOPCIProxy *proxy = VIRTIO_PCI_PROXY(d); virtio_pci_stop_ioeventfd(proxy); virtio_reset(proxy->vdev); msix_unuse_all_vectors(&proxy->pci_dev); @@ -464,9 +471,9 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, } } -static unsigned virtio_pci_get_features(void *opaque) +static unsigned virtio_pci_get_features(DeviceState *d) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = VIRTIO_PCI_PROXY(d); return proxy->host_features; } @@ -568,9 +575,9 @@ static void kvm_virtio_pci_vector_release(PCIDevice *dev, unsigned vector) } } -static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign) +static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = VIRTIO_PCI_PROXY(d); VirtQueue *vq = virtio_get_queue(proxy->vdev, n); EventNotifier *notifier = virtio_queue_get_guest_notifier(vq); @@ -588,15 +595,15 @@ static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign) return 0; } -static bool virtio_pci_query_guest_notifiers(void *opaque) +static bool virtio_pci_query_guest_notifiers(DeviceState *d) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = VIRTIO_PCI_PROXY(d); return msix_enabled(&proxy->pci_dev); } -static int virtio_pci_set_guest_notifiers(void *opaque, bool assign) +static int virtio_pci_set_guest_notifiers(DeviceState *d, bool assign) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = VIRTIO_PCI_PROXY(d); VirtIODevice *vdev = proxy->vdev; int r, n; @@ -612,7 +619,7 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign) break; } - r = virtio_pci_set_guest_notifier(opaque, n, assign); + r = virtio_pci_set_guest_notifier(d, n, assign); if (r < 0) { goto assign_error; } @@ -638,14 +645,14 @@ assign_error: /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */ assert(assign); while (--n >= 0) { - virtio_pci_set_guest_notifier(opaque, n, !assign); + virtio_pci_set_guest_notifier(d, n, !assign); } return r; } -static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign) +static int virtio_pci_set_host_notifier(DeviceState *d, int n, bool assign) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = VIRTIO_PCI_PROXY(d); /* Stop using ioeventfd for virtqueue kick if the device starts using host * notifiers. This makes it easy to avoid stepping on each others' toes. @@ -661,9 +668,9 @@ static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign) return virtio_pci_set_host_notifier_internal(proxy, n, assign, false); } -static void virtio_pci_vmstate_change(void *opaque, bool running) +static void virtio_pci_vmstate_change(DeviceState *d, bool running) { - VirtIOPCIProxy *proxy = opaque; + VirtIOPCIProxy *proxy = VIRTIO_PCI_PROXY(d); if (running) { /* Try to find out if the guest has bus master disabled, but is @@ -728,7 +735,7 @@ void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev) proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD; } - virtio_bind_device(vdev, &virtio_pci_bindings, proxy); + virtio_bind_device(vdev, &virtio_pci_bindings, VIRTIO_PCI_TO_QDEV(proxy)); proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY; proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE; proxy->host_features = vdev->get_features(vdev, proxy->host_features); diff --git a/hw/virtio.c b/hw/virtio.c index f40a8c5..e65d7c8 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -935,7 +943,7 @@ VirtIODevice *virtio_common_init(const char *name, uint16_t device_id, } void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding, - void *opaque) + DeviceState *opaque) { vdev->binding = binding; vdev->binding_opaque = opaque; diff --git a/hw/virtio.h b/hw/virtio.h index 7c17f7b..e2e57a4 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -91,17 +91,17 @@ typedef struct VirtQueueElement } VirtQueueElement; typedef struct { - void (*notify)(void * opaque, uint16_t vector); - void (*save_config)(void * opaque, QEMUFile *f); - void (*save_queue)(void * opaque, int n, QEMUFile *f); - int (*load_config)(void * opaque, QEMUFile *f); - int (*load_queue)(void * opaque, int n, QEMUFile *f); - int (*load_done)(void * opaque, QEMUFile *f); - unsigned (*get_features)(void * opaque); - bool (*query_guest_notifiers)(void * opaque); - int (*set_guest_notifiers)(void * opaque, bool assigned); - int (*set_host_notifier)(void * opaque, int n, bool assigned); - void (*vmstate_change)(void * opaque, bool running); + void (*notify)(DeviceState *d, uint16_t vector); + void (*save_config)(DeviceState *d, QEMUFile *f); + void (*save_queue)(DeviceState *d, int n, QEMUFile *f); + int (*load_config)(DeviceState *d, QEMUFile *f); + int (*load_queue)(DeviceState *d, int n, QEMUFile *f); + int (*load_done)(DeviceState *d, QEMUFile *f); + unsigned (*get_features)(DeviceState *d); + bool (*query_guest_notifiers)(DeviceState *d); + int (*set_guest_notifiers)(DeviceState *d, bool assigned); + int (*set_host_notifier)(DeviceState *d, int n, bool assigned); + void (*vmstate_change)(DeviceState *d, bool running); } VirtIOBindings; #define VIRTIO_PCI_QUEUE_MAX 64 @@ -128,7 +128,7 @@ struct VirtIODevice void (*set_status)(VirtIODevice *vdev, uint8_t val); VirtQueue *vq; const VirtIOBindings *binding; - void *binding_opaque; + DeviceState *binding_opaque; uint16_t device_id; bool vm_running; VMChangeStateEntry *vmstate; @@ -187,11 +187,11 @@ uint16_t virtio_queue_vector(VirtIODevice *vdev, int n); void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector); void virtio_set_status(VirtIODevice *vdev, uint8_t val); void virtio_reset(void *opaque); void virtio_update_irq(VirtIODevice *vdev); int virtio_set_features(VirtIODevice *vdev, uint32_t val); void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding, - void *opaque); + DeviceState *opaque); /* Base devices. */ typedef struct VirtIOBlkConf VirtIOBlkConf;