virtio: make bindings typesafe
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>
This commit is contained in:
parent
27dd773058
commit
d2a0ccc613
@ -136,7 +136,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
|
|||||||
|
|
||||||
bus->dev_offs += dev_len;
|
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);
|
dev->host_features = vdev->get_features(vdev, dev->host_features);
|
||||||
s390_virtio_device_sync(dev);
|
s390_virtio_device_sync(dev);
|
||||||
s390_virtio_reset_idx(dev);
|
s390_virtio_reset_idx(dev);
|
||||||
@ -363,9 +363,23 @@ VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem)
|
|||||||
return NULL;
|
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)
|
||||||
{
|
{
|
||||||
VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
|
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 = to_virtio_s390_device_fast(d);
|
||||||
uint64_t token = s390_virtio_device_vq_token(dev, vector);
|
uint64_t token = s390_virtio_device_vq_token(dev, vector);
|
||||||
S390CPU *cpu = s390_cpu_addr2state(0);
|
S390CPU *cpu = s390_cpu_addr2state(0);
|
||||||
CPUS390XState *env = &cpu->env;
|
CPUS390XState *env = &cpu->env;
|
||||||
@ -373,9 +387,9 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
|
|||||||
s390_virtio_irq(env, 0, token);
|
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;
|
return dev->host_features;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,35 +96,48 @@
|
|||||||
bool virtio_is_big_endian(void);
|
bool virtio_is_big_endian(void);
|
||||||
|
|
||||||
/* virtio device */
|
/* virtio device */
|
||||||
|
/* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */
|
||||||
static void virtio_pci_notify(void *opaque, uint16_t vector)
|
static inline VirtIOPCIProxy *to_virtio_pci_proxy(DeviceState *d)
|
||||||
{
|
{
|
||||||
VirtIOPCIProxy *proxy = opaque;
|
return container_of(d, VirtIOPCIProxy, pci_dev.qdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
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))
|
if (msix_enabled(&proxy->pci_dev))
|
||||||
msix_notify(&proxy->pci_dev, vector);
|
msix_notify(&proxy->pci_dev, vector);
|
||||||
else
|
else
|
||||||
qemu_set_irq(proxy->pci_dev.irq[0], proxy->vdev->isr & 1);
|
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);
|
pci_device_save(&proxy->pci_dev, f);
|
||||||
msix_save(&proxy->pci_dev, f);
|
msix_save(&proxy->pci_dev, f);
|
||||||
if (msix_present(&proxy->pci_dev))
|
if (msix_present(&proxy->pci_dev))
|
||||||
qemu_put_be16(f, proxy->vdev->config_vector);
|
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))
|
if (msix_present(&proxy->pci_dev))
|
||||||
qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n));
|
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;
|
int ret;
|
||||||
ret = pci_device_load(&proxy->pci_dev, f);
|
ret = pci_device_load(&proxy->pci_dev, f);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -143,9 +156,9 @@ static int virtio_pci_load_config(void * opaque, QEMUFile *f)
|
|||||||
return 0;
|
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;
|
uint16_t vector;
|
||||||
if (msix_present(&proxy->pci_dev)) {
|
if (msix_present(&proxy->pci_dev)) {
|
||||||
qemu_get_be16s(f, &vector);
|
qemu_get_be16s(f, &vector);
|
||||||
@ -243,7 +256,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
|
|||||||
|
|
||||||
void virtio_pci_reset(DeviceState *d)
|
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_pci_stop_ioeventfd(proxy);
|
||||||
virtio_reset(proxy->vdev);
|
virtio_reset(proxy->vdev);
|
||||||
msix_unuse_all_vectors(&proxy->pci_dev);
|
msix_unuse_all_vectors(&proxy->pci_dev);
|
||||||
@ -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;
|
return proxy->host_features;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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);
|
VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
|
||||||
EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
|
EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
|
||||||
|
|
||||||
@ -587,15 +600,15 @@ static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
|
|||||||
return 0;
|
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);
|
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;
|
VirtIODevice *vdev = proxy->vdev;
|
||||||
int r, n;
|
int r, n;
|
||||||
|
|
||||||
@ -611,7 +624,7 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = virtio_pci_set_guest_notifier(opaque, n, assign);
|
r = virtio_pci_set_guest_notifier(d, n, assign);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
goto assign_error;
|
goto assign_error;
|
||||||
}
|
}
|
||||||
@ -636,14 +649,14 @@ assign_error:
|
|||||||
/* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
|
/* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
|
||||||
assert(assign);
|
assert(assign);
|
||||||
while (--n >= 0) {
|
while (--n >= 0) {
|
||||||
virtio_pci_set_guest_notifier(opaque, n, !assign);
|
virtio_pci_set_guest_notifier(d, n, !assign);
|
||||||
}
|
}
|
||||||
return r;
|
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
|
/* Stop using ioeventfd for virtqueue kick if the device starts using host
|
||||||
* notifiers. This makes it easy to avoid stepping on each others' toes.
|
* notifiers. This makes it easy to avoid stepping on each others' toes.
|
||||||
@ -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);
|
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) {
|
if (running) {
|
||||||
/* Try to find out if the guest has bus master disabled, but is
|
/* Try to find out if the guest has bus master disabled, but is
|
||||||
@ -726,7 +739,7 @@ void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev)
|
|||||||
proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
|
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_NOTIFY_ON_EMPTY;
|
||||||
proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
|
proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
|
||||||
proxy->host_features = vdev->get_features(vdev, proxy->host_features);
|
proxy->host_features = vdev->get_features(vdev, proxy->host_features);
|
||||||
|
@ -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 virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
|
||||||
void *opaque)
|
DeviceState *opaque)
|
||||||
{
|
{
|
||||||
vdev->binding = binding;
|
vdev->binding = binding;
|
||||||
vdev->binding_opaque = opaque;
|
vdev->binding_opaque = opaque;
|
||||||
|
26
hw/virtio.h
26
hw/virtio.h
@ -91,17 +91,17 @@ typedef struct VirtQueueElement
|
|||||||
} VirtQueueElement;
|
} VirtQueueElement;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void (*notify)(void * opaque, uint16_t vector);
|
void (*notify)(DeviceState *d, uint16_t vector);
|
||||||
void (*save_config)(void * opaque, QEMUFile *f);
|
void (*save_config)(DeviceState *d, QEMUFile *f);
|
||||||
void (*save_queue)(void * opaque, int n, QEMUFile *f);
|
void (*save_queue)(DeviceState *d, int n, QEMUFile *f);
|
||||||
int (*load_config)(void * opaque, QEMUFile *f);
|
int (*load_config)(DeviceState *d, QEMUFile *f);
|
||||||
int (*load_queue)(void * opaque, int n, QEMUFile *f);
|
int (*load_queue)(DeviceState *d, int n, QEMUFile *f);
|
||||||
int (*load_done)(void * opaque, QEMUFile *f);
|
int (*load_done)(DeviceState *d, QEMUFile *f);
|
||||||
unsigned (*get_features)(void * opaque);
|
unsigned (*get_features)(DeviceState *d);
|
||||||
bool (*query_guest_notifiers)(void * opaque);
|
bool (*query_guest_notifiers)(DeviceState *d);
|
||||||
int (*set_guest_notifiers)(void * opaque, bool assigned);
|
int (*set_guest_notifiers)(DeviceState *d, bool assigned);
|
||||||
int (*set_host_notifier)(void * opaque, int n, bool assigned);
|
int (*set_host_notifier)(DeviceState *d, int n, bool assigned);
|
||||||
void (*vmstate_change)(void * opaque, bool running);
|
void (*vmstate_change)(DeviceState *d, bool running);
|
||||||
} VirtIOBindings;
|
} VirtIOBindings;
|
||||||
|
|
||||||
#define VIRTIO_PCI_QUEUE_MAX 64
|
#define VIRTIO_PCI_QUEUE_MAX 64
|
||||||
@ -128,7 +128,7 @@ struct VirtIODevice
|
|||||||
void (*set_status)(VirtIODevice *vdev, uint8_t val);
|
void (*set_status)(VirtIODevice *vdev, uint8_t val);
|
||||||
VirtQueue *vq;
|
VirtQueue *vq;
|
||||||
const VirtIOBindings *binding;
|
const VirtIOBindings *binding;
|
||||||
void *binding_opaque;
|
DeviceState *binding_opaque;
|
||||||
uint16_t device_id;
|
uint16_t device_id;
|
||||||
bool vm_running;
|
bool vm_running;
|
||||||
VMChangeStateEntry *vmstate;
|
VMChangeStateEntry *vmstate;
|
||||||
@ -191,7 +191,7 @@ void virtio_update_irq(VirtIODevice *vdev);
|
|||||||
int virtio_set_features(VirtIODevice *vdev, uint32_t val);
|
int virtio_set_features(VirtIODevice *vdev, uint32_t val);
|
||||||
|
|
||||||
void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
|
void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
|
||||||
void *opaque);
|
DeviceState *opaque);
|
||||||
|
|
||||||
/* Base devices. */
|
/* Base devices. */
|
||||||
typedef struct VirtIOBlkConf VirtIOBlkConf;
|
typedef struct VirtIOBlkConf VirtIOBlkConf;
|
||||||
|
Loading…
Reference in New Issue
Block a user