Skip to content

Commit

Permalink
virtio: make bindings typesafe
Browse files Browse the repository at this point in the history
Move bindings from opaque to DeviceState.
This gives us better type safety with no performance cost.
Add macros to make future QOM work easier.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
  • Loading branch information
mstsirkin committed Dec 20, 2012
1 parent 27dd773 commit d2a0ccc
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 45 deletions.
24 changes: 19 additions & 5 deletions hw/s390-virtio-bus.c
Expand Up @@ -136,7 +136,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, DEVICE(dev));
dev->host_features = vdev->get_features(vdev, dev->host_features);
s390_virtio_device_sync(dev);
s390_virtio_reset_idx(dev);
Expand Down Expand Up @@ -363,19 +363,33 @@ VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem)
return NULL;
}

static void virtio_s390_notify(void *opaque, uint16_t vector)
/* DeviceState to VirtIOS390Device. Note: used on datapath,
* be careful and test performance if you change this.
*/
static inline VirtIOS390Device *to_virtio_s390_device_fast(DeviceState *d)
{
return container_of(d, VirtIOS390Device, qdev);
}

/* DeviceState to VirtIOS390Device. TODO: use QOM. */
static inline VirtIOS390Device *to_virtio_s390_device(DeviceState *d)
{
return container_of(d, VirtIOS390Device, qdev);
}

static void virtio_s390_notify(DeviceState *d, uint16_t vector)
{
VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
VirtIOS390Device *dev = to_virtio_s390_device_fast(d);
uint64_t token = s390_virtio_device_vq_token(dev, vector);
S390CPU *cpu = s390_cpu_addr2state(0);
CPUS390XState *env = &cpu->env;

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 = to_virtio_s390_device(d);
return dev->host_features;
}

Expand Down
65 changes: 39 additions & 26 deletions hw/virtio-pci.c
Expand Up @@ -96,35 +96,48 @@
bool virtio_is_big_endian(void);

/* virtio device */
/* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */
static inline VirtIOPCIProxy *to_virtio_pci_proxy(DeviceState *d)
{
return container_of(d, VirtIOPCIProxy, 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.
*/
static inline VirtIOPCIProxy *to_virtio_pci_proxy_fast(DeviceState *d)
{
VirtIOPCIProxy *proxy = opaque;
return container_of(d, VirtIOPCIProxy, pci_dev.qdev);
}

static void virtio_pci_notify(DeviceState *d, uint16_t vector)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy_fast(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 = to_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 = to_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 = to_virtio_pci_proxy(d);
int ret;
ret = pci_device_load(&proxy->pci_dev, f);
if (ret) {
Expand All @@ -143,9 +156,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 = to_virtio_pci_proxy(d);
uint16_t vector;
if (msix_present(&proxy->pci_dev)) {
qemu_get_be16s(f, &vector);
Expand Down Expand Up @@ -243,7 +256,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 = to_virtio_pci_proxy(d);
virtio_pci_stop_ioeventfd(proxy);
virtio_reset(proxy->vdev);
msix_unuse_all_vectors(&proxy->pci_dev);
Expand Down Expand Up @@ -463,9 +476,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 = to_virtio_pci_proxy(d);
return proxy->host_features;
}

Expand Down Expand Up @@ -567,9 +580,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 = to_virtio_pci_proxy(d);
VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);

Expand All @@ -587,15 +600,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 = to_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 = to_virtio_pci_proxy(d);
VirtIODevice *vdev = proxy->vdev;
int r, n;

Expand All @@ -611,7 +624,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;
}
Expand All @@ -636,14 +649,14 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
/* 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 = to_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.
Expand All @@ -659,9 +672,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 = to_virtio_pci_proxy(d);

if (running) {
/* Try to find out if the guest has bus master disabled, but is
Expand Down Expand Up @@ -726,7 +739,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, DEVICE(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);
Expand Down
2 changes: 1 addition & 1 deletion hw/virtio.c
Expand Up @@ -935,7 +935,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;
Expand Down
26 changes: 13 additions & 13 deletions hw/virtio.h
Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -191,7 +191,7 @@ 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;
Expand Down

0 comments on commit d2a0ccc

Please sign in to comment.