aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/9pfs/virtio-9p-device.c43
-rw-r--r--hw/block/dataplane/virtio-blk.c30
-rw-r--r--hw/block/dataplane/virtio-blk.h5
-rw-r--r--hw/block/virtio-blk.c47
-rw-r--r--hw/char/virtio-serial-bus.c33
-rw-r--r--hw/net/virtio-net.c36
-rw-r--r--hw/s390x/virtio-ccw.c83
-rw-r--r--hw/s390x/virtio-ccw.h1
-rw-r--r--hw/scsi/vhost-scsi.c45
-rw-r--r--hw/scsi/virtio-scsi.c57
-rw-r--r--hw/virtio/virtio-balloon.c32
-rw-r--r--hw/virtio/virtio-bus.c80
-rw-r--r--hw/virtio/virtio-mmio.c9
-rw-r--r--hw/virtio/virtio-pci.c122
-rw-r--r--hw/virtio/virtio-pci.h1
-rw-r--r--hw/virtio/virtio-rng.c43
-rw-r--r--hw/virtio/virtio.c40
-rw-r--r--include/hw/virtio/virtio-bus.h22
-rw-r--r--include/hw/virtio/virtio-rng.h2
-rw-r--r--include/hw/virtio/virtio-scsi.h4
-rw-r--r--include/hw/virtio/virtio.h8
-rw-r--r--tests/qdev-monitor-test.c4
22 files changed, 413 insertions, 334 deletions
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index f0ffbe8c0d..15a4983eee 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -41,15 +41,16 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
g_free(cfg);
}
-static int virtio_9p_device_init(VirtIODevice *vdev)
+static void virtio_9p_device_realize(DeviceState *dev, Error **errp)
{
- V9fsState *s = VIRTIO_9P(vdev);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ V9fsState *s = VIRTIO_9P(dev);
int i, len;
struct stat stat;
FsDriverEntry *fse;
V9fsPath path;
- virtio_init(VIRTIO_DEVICE(s), "virtio-9p", VIRTIO_ID_9P,
+ virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P,
sizeof(struct virtio_9p_config) + MAX_TAG_LEN);
/* initialize pdu allocator */
@@ -67,16 +68,16 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
if (!fse) {
/* We don't have a fsdev identified by fsdev_id */
- fprintf(stderr, "Virtio-9p device couldn't find fsdev with the "
- "id = %s\n",
- s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL");
+ error_setg(errp, "Virtio-9p device couldn't find fsdev with the "
+ "id = %s",
+ s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL");
goto out;
}
if (!s->fsconf.tag) {
/* we haven't specified a mount_tag */
- fprintf(stderr, "fsdev with id %s needs mount_tag arguments\n",
- s->fsconf.fsdev_id);
+ error_setg(errp, "fsdev with id %s needs mount_tag arguments",
+ s->fsconf.fsdev_id);
goto out;
}
@@ -85,8 +86,8 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
s->ctx.exops.get_st_gen = NULL;
len = strlen(s->fsconf.tag);
if (len > MAX_TAG_LEN - 1) {
- fprintf(stderr, "mount tag '%s' (%d bytes) is longer than "
- "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1);
+ error_setg(errp, "mount tag '%s' (%d bytes) is longer than "
+ "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1);
goto out;
}
@@ -99,12 +100,12 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
qemu_co_rwlock_init(&s->rename_lock);
if (s->ops->init(&s->ctx) < 0) {
- fprintf(stderr, "Virtio-9p Failed to initialize fs-driver with id:%s"
- " and export path:%s\n", s->fsconf.fsdev_id, s->ctx.fs_root);
+ error_setg(errp, "Virtio-9p Failed to initialize fs-driver with id:%s"
+ " and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root);
goto out;
}
if (v9fs_init_worker_threads() < 0) {
- fprintf(stderr, "worker thread initialization failed\n");
+ error_setg(errp, "worker thread initialization failed");
goto out;
}
@@ -114,28 +115,25 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
* use co-routines here.
*/
if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) {
- fprintf(stderr,
- "error in converting name to path %s", strerror(errno));
+ error_setg(errp,
+ "error in converting name to path %s", strerror(errno));
goto out;
}
if (s->ops->lstat(&s->ctx, &path, &stat)) {
- fprintf(stderr, "share path %s does not exist\n", fse->path);
+ error_setg(errp, "share path %s does not exist", fse->path);
goto out;
} else if (!S_ISDIR(stat.st_mode)) {
- fprintf(stderr, "share path %s is not a directory\n", fse->path);
+ error_setg(errp, "share path %s is not a directory", fse->path);
goto out;
}
v9fs_path_free(&path);
- return 0;
+ return;
out:
g_free(s->ctx.fs_root);
g_free(s->tag);
virtio_cleanup(vdev);
v9fs_path_free(&path);
-
- return -1;
-
}
/* virtio-9p device */
@@ -149,9 +147,10 @@ static void virtio_9p_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+
dc->props = virtio_9p_properties;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
- vdc->init = virtio_9p_device_init;
+ vdc->realize = virtio_9p_device_realize;
vdc->get_features = virtio_9p_get_features;
vdc->get_config = virtio_9p_get_config;
}
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index f2d7350a50..1e57f3aabd 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -380,8 +380,9 @@ static void start_data_plane_bh(void *opaque)
s, QEMU_THREAD_JOINABLE);
}
-bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
- VirtIOBlockDataPlane **dataplane)
+void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
+ VirtIOBlockDataPlane **dataplane,
+ Error **errp)
{
VirtIOBlockDataPlane *s;
int fd;
@@ -389,33 +390,35 @@ bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
*dataplane = NULL;
if (!blk->data_plane) {
- return true;
+ return;
}
if (blk->scsi) {
- error_report("device is incompatible with x-data-plane, use scsi=off");
- return false;
+ error_setg(errp,
+ "device is incompatible with x-data-plane, use scsi=off");
+ return;
}
if (blk->config_wce) {
- error_report("device is incompatible with x-data-plane, "
- "use config-wce=off");
- return false;
+ error_setg(errp, "device is incompatible with x-data-plane, "
+ "use config-wce=off");
+ return;
}
/* If dataplane is (re-)enabled while the guest is running there could be
* block jobs that can conflict.
*/
if (bdrv_in_use(blk->conf.bs)) {
- error_report("cannot start dataplane thread while device is in use");
- return false;
+ error_setg(errp,
+ "cannot start dataplane thread while device is in use");
+ return;
}
fd = raw_get_aio_fd(blk->conf.bs);
if (fd < 0) {
- error_report("drive is incompatible with x-data-plane, "
- "use format=raw,cache=none,aio=native");
- return false;
+ error_setg(errp, "drive is incompatible with x-data-plane, "
+ "use format=raw,cache=none,aio=native");
+ return;
}
s = g_new0(VirtIOBlockDataPlane, 1);
@@ -427,7 +430,6 @@ bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
bdrv_set_in_use(blk->conf.bs, 1);
*dataplane = s;
- return true;
}
void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
diff --git a/hw/block/dataplane/virtio-blk.h b/hw/block/dataplane/virtio-blk.h
index c90e99f48f..1750c9905b 100644
--- a/hw/block/dataplane/virtio-blk.h
+++ b/hw/block/dataplane/virtio-blk.h
@@ -19,8 +19,9 @@
typedef struct VirtIOBlockDataPlane VirtIOBlockDataPlane;
-bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
- VirtIOBlockDataPlane **dataplane);
+void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
+ VirtIOBlockDataPlane **dataplane,
+ Error **errp);
void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s);
void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s);
void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s);
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 13f6d8276e..19d0961a47 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -657,6 +657,7 @@ static void virtio_blk_migration_state_changed(Notifier *notifier, void *data)
VirtIOBlock *s = container_of(notifier, VirtIOBlock,
migration_state_notifier);
MigrationState *mig = data;
+ Error *err = NULL;
if (migration_in_setup(mig)) {
if (!s->dataplane) {
@@ -671,31 +672,39 @@ static void virtio_blk_migration_state_changed(Notifier *notifier, void *data)
}
bdrv_drain_all(); /* complete in-flight non-dataplane requests */
virtio_blk_data_plane_create(VIRTIO_DEVICE(s), &s->blk,
- &s->dataplane);
+ &s->dataplane, &err);
+ if (err != NULL) {
+ error_report("%s", error_get_pretty(err));
+ error_free(err);
+ }
}
}
#endif /* CONFIG_VIRTIO_BLK_DATA_PLANE */
-static int virtio_blk_device_init(VirtIODevice *vdev)
+static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
{
- DeviceState *qdev = DEVICE(vdev);
- VirtIOBlock *s = VIRTIO_BLK(vdev);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOBlock *s = VIRTIO_BLK(dev);
VirtIOBlkConf *blk = &(s->blk);
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+ Error *err = NULL;
+#endif
static int virtio_blk_id;
if (!blk->conf.bs) {
- error_report("drive property not set");
- return -1;
+ error_setg(errp, "drive property not set");
+ return;
}
if (!bdrv_is_inserted(blk->conf.bs)) {
- error_report("Device needs media, but drive is empty");
- return -1;
+ error_setg(errp, "Device needs media, but drive is empty");
+ return;
}
blkconf_serial(&blk->conf, &blk->serial);
s->original_wce = bdrv_enable_write_cache(blk->conf.bs);
if (blkconf_geometry(&blk->conf, NULL, 65535, 255, 255) < 0) {
- return -1;
+ error_setg(errp, "Error setting geometry");
+ return;
}
virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
@@ -708,30 +717,32 @@ static int virtio_blk_device_init(VirtIODevice *vdev)
s->vq = virtio_add_queue(vdev, 128, virtio_blk_handle_output);
#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
- if (!virtio_blk_data_plane_create(vdev, blk, &s->dataplane)) {
+ virtio_blk_data_plane_create(vdev, blk, &s->dataplane, &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
virtio_cleanup(vdev);
- return -1;
+ return;
}
s->migration_state_notifier.notify = virtio_blk_migration_state_changed;
add_migration_state_change_notifier(&s->migration_state_notifier);
#endif
s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
- register_savevm(qdev, "virtio-blk", virtio_blk_id++, 2,
+ register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
virtio_blk_save, virtio_blk_load, s);
bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
bdrv_set_buffer_alignment(s->bs, s->conf->logical_block_size);
bdrv_iostatus_enable(s->bs);
- add_boot_device_path(s->conf->bootindex, qdev, "/disk@0,0");
- return 0;
+ add_boot_device_path(s->conf->bootindex, dev, "/disk@0,0");
}
-static int virtio_blk_device_exit(DeviceState *dev)
+static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOBlock *s = VIRTIO_BLK(dev);
+
#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
remove_migration_state_change_notifier(&s->migration_state_notifier);
virtio_blk_data_plane_destroy(s->dataplane);
@@ -741,7 +752,6 @@ static int virtio_blk_device_exit(DeviceState *dev)
unregister_savevm(dev, "virtio-blk", s);
blockdev_mark_auto_del(s->bs);
virtio_cleanup(vdev);
- return 0;
}
static Property virtio_blk_properties[] = {
@@ -753,10 +763,11 @@ static void virtio_blk_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = virtio_blk_device_exit;
+
dc->props = virtio_blk_properties;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
- vdc->init = virtio_blk_device_init;
+ vdc->realize = virtio_blk_device_realize;
+ vdc->unrealize = virtio_blk_device_unrealize;
vdc->get_config = virtio_blk_update_config;
vdc->set_config = virtio_blk_set_config;
vdc->get_features = virtio_blk_get_features;
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 703f026370..226e9f9a3c 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -889,22 +889,24 @@ static int virtser_port_qdev_exit(DeviceState *qdev)
return 0;
}
-static int virtio_serial_device_init(VirtIODevice *vdev)
+static void virtio_serial_device_realize(DeviceState *dev, Error **errp)
{
- DeviceState *qdev = DEVICE(vdev);
- VirtIOSerial *vser = VIRTIO_SERIAL(vdev);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOSerial *vser = VIRTIO_SERIAL(dev);
+ BusState *bus;
uint32_t i, max_supported_ports;
if (!vser->serial.max_virtserial_ports) {
- return -1;
+ error_setg(errp, "Maximum number of serial ports not specified");
+ return;
}
/* Each port takes 2 queues, and one pair is for the control queue */
max_supported_ports = VIRTIO_PCI_QUEUE_MAX / 2 - 1;
if (vser->serial.max_virtserial_ports > max_supported_ports) {
- error_report("maximum ports supported: %u", max_supported_ports);
- return -1;
+ error_setg(errp, "maximum ports supported: %u", max_supported_ports);
+ return;
}
virtio_init(vdev, "virtio-serial", VIRTIO_ID_CONSOLE,
@@ -912,8 +914,9 @@ static int virtio_serial_device_init(VirtIODevice *vdev)
/* Spawn a new virtio-serial bus on which the ports will ride as devices */
qbus_create_inplace(&vser->bus, sizeof(vser->bus), TYPE_VIRTIO_SERIAL_BUS,
- qdev, vdev->bus_name);
- vser->bus.qbus.allow_hotplug = 1;
+ dev, vdev->bus_name);
+ bus = BUS(&vser->bus);
+ bus->allow_hotplug = 1;
vser->bus.vser = vser;
QTAILQ_INIT(&vser->ports);
@@ -961,10 +964,8 @@ static int virtio_serial_device_init(VirtIODevice *vdev)
* Register for the savevm section with the virtio-console name
* to preserve backward compat
*/
- register_savevm(qdev, "virtio-console", -1, 3, virtio_serial_save,
+ register_savevm(dev, "virtio-console", -1, 3, virtio_serial_save,
virtio_serial_load, vser);
-
- return 0;
}
static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
@@ -987,10 +988,10 @@ static const TypeInfo virtio_serial_port_type_info = {
.class_init = virtio_serial_port_class_init,
};
-static int virtio_serial_device_exit(DeviceState *dev)
+static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp)
{
- VirtIOSerial *vser = VIRTIO_SERIAL(dev);
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOSerial *vser = VIRTIO_SERIAL(dev);
unregister_savevm(dev, "virtio-console", vser);
@@ -1004,7 +1005,6 @@ static int virtio_serial_device_exit(DeviceState *dev)
g_free(vser->post_load);
}
virtio_cleanup(vdev);
- return 0;
}
static Property virtio_serial_properties[] = {
@@ -1016,10 +1016,11 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = virtio_serial_device_exit;
+
dc->props = virtio_serial_properties;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
- vdc->init = virtio_serial_device_init;
+ vdc->realize = virtio_serial_device_realize;
+ vdc->unrealize = virtio_serial_device_unrealize;
vdc->get_features = get_features;
vdc->get_config = get_config;
vdc->set_config = set_config;
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index d312b9c83c..36266083b2 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1491,16 +1491,14 @@ void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
n->netclient_type = g_strdup(type);
}
-static int virtio_net_device_init(VirtIODevice *vdev)
+static void virtio_net_device_realize(DeviceState *dev, Error **errp)
{
- int i;
-
- DeviceState *qdev = DEVICE(vdev);
- VirtIONet *n = VIRTIO_NET(vdev);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIONet *n = VIRTIO_NET(dev);
NetClientState *nc;
+ int i;
- virtio_init(VIRTIO_DEVICE(n), "virtio-net", VIRTIO_ID_NET,
- n->config_size);
+ virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size);
n->max_queues = MAX(n->nic_conf.queues, 1);
n->vqs = g_malloc0(sizeof(VirtIONetQueue) * n->max_queues);
@@ -1540,7 +1538,7 @@ static int virtio_net_device_init(VirtIODevice *vdev)
n->netclient_type, n->netclient_name, n);
} else {
n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
- object_get_typename(OBJECT(qdev)), qdev->id, n);
+ object_get_typename(OBJECT(dev)), dev->id, n);
}
peer_test_vnet_hdr(n);
@@ -1567,24 +1565,23 @@ static int virtio_net_device_init(VirtIODevice *vdev)
nc = qemu_get_queue(n->nic);
nc->rxfilter_notify_enabled = 1;
- n->qdev = qdev;
- register_savevm(qdev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
+ n->qdev = dev;
+ register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
virtio_net_save, virtio_net_load, n);
- add_boot_device_path(n->nic_conf.bootindex, qdev, "/ethernet-phy@0");
- return 0;
+ add_boot_device_path(n->nic_conf.bootindex, dev, "/ethernet-phy@0");
}
-static int virtio_net_device_exit(DeviceState *qdev)
+static void virtio_net_device_unrealize(DeviceState *dev, Error **errp)
{
- VirtIONet *n = VIRTIO_NET(qdev);
- VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIONet *n = VIRTIO_NET(dev);
int i;
/* This will stop vhost backend if appropriate. */
virtio_net_set_status(vdev, 0);
- unregister_savevm(qdev, "virtio-net", n);
+ unregister_savevm(dev, "virtio-net", n);
if (n->netclient_name) {
g_free(n->netclient_name);
@@ -1615,8 +1612,6 @@ static int virtio_net_device_exit(DeviceState *qdev)
g_free(n->vqs);
qemu_del_nic(n->nic);
virtio_cleanup(vdev);
-
- return 0;
}
static void virtio_net_instance_init(Object *obj)
@@ -1643,10 +1638,11 @@ static void virtio_net_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = virtio_net_device_exit;
+
dc->props = virtio_net_properties;
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
- vdc->init = virtio_net_device_init;
+ vdc->realize = virtio_net_device_realize;
+ vdc->unrealize = virtio_net_device_unrealize;
vdc->get_config = virtio_net_get_config;
vdc->set_config = virtio_net_set_config;
vdc->get_features = virtio_net_get_features;
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index f93a81c7cd..ecc80ecaf7 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -57,9 +57,10 @@ static const TypeInfo virtual_css_bus_info = {
VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch)
{
VirtIODevice *vdev = NULL;
+ VirtioCcwDevice *dev = sch->driver_data;
- if (sch->driver_data) {
- vdev = ((VirtioCcwDevice *)sch->driver_data)->vdev;
+ if (dev) {
+ vdev = virtio_bus_get_device(&dev->bus);
}
return vdev;
}
@@ -67,7 +68,8 @@ VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch)
static int virtio_ccw_set_guest2host_notifier(VirtioCcwDevice *dev, int n,
bool assign, bool set_handler)
{
- VirtQueue *vq = virtio_get_queue(dev->vdev, n);
+ VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
int r = 0;
SubchDev *sch = dev->sch;
@@ -97,6 +99,7 @@ static int virtio_ccw_set_guest2host_notifier(VirtioCcwDevice *dev, int n,
static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
{
+ VirtIODevice *vdev;
int n, r;
if (!(dev->flags & VIRTIO_CCW_FLAG_USE_IOEVENTFD) ||
@@ -104,8 +107,9 @@ static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
dev->ioeventfd_started) {
return;
}
+ vdev = virtio_bus_get_device(&dev->bus);
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(dev->vdev, n)) {
+ if (!virtio_queue_get_num(vdev, n)) {
continue;
}
r = virtio_ccw_set_guest2host_notifier(dev, n, true, true);
@@ -118,7 +122,7 @@ static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
assign_error:
while (--n >= 0) {
- if (!virtio_queue_get_num(dev->vdev, n)) {
+ if (!virtio_queue_get_num(vdev, n)) {
continue;
}
r = virtio_ccw_set_guest2host_notifier(dev, n, false, false);
@@ -132,13 +136,15 @@ static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
static void virtio_ccw_stop_ioeventfd(VirtioCcwDevice *dev)
{
+ VirtIODevice *vdev;
int n, r;
if (!dev->ioeventfd_started) {
return;
}
+ vdev = virtio_bus_get_device(&dev->bus);
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(dev->vdev, n)) {
+ if (!virtio_queue_get_num(vdev, n)) {
continue;
}
r = virtio_ccw_set_guest2host_notifier(dev, n, false, false);
@@ -189,7 +195,7 @@ typedef struct VirtioFeatDesc {
static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
uint16_t index, uint16_t num)
{
- VirtioCcwDevice *dev = sch->driver_data;
+ VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
if (index > VIRTIO_PCI_QUEUE_MAX) {
return -EINVAL;
@@ -200,23 +206,23 @@ static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
return -EINVAL;
}
- if (!dev) {
+ if (!vdev) {
return -EINVAL;
}
- virtio_queue_set_addr(dev->vdev, index, addr);
+ virtio_queue_set_addr(vdev, index, addr);
if (!addr) {
- virtio_queue_set_vector(dev->vdev, index, 0);
+ virtio_queue_set_vector(vdev, index, 0);
} else {
/* Fail if we don't have a big enough queue. */
/* TODO: Add interface to handle vring.num changing */
- if (virtio_queue_get_num(dev->vdev, index) > num) {
+ if (virtio_queue_get_num(vdev, index) > num) {
return -EINVAL;
}
- virtio_queue_set_vector(dev->vdev, index, index);
+ virtio_queue_set_vector(vdev, index, index);
}
/* tell notify handler in case of config change */
- dev->vdev->config_vector = VIRTIO_PCI_QUEUE_MAX;
+ vdev->config_vector = VIRTIO_PCI_QUEUE_MAX;
return 0;
}
@@ -230,6 +236,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
hwaddr indicators;
VqConfigBlock vq_config;
VirtioCcwDevice *dev = sch->driver_data;
+ VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
bool check_len;
int len;
hwaddr hw_len;
@@ -272,7 +279,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
break;
case CCW_CMD_VDEV_RESET:
virtio_ccw_stop_ioeventfd(dev);
- virtio_reset(dev->vdev);
+ virtio_reset(vdev);
ret = 0;
break;
case CCW_CMD_READ_FEAT:
@@ -319,7 +326,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
features.features = ldl_le_phys(ccw.cda);
if (features.index < ARRAY_SIZE(dev->host_features)) {
virtio_bus_set_vdev_features(&dev->bus, features.features);
- dev->vdev->guest_features = features.features;
+ vdev->guest_features = features.features;
} else {
/*
* If the guest supports more feature bits, assert that it
@@ -337,30 +344,30 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
break;
case CCW_CMD_READ_CONF:
if (check_len) {
- if (ccw.count > dev->vdev->config_len) {
+ if (ccw.count > vdev->config_len) {
ret = -EINVAL;
break;
}
}
- len = MIN(ccw.count, dev->vdev->config_len);
+ len = MIN(ccw.count, vdev->config_len);
if (!ccw.cda) {
ret = -EFAULT;
} else {
- virtio_bus_get_vdev_config(&dev->bus, dev->vdev->config);
+ virtio_bus_get_vdev_config(&dev->bus, vdev->config);
/* XXX config space endianness */
- cpu_physical_memory_write(ccw.cda, dev->vdev->config, len);
+ cpu_physical_memory_write(ccw.cda, vdev->config, len);
sch->curr_status.scsw.count = ccw.count - len;
ret = 0;
}
break;
case CCW_CMD_WRITE_CONF:
if (check_len) {
- if (ccw.count > dev->vdev->config_len) {
+ if (ccw.count > vdev->config_len) {
ret = -EINVAL;
break;
}
}
- len = MIN(ccw.count, dev->vdev->config_len);
+ len = MIN(ccw.count, vdev->config_len);
hw_len = len;
if (!ccw.cda) {
ret = -EFAULT;
@@ -371,9 +378,9 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
} else {
len = hw_len;
/* XXX config space endianness */
- memcpy(dev->vdev->config, config, len);
+ memcpy(vdev->config, config, len);
cpu_physical_memory_unmap(config, hw_len, 0, hw_len);
- virtio_bus_set_vdev_config(&dev->bus, dev->vdev->config);
+ virtio_bus_set_vdev_config(&dev->bus, vdev->config);
sch->curr_status.scsw.count = ccw.count - len;
ret = 0;
}
@@ -397,9 +404,9 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
virtio_ccw_stop_ioeventfd(dev);
}
- virtio_set_status(dev->vdev, status);
- if (dev->vdev->status == 0) {
- virtio_reset(dev->vdev);
+ virtio_set_status(vdev, status);
+ if (vdev->status == 0) {
+ virtio_reset(vdev);
}
if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
virtio_ccw_start_ioeventfd(dev);
@@ -463,7 +470,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
} else {
vq_config.index = lduw_phys(ccw.cda);
- vq_config.num_max = virtio_queue_get_num(dev->vdev,
+ vq_config.num_max = virtio_queue_get_num(vdev,
vq_config.index);
stw_phys(ccw.cda + sizeof(vq_config.index), vq_config.num_max);
sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
@@ -495,7 +502,6 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
sch->driver_data = dev;
dev->sch = sch;
- dev->vdev = vdev;
dev->indicators = 0;
/* Initialize subchannel structure. */
@@ -608,7 +614,7 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
memset(&sch->id, 0, sizeof(SenseId));
sch->id.reserved = 0xff;
sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
- sch->id.cu_model = dev->vdev->device_id;
+ sch->id.cu_model = vdev->device_id;
/* Only the first 32 feature bits are used. */
dev->host_features[0] = virtio_bus_get_vdev_features(&dev->bus,
@@ -631,7 +637,6 @@ static int virtio_ccw_exit(VirtioCcwDevice *dev)
{
SubchDev *sch = dev->sch;
- virtio_ccw_stop_ioeventfd(dev);
if (sch) {
css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
g_free(sch);
@@ -892,9 +897,10 @@ static unsigned virtio_ccw_get_features(DeviceState *d)
static void virtio_ccw_reset(DeviceState *d)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
virtio_ccw_stop_ioeventfd(dev);
- virtio_reset(dev->vdev);
+ virtio_reset(vdev);
css_reset_sch(dev->sch);
dev->indicators = 0;
dev->indicators2 = 0;
@@ -934,9 +940,10 @@ static int virtio_ccw_set_host_notifier(DeviceState *d, int n, bool assign)
static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
bool assign, bool with_irqfd)
{
- VirtQueue *vq = virtio_get_queue(dev->vdev, n);
+ VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
- VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(dev->vdev);
+ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
if (assign) {
int r = event_notifier_init(notifier, 0);
@@ -952,16 +959,16 @@ static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
* land in qemu (and only the irq fd) in this code.
*/
if (k->guest_notifier_mask) {
- k->guest_notifier_mask(dev->vdev, n, false);
+ k->guest_notifier_mask(vdev, n, false);
}
/* get lost events and re-inject */
if (k->guest_notifier_pending &&
- k->guest_notifier_pending(dev->vdev, n)) {
+ k->guest_notifier_pending(vdev, n)) {
event_notifier_set(notifier);
}
} else {
if (k->guest_notifier_mask) {
- k->guest_notifier_mask(dev->vdev, n, true);
+ k->guest_notifier_mask(vdev, n, true);
}
virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
event_notifier_cleanup(notifier);
@@ -973,7 +980,7 @@ static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs,
bool assigned)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
- VirtIODevice *vdev = dev->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
int r, n;
for (n = 0; n < nvqs; n++) {
@@ -1228,6 +1235,8 @@ static int virtio_ccw_busdev_unplug(DeviceState *dev)
VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
SubchDev *sch = _dev->sch;
+ virtio_ccw_stop_ioeventfd(_dev);
+
/*
* We should arrive here only for device_del, since we don't support
* direct hot(un)plug of channels, but only through virtio.
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 96d6f5d5b7..00932c746d 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -77,7 +77,6 @@ typedef struct VirtIOCCWDeviceClass {
struct VirtioCcwDevice {
DeviceState parent_obj;
SubchDev *sch;
- VirtIODevice *vdev;
char *bus_id;
uint32_t host_features[VIRTIO_CCW_FEATURE_SIZE];
VirtioBusState bus;
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 9e770fba98..3983a5b464 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -196,29 +196,31 @@ static void vhost_scsi_set_status(VirtIODevice *vdev, uint8_t val)
}
}
-static int vhost_scsi_init(VirtIODevice *vdev)
+static void vhost_scsi_realize(DeviceState *dev, Error **errp)
{
- VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
- VHostSCSI *s = VHOST_SCSI(vdev);
+ VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
+ VHostSCSI *s = VHOST_SCSI(dev);
+ Error *err = NULL;
int vhostfd = -1;
int ret;
if (!vs->conf.wwpn) {
- error_report("vhost-scsi: missing wwpn\n");
- return -EINVAL;
+ error_setg(errp, "vhost-scsi: missing wwpn");
+ return;
}
if (vs->conf.vhostfd) {
vhostfd = monitor_handle_fd_param(cur_mon, vs->conf.vhostfd);
if (vhostfd == -1) {
- error_report("vhost-scsi: unable to parse vhostfd\n");
- return -EINVAL;
+ error_setg(errp, "vhost-scsi: unable to parse vhostfd");
+ return;
}
}
- ret = virtio_scsi_common_init(vs);
- if (ret < 0) {
- return ret;
+ virtio_scsi_common_realize(dev, &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ return;
}
s->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
@@ -227,24 +229,21 @@ static int vhost_scsi_init(VirtIODevice *vdev)
ret = vhost_dev_init(&s->dev, vhostfd, "/dev/vhost-scsi", true);
if (ret < 0) {
- error_report("vhost-scsi: vhost initialization failed: %s\n",
- strerror(-ret));
- return ret;
+ error_setg(errp, "vhost-scsi: vhost initialization failed: %s",
+ strerror(-ret));
+ return;
}
s->dev.backend_features = 0;
error_setg(&s->migration_blocker,
"vhost-scsi does not support migration");
migrate_add_blocker(s->migration_blocker);
-
- return 0;
}
-static int vhost_scsi_exit(DeviceState *qdev)
+static void vhost_scsi_unrealize(DeviceState *dev, Error **errp)
{
- VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
- VHostSCSI *s = VHOST_SCSI(qdev);
- VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(qdev);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VHostSCSI *s = VHOST_SCSI(dev);
migrate_del_blocker(s->migration_blocker);
error_free(s->migration_blocker);
@@ -253,7 +252,8 @@ static int vhost_scsi_exit(DeviceState *qdev)
vhost_scsi_set_status(vdev, 0);
g_free(s->dev.vqs);
- return virtio_scsi_common_exit(vs);
+
+ virtio_scsi_common_unrealize(dev, errp);
}
static Property vhost_scsi_properties[] = {
@@ -265,10 +265,11 @@ static void vhost_scsi_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = vhost_scsi_exit;
+
dc->props = vhost_scsi_properties;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
- vdc->init = vhost_scsi_init;
+ vdc->realize = vhost_scsi_realize;
+ vdc->unrealize = vhost_scsi_unrealize;
vdc->get_features = vhost_scsi_get_features;
vdc->set_config = vhost_scsi_set_config;
vdc->set_status = vhost_scsi_set_status;
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 26d95a14ec..6dcdd1b91c 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -589,12 +589,13 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
.load_request = virtio_scsi_load_request,
};
-int virtio_scsi_common_init(VirtIOSCSICommon *s)
+void virtio_scsi_common_realize(DeviceState *dev, Error **errp)
{
- VirtIODevice *vdev = VIRTIO_DEVICE(s);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(dev);
int i;
- virtio_init(VIRTIO_DEVICE(s), "virtio-scsi", VIRTIO_ID_SCSI,
+ virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI,
sizeof(VirtIOSCSIConfig));
s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *));
@@ -609,57 +610,52 @@ int virtio_scsi_common_init(VirtIOSCSICommon *s)
s->cmd_vqs[i] = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
virtio_scsi_handle_cmd);
}
-
- return 0;
}
-static int virtio_scsi_device_init(VirtIODevice *vdev)
+static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
{
- DeviceState *qdev = DEVICE(vdev);
- VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
- VirtIOSCSI *s = VIRTIO_SCSI(vdev);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOSCSI *s = VIRTIO_SCSI(dev);
static int virtio_scsi_id;
Error *err = NULL;
- int ret;
- ret = virtio_scsi_common_init(vs);
- if (ret < 0) {
- return ret;
+ virtio_scsi_common_realize(dev, &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ return;
}
- scsi_bus_new(&s->bus, sizeof(s->bus), qdev,
+ scsi_bus_new(&s->bus, sizeof(s->bus), dev,
&virtio_scsi_scsi_info, vdev->bus_name);
- if (!qdev->hotplugged) {
+ if (!dev->hotplugged) {
scsi_bus_legacy_handle_cmdline(&s->bus, &err);
if (err != NULL) {
- error_free(err);
- return -1;
+ error_propagate(errp, err);
+ return;
}
}
- register_savevm(qdev, "virtio-scsi", virtio_scsi_id++, 1,
+ register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
virtio_scsi_save, virtio_scsi_load, s);
-
- return 0;
}
-int virtio_scsi_common_exit(VirtIOSCSICommon *vs)
+void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp)
{
- VirtIODevice *vdev = VIRTIO_DEVICE(vs);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
g_free(vs->cmd_vqs);
virtio_cleanup(vdev);
- return 0;
}
-static int virtio_scsi_device_exit(DeviceState *qdev)
+static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
{
- VirtIOSCSI *s = VIRTIO_SCSI(qdev);
- VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(qdev);
+ VirtIOSCSI *s = VIRTIO_SCSI(dev);
+
+ unregister_savevm(dev, "virtio-scsi", s);
- unregister_savevm(qdev, "virtio-scsi", s);
- return virtio_scsi_common_exit(vs);
+ virtio_scsi_common_unrealize(dev, errp);
}
static Property virtio_scsi_properties[] = {
@@ -680,10 +676,11 @@ static void virtio_scsi_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = virtio_scsi_device_exit;
+
dc->props = virtio_scsi_properties;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
- vdc->init = virtio_scsi_device_init;
+ vdc->realize = virtio_scsi_device_realize;
+ vdc->unrealize = virtio_scsi_device_unrealize;
vdc->set_config = virtio_scsi_set_config;
vdc->get_features = virtio_scsi_get_features;
vdc->reset = virtio_scsi_reset;
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 9504877120..d9754dbd33 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -337,10 +337,10 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
-static int virtio_balloon_device_init(VirtIODevice *vdev)
+static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
{
- DeviceState *qdev = DEVICE(vdev);
- VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOBalloon *s = VIRTIO_BALLOON(dev);
int ret;
virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON, 8);
@@ -349,37 +349,36 @@ static int virtio_balloon_device_init(VirtIODevice *vdev)
virtio_balloon_stat, s);
if (ret < 0) {
- virtio_cleanup(VIRTIO_DEVICE(s));
- return -1;
+ error_setg(errp, "Adding balloon handler failed");
+ virtio_cleanup(vdev);
+ return;
}
s->ivq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats);
- register_savevm(qdev, "virtio-balloon", -1, 1,
+ register_savevm(dev, "virtio-balloon", -1, 1,
virtio_balloon_save, virtio_balloon_load, s);
- object_property_add(OBJECT(qdev), "guest-stats", "guest statistics",
+ object_property_add(OBJECT(dev), "guest-stats", "guest statistics",
balloon_stats_get_all, NULL, NULL, s, NULL);
- object_property_add(OBJECT(qdev), "guest-stats-polling-interval", "int",
+ object_property_add(OBJECT(dev), "guest-stats-polling-interval", "int",
balloon_stats_get_poll_interval,
balloon_stats_set_poll_interval,
NULL, s, NULL);
- return 0;
}
-static int virtio_balloon_device_exit(DeviceState *qdev)
+static void virtio_balloon_device_unrealize(DeviceState *dev, Error **errp)
{
- VirtIOBalloon *s = VIRTIO_BALLOON(qdev);
- VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIOBalloon *s = VIRTIO_BALLOON(dev);
balloon_stats_destroy_timer(s);
qemu_remove_balloon_handler(s);
- unregister_savevm(qdev, "virtio-balloon", s);
+ unregister_savevm(dev, "virtio-balloon", s);
virtio_cleanup(vdev);
- return 0;
}
static Property virtio_balloon_properties[] = {
@@ -390,10 +389,11 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = virtio_balloon_device_exit;
+
dc->props = virtio_balloon_properties;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
- vdc->init = virtio_balloon_device_init;
+ vdc->realize = virtio_balloon_device_realize;
+ vdc->unrealize = virtio_balloon_device_unrealize;
vdc->get_config = virtio_balloon_get_config;
vdc->set_config = virtio_balloon_set_config;
vdc->get_features = virtio_balloon_get_features;
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index e6b103c991..eb77019267 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -37,8 +37,8 @@ do { printf("virtio_bus: " fmt , ## __VA_ARGS__); } while (0)
#define DPRINTF(fmt, ...) do { } while (0)
#endif
-/* Plug the VirtIODevice */
-int virtio_bus_plug_device(VirtIODevice *vdev)
+/* A VirtIODevice is being plugged */
+int virtio_bus_device_plugged(VirtIODevice *vdev)
{
DeviceState *qdev = DEVICE(vdev);
BusState *qbus = BUS(qdev_get_parent_bus(qdev));
@@ -46,8 +46,6 @@ int virtio_bus_plug_device(VirtIODevice *vdev)
VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
DPRINTF("%s: plug device.\n", qbus->name);
- bus->vdev = vdev;
-
if (klass->device_plugged != NULL) {
klass->device_plugged(qbus->parent);
}
@@ -58,73 +56,83 @@ int virtio_bus_plug_device(VirtIODevice *vdev)
/* Reset the virtio_bus */
void virtio_bus_reset(VirtioBusState *bus)
{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
+
DPRINTF("%s: reset device.\n", qbus->name);
- if (bus->vdev != NULL) {
- virtio_reset(bus->vdev);
+ if (vdev != NULL) {
+ virtio_reset(vdev);
}
}
-/* Destroy the VirtIODevice */
-void virtio_bus_destroy_device(VirtioBusState *bus)
+/* A VirtIODevice is being unplugged */
+void virtio_bus_device_unplugged(VirtIODevice *vdev)
{
- BusState *qbus = BUS(bus);
- VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
+ DeviceState *qdev = DEVICE(vdev);
+ BusState *qbus = BUS(qdev_get_parent_bus(qdev));
+ VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(qbus);
+
DPRINTF("%s: remove device.\n", qbus->name);
- if (bus->vdev != NULL) {
- if (klass->device_unplug != NULL) {
- klass->device_unplug(qbus->parent);
+ if (vdev != NULL) {
+ if (klass->device_unplugged != NULL) {
+ klass->device_unplugged(qbus->parent);
}
- object_unparent(OBJECT(bus->vdev));
- bus->vdev = NULL;
}
}
/* Get the device id of the plugged device. */
uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus)
{
- assert(bus->vdev != NULL);
- return bus->vdev->device_id;
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
+ assert(vdev != NULL);
+ return vdev->device_id;
}
/* Get the config_len field of the plugged device. */
size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus)
{
- assert(bus->vdev != NULL);
- return bus->vdev->config_len;
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
+ assert(vdev != NULL);
+ return vdev->config_len;
}
/* Get the features of the plugged device. */
uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus,
uint32_t requested_features)
{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
VirtioDeviceClass *k;
- assert(bus->vdev != NULL);
- k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+
+ assert(vdev != NULL);
+ k = VIRTIO_DEVICE_GET_CLASS(vdev);
assert(k->get_features != NULL);
- return k->get_features(bus->vdev, requested_features);
+ return k->get_features(vdev, requested_features);
}
/* Set the features of the plugged device. */
void virtio_bus_set_vdev_features(VirtioBusState *bus,
uint32_t requested_features)
{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
VirtioDeviceClass *k;
- assert(bus->vdev != NULL);
- k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+
+ assert(vdev != NULL);
+ k = VIRTIO_DEVICE_GET_CLASS(vdev);
if (k->set_features != NULL) {
- k->set_features(bus->vdev, requested_features);
+ k->set_features(vdev, requested_features);
}
}
/* Get bad features of the plugged device. */
uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus)
{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
VirtioDeviceClass *k;
- assert(bus->vdev != NULL);
- k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+
+ assert(vdev != NULL);
+ k = VIRTIO_DEVICE_GET_CLASS(vdev);
if (k->bad_features != NULL) {
- return k->bad_features(bus->vdev);
+ return k->bad_features(vdev);
} else {
return 0;
}
@@ -133,22 +141,26 @@ uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus)
/* Get config of the plugged device. */
void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config)
{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
VirtioDeviceClass *k;
- assert(bus->vdev != NULL);
- k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+
+ assert(vdev != NULL);
+ k = VIRTIO_DEVICE_GET_CLASS(vdev);
if (k->get_config != NULL) {
- k->get_config(bus->vdev, config);
+ k->get_config(vdev, config);
}
}
/* Set config of the plugged device. */
void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config)
{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
VirtioDeviceClass *k;
- assert(bus->vdev != NULL);
- k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+
+ assert(vdev != NULL);
+ k = VIRTIO_DEVICE_GET_CLASS(vdev);
if (k->set_config != NULL) {
- k->set_config(bus->vdev, config);
+ k->set_config(vdev, config);
}
}
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index 29cf284d12..8829eb0e26 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -95,7 +95,7 @@ static void virtio_mmio_bus_new(VirtioBusState *bus, size_t bus_size,
static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
{
VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
- VirtIODevice *vdev = proxy->bus.vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
DPRINTF("virtio_mmio_read offset 0x%x\n", (int)offset);
@@ -185,7 +185,7 @@ static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
{
VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
- VirtIODevice *vdev = proxy->bus.vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
DPRINTF("virtio_mmio_write offset 0x%x value 0x%" PRIx64 "\n",
(int)offset, value);
@@ -298,12 +298,13 @@ static const MemoryRegionOps virtio_mem_ops = {
static void virtio_mmio_update_irq(DeviceState *opaque, uint16_t vector)
{
VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
int level;
- if (!proxy->bus.vdev) {
+ if (!vdev) {
return;
}
- level = (proxy->bus.vdev->isr != 0);
+ level = (vdev->isr != 0);
DPRINTF("virtio_mmio setting IRQ %d\n", level);
qemu_set_irq(proxy->irq, level);
}
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 7647be8a3c..30c9f2b698 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -113,31 +113,40 @@ static inline VirtIOPCIProxy *to_virtio_pci_proxy_fast(DeviceState *d)
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
- pci_set_irq(&proxy->pci_dev, proxy->vdev->isr & 1);
+ else {
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ pci_set_irq(&proxy->pci_dev, vdev->isr & 1);
+ }
}
static void virtio_pci_save_config(DeviceState *d, QEMUFile *f)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
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);
+ qemu_put_be16(f, vdev->config_vector);
}
static void virtio_pci_save_queue(DeviceState *d, int n, QEMUFile *f)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
if (msix_present(&proxy->pci_dev))
- qemu_put_be16(f, virtio_queue_vector(proxy->vdev, n));
+ qemu_put_be16(f, virtio_queue_vector(vdev, n));
}
static int virtio_pci_load_config(DeviceState *d, QEMUFile *f)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
int ret;
ret = pci_device_load(&proxy->pci_dev, f);
if (ret) {
@@ -146,12 +155,12 @@ static int virtio_pci_load_config(DeviceState *d, QEMUFile *f)
msix_unuse_all_vectors(&proxy->pci_dev);
msix_load(&proxy->pci_dev, f);
if (msix_present(&proxy->pci_dev)) {
- qemu_get_be16s(f, &proxy->vdev->config_vector);
+ qemu_get_be16s(f, &vdev->config_vector);
} else {
- proxy->vdev->config_vector = VIRTIO_NO_VECTOR;
+ vdev->config_vector = VIRTIO_NO_VECTOR;
}
- if (proxy->vdev->config_vector != VIRTIO_NO_VECTOR) {
- return msix_vector_use(&proxy->pci_dev, proxy->vdev->config_vector);
+ if (vdev->config_vector != VIRTIO_NO_VECTOR) {
+ return msix_vector_use(&proxy->pci_dev, vdev->config_vector);
}
return 0;
}
@@ -159,13 +168,15 @@ static int virtio_pci_load_config(DeviceState *d, QEMUFile *f)
static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+
uint16_t vector;
if (msix_present(&proxy->pci_dev)) {
qemu_get_be16s(f, &vector);
} else {
vector = VIRTIO_NO_VECTOR;
}
- virtio_queue_set_vector(proxy->vdev, n, vector);
+ virtio_queue_set_vector(vdev, n, vector);
if (vector != VIRTIO_NO_VECTOR) {
return msix_vector_use(&proxy->pci_dev, vector);
}
@@ -175,7 +186,8 @@ static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f)
static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
int n, bool assign, bool set_handler)
{
- VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
int r = 0;
@@ -200,6 +212,7 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
{
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
int n, r;
if (!(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) ||
@@ -209,7 +222,7 @@ static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
}
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(proxy->vdev, n)) {
+ if (!virtio_queue_get_num(vdev, n)) {
continue;
}
@@ -223,7 +236,7 @@ static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
assign_error:
while (--n >= 0) {
- if (!virtio_queue_get_num(proxy->vdev, n)) {
+ if (!virtio_queue_get_num(vdev, n)) {
continue;
}
@@ -236,6 +249,7 @@ assign_error:
static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
{
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
int r;
int n;
@@ -244,7 +258,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
}
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
- if (!virtio_queue_get_num(proxy->vdev, n)) {
+ if (!virtio_queue_get_num(vdev, n)) {
continue;
}
@@ -257,7 +271,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
VirtIOPCIProxy *proxy = opaque;
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
hwaddr pa;
switch (addr) {
@@ -272,7 +286,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
pa = (hwaddr)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
if (pa == 0) {
virtio_pci_stop_ioeventfd(proxy);
- virtio_reset(proxy->vdev);
+ virtio_reset(vdev);
msix_unuse_all_vectors(&proxy->pci_dev);
}
else
@@ -299,7 +313,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
}
if (vdev->status == 0) {
- virtio_reset(proxy->vdev);
+ virtio_reset(vdev);
msix_unuse_all_vectors(&proxy->pci_dev);
}
@@ -335,7 +349,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
{
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
uint32_t ret = 0xFFFFFFFF;
switch (addr) {
@@ -381,6 +395,7 @@ static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr,
unsigned size)
{
VirtIOPCIProxy *proxy = opaque;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
uint64_t val = 0;
if (addr < config) {
@@ -390,16 +405,16 @@ static uint64_t virtio_pci_config_read(void *opaque, hwaddr addr,
switch (size) {
case 1:
- val = virtio_config_readb(proxy->vdev, addr);
+ val = virtio_config_readb(vdev, addr);
break;
case 2:
- val = virtio_config_readw(proxy->vdev, addr);
+ val = virtio_config_readw(vdev, addr);
if (virtio_is_big_endian()) {
val = bswap16(val);
}
break;
case 4:
- val = virtio_config_readl(proxy->vdev, addr);
+ val = virtio_config_readl(vdev, addr);
if (virtio_is_big_endian()) {
val = bswap32(val);
}
@@ -413,6 +428,7 @@ static void virtio_pci_config_write(void *opaque, hwaddr addr,
{
VirtIOPCIProxy *proxy = opaque;
uint32_t config = VIRTIO_PCI_CONFIG(&proxy->pci_dev);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
if (addr < config) {
virtio_ioport_write(proxy, addr, val);
return;
@@ -424,19 +440,19 @@ static void virtio_pci_config_write(void *opaque, hwaddr addr,
*/
switch (size) {
case 1:
- virtio_config_writeb(proxy->vdev, addr, val);
+ virtio_config_writeb(vdev, addr, val);
break;
case 2:
if (virtio_is_big_endian()) {
val = bswap16(val);
}
- virtio_config_writew(proxy->vdev, addr, val);
+ virtio_config_writew(vdev, addr, val);
break;
case 4:
if (virtio_is_big_endian()) {
val = bswap32(val);
}
- virtio_config_writel(proxy->vdev, addr, val);
+ virtio_config_writel(vdev, addr, val);
break;
}
}
@@ -455,6 +471,7 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
uint32_t val, int len)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
pci_default_write_config(pci_dev, address, val, len);
@@ -462,8 +479,7 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
!(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
!(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
virtio_pci_stop_ioeventfd(proxy);
- virtio_set_status(proxy->vdev,
- proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
+ virtio_set_status(vdev, vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
}
}
@@ -506,7 +522,8 @@ static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy,
unsigned int vector)
{
VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
- VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, queue_no);
EventNotifier *n = virtio_queue_get_guest_notifier(vq);
int ret;
ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, NULL, irqfd->virq);
@@ -517,7 +534,8 @@ static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy,
unsigned int queue_no,
unsigned int vector)
{
- VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtQueue *vq = virtio_get_queue(vdev, queue_no);
EventNotifier *n = virtio_queue_get_guest_notifier(vq);
VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
int ret;
@@ -529,7 +547,7 @@ static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy,
static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)
{
PCIDevice *dev = &proxy->pci_dev;
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
unsigned int vector;
int ret, queue_no;
@@ -578,7 +596,7 @@ undo:
static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs)
{
PCIDevice *dev = &proxy->pci_dev;
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
unsigned int vector;
int queue_no;
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
@@ -606,8 +624,9 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
unsigned int vector,
MSIMessage msg)
{
- VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(proxy->vdev);
- VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+ VirtQueue *vq = virtio_get_queue(vdev, queue_no);
EventNotifier *n = virtio_queue_get_guest_notifier(vq);
VirtIOIRQFD *irqfd;
int ret = 0;
@@ -626,10 +645,10 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
* Otherwise, set it up now.
*/
if (k->guest_notifier_mask) {
- k->guest_notifier_mask(proxy->vdev, queue_no, false);
+ k->guest_notifier_mask(vdev, queue_no, false);
/* Test after unmasking to avoid losing events. */
if (k->guest_notifier_pending &&
- k->guest_notifier_pending(proxy->vdev, queue_no)) {
+ k->guest_notifier_pending(vdev, queue_no)) {
event_notifier_set(n);
}
} else {
@@ -642,13 +661,14 @@ static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy,
unsigned int queue_no,
unsigned int vector)
{
- VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(proxy->vdev);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
/* If guest supports masking, keep irqfd but mask it.
* Otherwise, clean it up now.
*/
if (k->guest_notifier_mask) {
- k->guest_notifier_mask(proxy->vdev, queue_no, true);
+ k->guest_notifier_mask(vdev, queue_no, true);
} else {
kvm_virtio_pci_irqfd_release(proxy, queue_no, vector);
}
@@ -658,7 +678,7 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
MSIMessage msg)
{
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
int ret, queue_no;
for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) {
@@ -688,7 +708,7 @@ undo:
static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector)
{
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
int queue_no;
for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) {
@@ -707,7 +727,7 @@ static void virtio_pci_vector_poll(PCIDevice *dev,
unsigned int vector_end)
{
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
int queue_no;
unsigned int vector;
@@ -739,8 +759,9 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
bool with_irqfd)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
- VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(proxy->vdev);
- VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
if (assign) {
@@ -755,7 +776,7 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
}
if (!msix_enabled(&proxy->pci_dev) && vdc->guest_notifier_mask) {
- vdc->guest_notifier_mask(proxy->vdev, n, !assign);
+ vdc->guest_notifier_mask(vdev, n, !assign);
}
return 0;
@@ -770,7 +791,7 @@ static bool virtio_pci_query_guest_notifiers(DeviceState *d)
static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
- VirtIODevice *vdev = proxy->vdev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
int r, n;
bool with_irqfd = msix_enabled(&proxy->pci_dev) &&
@@ -864,11 +885,12 @@ static int virtio_pci_set_host_notifier(DeviceState *d, int n, bool assign)
static void virtio_pci_vmstate_change(DeviceState *d, bool running)
{
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
if (running) {
/* Try to find out if the guest has bus master disabled, but is
in ready state. Then we have a buggy guest OS. */
- if ((proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
+ if ((vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
!(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
}
@@ -943,8 +965,6 @@ static void virtio_pci_device_plugged(DeviceState *d)
uint8_t *config;
uint32_t size;
- proxy->vdev = bus->vdev;
-
config = proxy->pci_dev.config;
if (proxy->class_code) {
pci_config_set_class(config, proxy->class_code);
@@ -982,6 +1002,15 @@ static void virtio_pci_device_plugged(DeviceState *d)
proxy->host_features);
}
+static void virtio_pci_device_unplugged(DeviceState *d)
+{
+ PCIDevice *pci_dev = PCI_DEVICE(d);
+ VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
+
+ virtio_pci_stop_ioeventfd(proxy);
+ msix_uninit_exclusive_bar(pci_dev);
+}
+
static int virtio_pci_init(PCIDevice *pci_dev)
{
VirtIOPCIProxy *dev = VIRTIO_PCI(pci_dev);
@@ -996,9 +1025,7 @@ static int virtio_pci_init(PCIDevice *pci_dev)
static void virtio_pci_exit(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
- virtio_pci_stop_ioeventfd(proxy);
memory_region_destroy(&proxy->bar);
- msix_uninit_exclusive_bar(pci_dev);
}
static void virtio_pci_reset(DeviceState *qdev)
@@ -1533,6 +1560,7 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
k->set_guest_notifiers = virtio_pci_set_guest_notifiers;
k->vmstate_change = virtio_pci_vmstate_change;
k->device_plugged = virtio_pci_device_plugged;
+ k->device_unplugged = virtio_pci_device_unplugged;
}
static const TypeInfo virtio_pci_bus_info = {
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index 917bcc5348..dc332ae774 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -82,7 +82,6 @@ typedef struct VirtioPCIClass {
struct VirtIOPCIProxy {
PCIDevice pci_dev;
- VirtIODevice *vdev;
MemoryRegion bar;
uint32_t flags;
uint32_t class_code;
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index b22ccf1008..755fdee628 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -133,27 +133,27 @@ static void check_rate_limit(void *opaque)
qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + vrng->conf.period_ms);
}
-static int virtio_rng_device_init(VirtIODevice *vdev)
+static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
{
- DeviceState *qdev = DEVICE(vdev);
- VirtIORNG *vrng = VIRTIO_RNG(vdev);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIORNG *vrng = VIRTIO_RNG(dev);
Error *local_err = NULL;
if (!vrng->conf.period_ms > 0) {
- qerror_report(QERR_INVALID_PARAMETER_VALUE, "period",
- "a positive number");
- return -1;
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, "period",
+ "a positive number");
+ return;
}
if (vrng->conf.rng == NULL) {
vrng->conf.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
- object_property_add_child(OBJECT(qdev),
+ object_property_add_child(OBJECT(dev),
"default-backend",
OBJECT(vrng->conf.default_backend),
NULL);
- object_property_set_link(OBJECT(qdev),
+ object_property_set_link(OBJECT(dev),
OBJECT(vrng->conf.default_backend),
"rng", NULL);
}
@@ -162,15 +162,14 @@ static int virtio_rng_device_init(VirtIODevice *vdev)
vrng->rng = vrng->conf.rng;
if (vrng->rng == NULL) {
- qerror_report(QERR_INVALID_PARAMETER_VALUE, "rng", "a valid object");
- return -1;
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, "rng", "a valid object");
+ return;
}
rng_backend_open(vrng->rng, &local_err);
if (local_err) {
- qerror_report_err(local_err);
- error_free(local_err);
- return -1;
+ error_propagate(errp, local_err);
+ return;
}
vrng->vq = virtio_add_queue(vdev, 8, handle_input);
@@ -184,22 +183,19 @@ static int virtio_rng_device_init(VirtIODevice *vdev)
timer_mod(vrng->rate_limit_timer,
qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + vrng->conf.period_ms);
- register_savevm(qdev, "virtio-rng", -1, 1, virtio_rng_save,
+ register_savevm(dev, "virtio-rng", -1, 1, virtio_rng_save,
virtio_rng_load, vrng);
-
- return 0;
}
-static int virtio_rng_device_exit(DeviceState *qdev)
+static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp)
{
- VirtIORNG *vrng = VIRTIO_RNG(qdev);
- VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtIORNG *vrng = VIRTIO_RNG(dev);
timer_del(vrng->rate_limit_timer);
timer_free(vrng->rate_limit_timer);
- unregister_savevm(qdev, "virtio-rng", vrng);
+ unregister_savevm(dev, "virtio-rng", vrng);
virtio_cleanup(vdev);
- return 0;
}
static Property virtio_rng_properties[] = {
@@ -211,10 +207,11 @@ static void virtio_rng_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- dc->exit = virtio_rng_device_exit;
+
dc->props = virtio_rng_properties;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
- vdc->init = virtio_rng_device_init;
+ vdc->realize = virtio_rng_device_realize;
+ vdc->unrealize = virtio_rng_device_unrealize;
vdc->get_features = get_features;
}
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 2f1e73bc75..144b9ca2ef 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1150,35 +1150,49 @@ void virtio_device_set_child_bus_name(VirtIODevice *vdev, char *bus_name)
}
}
-static int virtio_device_init(DeviceState *qdev)
+static void virtio_device_realize(DeviceState *dev, Error **errp)
{
- VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
- VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(qdev);
- assert(k->init != NULL);
- if (k->init(vdev) < 0) {
- return -1;
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev);
+ Error *err = NULL;
+
+ if (vdc->realize != NULL) {
+ vdc->realize(dev, &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ return;
+ }
}
- virtio_bus_plug_device(vdev);
- return 0;
+ virtio_bus_device_plugged(vdev);
}
-static int virtio_device_exit(DeviceState *qdev)
+static void virtio_device_unrealize(DeviceState *dev, Error **errp)
{
- VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+ VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev);
+ Error *err = NULL;
+
+ if (vdc->unrealize != NULL) {
+ vdc->unrealize(dev, &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ return;
+ }
+ }
if (vdev->bus_name) {
g_free(vdev->bus_name);
vdev->bus_name = NULL;
}
- return 0;
}
static void virtio_device_class_init(ObjectClass *klass, void *data)
{
/* Set the default value here. */
DeviceClass *dc = DEVICE_CLASS(klass);
- dc->init = virtio_device_init;
- dc->exit = virtio_device_exit;
+
+ dc->realize = virtio_device_realize;
+ dc->unrealize = virtio_device_unrealize;
dc->bus_type = TYPE_VIRTIO_BUS;
}
diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index 9217f85abc..0756545d4d 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -61,7 +61,7 @@ typedef struct VirtioBusClass {
* transport independent exit function.
* This is called by virtio-bus just before the device is unplugged.
*/
- void (*device_unplug)(DeviceState *d);
+ void (*device_unplugged)(DeviceState *d);
/*
* Does the transport have variable vring alignment?
* (ie can it ever call virtio_queue_set_align()?)
@@ -72,15 +72,11 @@ typedef struct VirtioBusClass {
struct VirtioBusState {
BusState parent_obj;
- /*
- * Only one VirtIODevice can be plugged on the bus.
- */
- VirtIODevice *vdev;
};
-int virtio_bus_plug_device(VirtIODevice *vdev);
+int virtio_bus_device_plugged(VirtIODevice *vdev);
void virtio_bus_reset(VirtioBusState *bus);
-void virtio_bus_destroy_device(VirtioBusState *bus);
+void virtio_bus_device_unplugged(VirtIODevice *bus);
/* Get the device id of the plugged device. */
uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus);
/* Get the config_len field of the plugged device. */
@@ -98,4 +94,16 @@ void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config);
/* Set config of the plugged device. */
void virtio_bus_set_vdev_config(VirtioBusState *bus, uint8_t *config);
+static inline VirtIODevice *virtio_bus_get_device(VirtioBusState *bus)
+{
+ BusState *qbus = &bus->parent_obj;
+ BusChild *kid = QTAILQ_FIRST(&qbus->children);
+ DeviceState *qdev = kid ? kid->child : NULL;
+
+ /* This is used on the data path, the cast is guaranteed
+ * to succeed by the qdev machinery.
+ */
+ return (VirtIODevice *)qdev;
+}
+
#endif /* VIRTIO_BUS_H */
diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h
index debaa15d5a..14e85a5a3a 100644
--- a/include/hw/virtio/virtio-rng.h
+++ b/include/hw/virtio/virtio-rng.h
@@ -18,6 +18,8 @@
#define TYPE_VIRTIO_RNG "virtio-rng-device"
#define VIRTIO_RNG(obj) \
OBJECT_CHECK(VirtIORNG, (obj), TYPE_VIRTIO_RNG)
+#define VIRTIO_RNG_GET_PARENT_CLASS(obj) \
+ OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_RNG)
/* The Virtio ID for the virtio rng device */
#define VIRTIO_ID_RNG 4
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 9a985403c2..42b102487a 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -186,7 +186,7 @@ typedef struct {
DEFINE_PROP_BIT("param_change", _state, _feature_field, \
VIRTIO_SCSI_F_CHANGE, true)
-int virtio_scsi_common_init(VirtIOSCSICommon *vs);
-int virtio_scsi_common_exit(VirtIOSCSICommon *vs);
+void virtio_scsi_common_realize(DeviceState *dev, Error **errp);
+void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp);
#endif /* _QEMU_VIRTIO_SCSI_H */
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index a90522d6d6..3e54e90aad 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -124,9 +124,13 @@ struct VirtIODevice
};
typedef struct VirtioDeviceClass {
- /* This is what a VirtioDevice must implement */
+ /*< private >*/
DeviceClass parent;
- int (*init)(VirtIODevice *vdev);
+ /*< public >*/
+
+ /* This is what a VirtioDevice must implement */
+ DeviceRealize realize;
+ DeviceUnrealize unrealize;
uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features);
uint32_t (*bad_features)(VirtIODevice *vdev);
void (*set_features)(VirtIODevice *vdev, uint32_t val);
diff --git a/tests/qdev-monitor-test.c b/tests/qdev-monitor-test.c
index 33a8ea4b9c..ba7f9cc238 100644
--- a/tests/qdev-monitor-test.c
+++ b/tests/qdev-monitor-test.c
@@ -32,10 +32,8 @@ static void test_device_add(void)
"}}");
g_assert(response);
error = qdict_get_qdict(response, "error");
- g_assert(!strcmp(qdict_get_try_str(error, "class") ?: "",
- "GenericError"));
g_assert(!strcmp(qdict_get_try_str(error, "desc") ?: "",
- "Device initialization failed."));
+ "Device needs media, but drive is empty"));
QDECREF(response);
/* Delete the drive */