aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio
diff options
context:
space:
mode:
Diffstat (limited to 'hw/virtio')
-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
7 files changed, 189 insertions, 138 deletions
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;
}