From mboxrd@z Thu Jan 1 00:00:00 1970 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 Date: Mon, 17 Dec 2012 23:40:42 +0200 From: "Michael S. Tsirkin" Message-ID: <20121217214042.GA11926@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCHv2] virtio: make bindings typesafe List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org, afaerber@suse.de, pbonzini@redhat.com Cc: Anthony Liguori , Stefan Hajnoczi , "Michael S. Tsirkin" , Jan Kiszka , Alexander Graf , Christian Borntraeger 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=E4rber: 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) =20 bus->dev_offs +=3D dev_len; =20 - virtio_bind_device(vdev, &virtio_s390_bindings, dev); + virtio_bind_device(vdev, &virtio_s390_bindings, VIRTIO_S390_TO_QDEV(= dev)); dev->host_features =3D 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(VirtIOS39= 0Bus *bus, ram_addr_t mem) return NULL; } =20 -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 =3D (VirtIOS390Device*)opaque; + VirtIOS390Device *dev =3D VIRTIO_S390_DEVICE(d); uint64_t token =3D s390_virtio_device_vq_token(dev, vector); S390CPU *cpu =3D s390_cpu_addr2state(0); CPUS390XState *env =3D &cpu->env; @@ -374,9 +382,9 @@ static void virtio_s390_notify(void *opaque, uint16_t= vector) s390_virtio_irq(env, 0, token); } =20 -static unsigned virtio_s390_get_features(void *opaque) +static unsigned virtio_s390_get_features(DeviceState *d) { - VirtIOS390Device *dev =3D (VirtIOS390Device*)opaque; + VirtIOS390Device *dev =3D VIRTIO_S390_DEVICE(d); return dev->host_features; } =20 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); =20 /* virtio device */ +/* VirtIOPCIProxy to DeviceState. */ +#define VIRTIO_PCI_TO_QDEV(proxy) (&(proxy)->pci_dev.qdev) =20 -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 =3D opaque; + VirtIOPCIProxy *proxy =3D 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); } =20 -static void virtio_pci_save_config(void * opaque, QEMUFile *f) +static void virtio_pci_save_config(DeviceState *d, QEMUFile *f) { - VirtIOPCIProxy *proxy =3D opaque; + VirtIOPCIProxy *proxy =3D 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); } =20 -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 =3D opaque; + VirtIOPCIProxy *proxy =3D VIRTIO_PCI_PROXY(d); if (msix_present(&proxy->pci_dev)) qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n)); } =20 -static int virtio_pci_load_config(void * opaque, QEMUFile *f) +static int virtio_pci_load_config(DeviceState *d, QEMUFile *f) { - VirtIOPCIProxy *proxy =3D opaque; + VirtIOPCIProxy *proxy =3D VIRTIO_PCI_PROXY(d); int ret; ret =3D pci_device_load(&proxy->pci_dev, f); if (ret) { @@ -144,9 +151,9 @@ static int virtio_pci_load_config(void * opaque, QEMU= File *f) return 0; } =20 -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 =3D opaque; + VirtIOPCIProxy *proxy =3D 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) =20 void virtio_pci_reset(DeviceState *d) { - VirtIOPCIProxy *proxy =3D container_of(d, VirtIOPCIProxy, pci_dev.qd= ev); + VirtIOPCIProxy *proxy =3D 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, u= int32_t address, } } =20 -static unsigned virtio_pci_get_features(void *opaque) +static unsigned virtio_pci_get_features(DeviceState *d) { - VirtIOPCIProxy *proxy =3D opaque; + VirtIOPCIProxy *proxy =3D VIRTIO_PCI_PROXY(d); return proxy->host_features; } =20 @@ -568,9 +575,9 @@ static void kvm_virtio_pci_vector_release(PCIDevice *= dev, unsigned vector) } } =20 -static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assig= n) +static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool ass= ign) { - VirtIOPCIProxy *proxy =3D opaque; + VirtIOPCIProxy *proxy =3D VIRTIO_PCI_PROXY(d); VirtQueue *vq =3D virtio_get_queue(proxy->vdev, n); EventNotifier *notifier =3D virtio_queue_get_guest_notifier(vq); =20 @@ -588,15 +595,15 @@ static int virtio_pci_set_guest_notifier(void *opaq= ue, int n, bool assign) return 0; } =20 -static bool virtio_pci_query_guest_notifiers(void *opaque) +static bool virtio_pci_query_guest_notifiers(DeviceState *d) { - VirtIOPCIProxy *proxy =3D opaque; + VirtIOPCIProxy *proxy =3D VIRTIO_PCI_PROXY(d); return msix_enabled(&proxy->pci_dev); } =20 -static int virtio_pci_set_guest_notifiers(void *opaque, bool assign) +static int virtio_pci_set_guest_notifiers(DeviceState *d, bool assign) { - VirtIOPCIProxy *proxy =3D opaque; + VirtIOPCIProxy *proxy =3D VIRTIO_PCI_PROXY(d); VirtIODevice *vdev =3D proxy->vdev; int r, n; =20 @@ -612,7 +619,7 @@ static int virtio_pci_set_guest_notifiers(void *opaqu= e, bool assign) break; } =20 - r =3D virtio_pci_set_guest_notifier(opaque, n, assign); + r =3D 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 >=3D 0) { - virtio_pci_set_guest_notifier(opaque, n, !assign); + virtio_pci_set_guest_notifier(d, n, !assign); } return r; } =20 -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 assi= gn) { - VirtIOPCIProxy *proxy =3D opaque; + VirtIOPCIProxy *proxy =3D VIRTIO_PCI_PROXY(d); =20 /* Stop using ioeventfd for virtqueue kick if the device starts usin= g 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= ); } =20 -static void virtio_pci_vmstate_change(void *opaque, bool running) +static void virtio_pci_vmstate_change(DeviceState *d, bool running) { - VirtIOPCIProxy *proxy =3D opaque; + VirtIOPCIProxy *proxy =3D VIRTIO_PCI_PROXY(d); =20 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, VirtIODev= ice *vdev) proxy->flags &=3D ~VIRTIO_PCI_FLAG_USE_IOEVENTFD; } =20 - virtio_bind_device(vdev, &virtio_pci_bindings, proxy); + virtio_bind_device(vdev, &virtio_pci_bindings, VIRTIO_PCI_TO_QDEV(pr= oxy)); proxy->host_features |=3D 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY; proxy->host_features |=3D 0x1 << VIRTIO_F_BAD_FEATURE; proxy->host_features =3D vdev->get_features(vdev, proxy->host_featur= es); 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, ui= nt16_t device_id, } =20 void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *bindin= g, - void *opaque) + DeviceState *opaque) { vdev->binding =3D binding; vdev->binding_opaque =3D 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; =20 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; =20 #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, in= t 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); =20 void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *bindin= g, - void *opaque); + DeviceState *opaque); =20 /* Base devices. */ typedef struct VirtIOBlkConf VirtIOBlkConf;