summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/core/loader.c2
-rw-r--r--hw/s390x/ipl.c24
-rw-r--r--hw/s390x/s390-virtio-bus.c97
-rw-r--r--hw/s390x/s390-virtio-bus.h2
-rw-r--r--hw/s390x/s390-virtio-ccw.c10
-rw-r--r--hw/s390x/virtio-ccw.c134
-rw-r--r--hw/s390x/virtio-ccw.h2
7 files changed, 164 insertions, 107 deletions
diff --git a/hw/core/loader.c b/hw/core/loader.c
index e45dc0b174..76d8acace9 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -297,6 +297,7 @@ static void *load_at(int fd, int offset, int size)
 #undef elf_phdr
 #undef elf_shdr
 #undef elf_sym
+#undef elf_rela
 #undef elf_note
 #undef elf_word
 #undef elf_sword
@@ -307,6 +308,7 @@ static void *load_at(int fd, int offset, int size)
 #define elf_note	elf64_note
 #define elf_shdr	elf64_shdr
 #define elf_sym		elf64_sym
+#define elf_rela        elf64_rela
 #define elf_word        uint64_t
 #define elf_sword        int64_t
 #define bswapSZs	bswap64s
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index b57adbd99e..d6c0a49071 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -14,6 +14,7 @@
 #include "sysemu/sysemu.h"
 #include "cpu.h"
 #include "elf.h"
+#include "exec/ram_addr.h"
 #include "hw/loader.h"
 #include "hw/sysbus.h"
 #include "hw/s390x/virtio-ccw.h"
@@ -95,6 +96,16 @@ static const VMStateDescription vmstate_ipl = {
      }
 };
 
+static uint64_t bios_translate_addr(void *opaque, uint64_t srcaddr)
+{
+    uint64_t dstaddr = *(uint64_t *) opaque;
+    /*
+     * Assuming that our s390-ccw.img was linked for starting at address 0,
+     * we can simply add the destination address for the final location
+     */
+    return srcaddr + dstaddr;
+}
+
 static int s390_ipl_init(SysBusDevice *dev)
 {
     S390IPLState *ipl = S390_IPL(dev);
@@ -109,6 +120,8 @@ static int s390_ipl_init(SysBusDevice *dev)
      * even if an external kernel has been defined.
      */
     if (!ipl->kernel || ipl->enforce_bios) {
+        uint64_t fwbase = (MIN(ram_size, 0x80000000U) - 0x200000) & ~0xffffUL;
+
         if (bios_name == NULL) {
             bios_name = ipl->firmware;
         }
@@ -118,9 +131,14 @@ static int s390_ipl_init(SysBusDevice *dev)
             hw_error("could not find stage1 bootloader\n");
         }
 
-        bios_size = load_elf(bios_filename, NULL, NULL, &ipl->bios_start_addr,
-                             NULL, NULL, 1, ELF_MACHINE, 0);
-        if (bios_size < 0) {
+        bios_size = load_elf(bios_filename, bios_translate_addr, &fwbase,
+                             &ipl->bios_start_addr, NULL, NULL, 1,
+                             ELF_MACHINE, 0);
+        if (bios_size > 0) {
+            /* Adjust ELF start address to final location */
+            ipl->bios_start_addr += fwbase;
+        } else {
+            /* Try to load non-ELF file (e.g. s390-zipl.rom) */
             bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START,
                                             4096);
             ipl->bios_start_addr = ZIPL_IMAGE_START;
diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 39dc2011b9..55a5581d1b 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -111,7 +111,8 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
     return bus;
 }
 
-static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
+static void s390_virtio_device_init(VirtIOS390Device *dev,
+                                    VirtIODevice *vdev)
 {
     VirtIOS390Bus *bus;
     int dev_len;
@@ -135,25 +136,26 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
     if (dev->qdev.hotplugged) {
         s390_virtio_irq(VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
     }
-
-    return 0;
 }
 
-static int s390_virtio_net_init(VirtIOS390Device *s390_dev)
+static void s390_virtio_net_realize(VirtIOS390Device *s390_dev, Error **errp)
 {
     DeviceState *qdev = DEVICE(s390_dev);
     VirtIONetS390 *dev = VIRTIO_NET_S390(s390_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
+    Error *err = NULL;
 
     virtio_net_set_config_size(&dev->vdev, s390_dev->host_features);
     virtio_net_set_netclient_name(&dev->vdev, qdev->id,
                                   object_get_typename(OBJECT(qdev)));
     qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
-    if (qdev_init(vdev) < 0) {
-        return -1;
+    object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
     }
 
-    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
+    s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
 }
 
 static void s390_virtio_net_instance_init(Object *obj)
@@ -166,15 +168,19 @@ static void s390_virtio_net_instance_init(Object *obj)
                               "bootindex", &error_abort);
 }
 
-static int s390_virtio_blk_init(VirtIOS390Device *s390_dev)
+static void s390_virtio_blk_realize(VirtIOS390Device *s390_dev, Error **errp)
 {
     VirtIOBlkS390 *dev = VIRTIO_BLK_S390(s390_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
+    Error *err = NULL;
+
     qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
-    if (qdev_init(vdev) < 0) {
-        return -1;
+    object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
     }
-    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
+    s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
 }
 
 static void s390_virtio_blk_instance_init(Object *obj)
@@ -189,13 +195,13 @@ static void s390_virtio_blk_instance_init(Object *obj)
                               "bootindex", &error_abort);
 }
 
-static int s390_virtio_serial_init(VirtIOS390Device *s390_dev)
+static void s390_virtio_serial_realize(VirtIOS390Device *s390_dev, Error **errp)
 {
     VirtIOSerialS390 *dev = VIRTIO_SERIAL_S390(s390_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
     DeviceState *qdev = DEVICE(s390_dev);
+    Error *err = NULL;
     VirtIOS390Bus *bus;
-    int r;
     char *bus_name;
 
     bus = DO_UPCAST(VirtIOS390Bus, bus, qdev->parent_bus);
@@ -211,16 +217,14 @@ static int s390_virtio_serial_init(VirtIOS390Device *s390_dev)
     }
 
     qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
-    if (qdev_init(vdev) < 0) {
-        return -1;
+    object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
     }
 
-    r = s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
-    if (!r) {
-        bus->console = s390_dev;
-    }
-
-    return r;
+    s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
+    bus->console = s390_dev;
 }
 
 static void s390_virtio_serial_instance_init(Object *obj)
@@ -231,11 +235,12 @@ static void s390_virtio_serial_instance_init(Object *obj)
                                 TYPE_VIRTIO_SERIAL);
 }
 
-static int s390_virtio_scsi_init(VirtIOS390Device *s390_dev)
+static void s390_virtio_scsi_realize(VirtIOS390Device *s390_dev, Error **errp)
 {
     VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(s390_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
     DeviceState *qdev = DEVICE(s390_dev);
+    Error *err = NULL;
     char *bus_name;
 
     /*
@@ -249,11 +254,13 @@ static int s390_virtio_scsi_init(VirtIOS390Device *s390_dev)
     }
 
     qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
-    if (qdev_init(vdev) < 0) {
-        return -1;
+    object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
     }
 
-    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
+    s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
 }
 
 static void s390_virtio_scsi_instance_init(Object *obj)
@@ -265,17 +272,20 @@ static void s390_virtio_scsi_instance_init(Object *obj)
 }
 
 #ifdef CONFIG_VHOST_SCSI
-static int s390_vhost_scsi_init(VirtIOS390Device *s390_dev)
+static void s390_vhost_scsi_realize(VirtIOS390Device *s390_dev, Error **errp)
 {
     VHostSCSIS390 *dev = VHOST_SCSI_S390(s390_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
+    Error *err = NULL;
 
     qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
-    if (qdev_init(vdev) < 0) {
-        return -1;
+    object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
     }
 
-    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
+    s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
 }
 
 static void s390_vhost_scsi_instance_init(Object *obj)
@@ -288,21 +298,24 @@ static void s390_vhost_scsi_instance_init(Object *obj)
 #endif
 
 
-static int s390_virtio_rng_init(VirtIOS390Device *s390_dev)
+static void s390_virtio_rng_realize(VirtIOS390Device *s390_dev, Error **errp)
 {
     VirtIORNGS390 *dev = VIRTIO_RNG_S390(s390_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
+    Error *err = NULL;
 
     qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
-    if (qdev_init(vdev) < 0) {
-        return -1;
+    object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
     }
 
     object_property_set_link(OBJECT(dev),
                              OBJECT(dev->vdev.conf.rng), "rng",
                              NULL);
 
-    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
+    s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
 }
 
 static void s390_virtio_rng_instance_init(Object *obj)
@@ -509,7 +522,7 @@ static void s390_virtio_net_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 
-    k->init = s390_virtio_net_init;
+    k->realize = s390_virtio_net_realize;
     dc->props = s390_virtio_net_properties;
 }
 
@@ -525,7 +538,7 @@ static void s390_virtio_blk_class_init(ObjectClass *klass, void *data)
 {
     VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 
-    k->init = s390_virtio_blk_init;
+    k->realize = s390_virtio_blk_realize;
 }
 
 static const TypeInfo s390_virtio_blk = {
@@ -545,7 +558,7 @@ static void s390_virtio_serial_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 
-    k->init = s390_virtio_serial_init;
+    k->realize = s390_virtio_serial_realize;
     dc->props = s390_virtio_serial_properties;
 }
 
@@ -567,7 +580,7 @@ static void s390_virtio_rng_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 
-    k->init = s390_virtio_rng_init;
+    k->realize = s390_virtio_rng_realize;
     dc->props = s390_virtio_rng_properties;
 }
 
@@ -579,14 +592,14 @@ static const TypeInfo s390_virtio_rng = {
     .class_init    = s390_virtio_rng_class_init,
 };
 
-static int s390_virtio_busdev_init(DeviceState *dev)
+static void s390_virtio_busdev_realize(DeviceState *dev, Error **errp)
 {
     VirtIOS390Device *_dev = (VirtIOS390Device *)dev;
     VirtIOS390DeviceClass *_info = VIRTIO_S390_DEVICE_GET_CLASS(dev);
 
     virtio_s390_bus_new(&_dev->bus, sizeof(_dev->bus), _dev);
 
-    return _info->init(_dev);
+    _info->realize(_dev, errp);
 }
 
 static void s390_virtio_busdev_reset(DeviceState *dev)
@@ -600,7 +613,7 @@ static void virtio_s390_device_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->init = s390_virtio_busdev_init;
+    dc->realize = s390_virtio_busdev_realize;
     dc->bus_type = TYPE_S390_VIRTIO_BUS;
     dc->reset = s390_virtio_busdev_reset;
 }
@@ -625,7 +638,7 @@ static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 
-    k->init = s390_virtio_scsi_init;
+    k->realize = s390_virtio_scsi_realize;
     dc->props = s390_virtio_scsi_properties;
 }
 
@@ -648,7 +661,7 @@ static void s390_vhost_scsi_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
 
-    k->init = s390_vhost_scsi_init;
+    k->realize = s390_vhost_scsi_realize;
     dc->props = s390_vhost_scsi_properties;
 }
 
diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h
index 92aa9d0499..810a6ef1fc 100644
--- a/hw/s390x/s390-virtio-bus.h
+++ b/hw/s390x/s390-virtio-bus.h
@@ -83,7 +83,7 @@ typedef struct VirtIOS390Device VirtIOS390Device;
 
 typedef struct VirtIOS390DeviceClass {
     DeviceClass qdev;
-    int (*init)(VirtIOS390Device *dev);
+    void (*realize)(VirtIOS390Device *dev, Error **errp);
 } VirtIOS390DeviceClass;
 
 struct VirtIOS390Device {
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 8f0ae59b5f..dac00cec7c 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -97,6 +97,7 @@ static void ccw_init(MachineState *machine)
     ram_addr_t pad_size = 0;
     ram_addr_t maxmem = qemu_opt_get_size(opts, "maxmem", my_ram_size);
     ram_addr_t standby_mem_size = maxmem - my_ram_size;
+    uint64_t kvm_limit;
 
     /* The storage increment size is a multiple of 1M and is a power of 2.
      * The number of storage increments must be MAX_STORAGE_INCREMENTS or fewer.
@@ -121,6 +122,15 @@ static void ccw_init(MachineState *machine)
 
     /* let's propagate the changed ram size into the global variable. */
     ram_size = my_ram_size;
+    machine->maxram_size = my_ram_size + standby_mem_size;
+
+    ret = s390_set_memory_limit(machine->maxram_size, &kvm_limit);
+    if (ret == -E2BIG) {
+        hw_error("qemu: host supports a maximum of %" PRIu64 " GB",
+                 kvm_limit >> 30);
+    } else if (ret) {
+        hw_error("qemu: setting the guest size failed");
+    }
 
     /* get a BUS */
     css_bus = virtual_css_bus_init();
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index ffbb9c2c89..fce52a929c 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -607,7 +607,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
     return ret;
 }
 
-static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
+static void virtio_ccw_device_realize(VirtioCcwDevice *dev,
+                                      VirtIODevice *vdev, Error **errp)
 {
     unsigned int cssid = 0;
     unsigned int ssid = 0;
@@ -616,7 +617,6 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
     bool have_devno = false;
     bool found = false;
     SubchDev *sch;
-    int ret;
     int num;
     DeviceState *parent = DEVICE(dev);
 
@@ -639,21 +639,19 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
         num = sscanf(dev->bus_id, "%x.%x.%04x", &cssid, &ssid, &devno);
         if (num == 3) {
             if ((cssid > MAX_CSSID) || (ssid > MAX_SSID)) {
-                ret = -EINVAL;
-                error_report("Invalid cssid or ssid: cssid %x, ssid %x",
-                             cssid, ssid);
+                error_setg(errp, "Invalid cssid or ssid: cssid %x, ssid %x",
+                           cssid, ssid);
                 goto out_err;
             }
             /* Enforce use of virtual cssid. */
             if (cssid != VIRTUAL_CSSID) {
-                ret = -EINVAL;
-                error_report("cssid %x not valid for virtio devices", cssid);
+                error_setg(errp, "cssid %x not valid for virtio devices",
+                           cssid);
                 goto out_err;
             }
             if (css_devno_used(cssid, ssid, devno)) {
-                ret = -EEXIST;
-                error_report("Device %x.%x.%04x already exists", cssid, ssid,
-                             devno);
+                error_setg(errp, "Device %x.%x.%04x already exists",
+                           cssid, ssid, devno);
                 goto out_err;
             }
             sch->cssid = cssid;
@@ -661,8 +659,7 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
             sch->devno = devno;
             have_devno = true;
         } else {
-            ret = -EINVAL;
-            error_report("Malformed devno parameter '%s'", dev->bus_id);
+            error_setg(errp, "Malformed devno parameter '%s'", dev->bus_id);
             goto out_err;
         }
     }
@@ -678,9 +675,8 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
             }
         }
         if (!found) {
-            ret = -ENODEV;
-            error_report("No free subchannel found for %x.%x.%04x", cssid, ssid,
-                         devno);
+            error_setg(errp, "No free subchannel found for %x.%x.%04x",
+                       cssid, ssid, devno);
             goto out_err;
         }
         trace_virtio_ccw_new_device(cssid, ssid, schid, devno,
@@ -702,8 +698,7 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
                         if (devno == MAX_SCHID) {
                             devno = 0;
                         } else if (devno == schid - 1) {
-                            ret = -ENODEV;
-                            error_report("No free devno found");
+                            error_setg(errp, "No free devno found");
                             goto out_err;
                         } else {
                             devno++;
@@ -720,8 +715,7 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
             }
         }
         if (!found) {
-            ret = -ENODEV;
-            error_report("Virtual channel subsystem is full!");
+            error_setg(errp, "Virtual channel subsystem is full!");
             goto out_err;
         }
         trace_virtio_ccw_new_device(cssid, ssid, schid, devno,
@@ -748,12 +742,11 @@ static int virtio_ccw_device_init(VirtioCcwDevice *dev, VirtIODevice *vdev)
 
     css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
                           parent->hotplugged, 1);
-    return 0;
+    return;
 
 out_err:
     dev->sch = NULL;
     g_free(sch);
-    return ret;
 }
 
 static int virtio_ccw_exit(VirtioCcwDevice *dev)
@@ -771,21 +764,24 @@ static int virtio_ccw_exit(VirtioCcwDevice *dev)
     return 0;
 }
 
-static int virtio_ccw_net_init(VirtioCcwDevice *ccw_dev)
+static void virtio_ccw_net_realize(VirtioCcwDevice *ccw_dev, Error **errp)
 {
     DeviceState *qdev = DEVICE(ccw_dev);
     VirtIONetCcw *dev = VIRTIO_NET_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
+    Error *err = NULL;
 
     virtio_net_set_config_size(&dev->vdev, ccw_dev->host_features[0]);
     virtio_net_set_netclient_name(&dev->vdev, qdev->id,
                                   object_get_typename(OBJECT(qdev)));
     qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
-    if (qdev_init(vdev) < 0) {
-        return -1;
+    object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
     }
 
-    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
+    virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp);
 }
 
 static void virtio_ccw_net_instance_init(Object *obj)
@@ -798,16 +794,20 @@ static void virtio_ccw_net_instance_init(Object *obj)
                               "bootindex", &error_abort);
 }
 
-static int virtio_ccw_blk_init(VirtioCcwDevice *ccw_dev)
+static void virtio_ccw_blk_realize(VirtioCcwDevice *ccw_dev, Error **errp)
 {
     VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
+    Error *err = NULL;
+
     qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
-    if (qdev_init(vdev) < 0) {
-        return -1;
+    object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
     }
 
-    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
+    virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp);
 }
 
 static void virtio_ccw_blk_instance_init(Object *obj)
@@ -822,11 +822,12 @@ static void virtio_ccw_blk_instance_init(Object *obj)
                               "bootindex", &error_abort);
 }
 
-static int virtio_ccw_serial_init(VirtioCcwDevice *ccw_dev)
+static void virtio_ccw_serial_realize(VirtioCcwDevice *ccw_dev, Error **errp)
 {
     VirtioSerialCcw *dev = VIRTIO_SERIAL_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
     DeviceState *proxy = DEVICE(ccw_dev);
+    Error *err = NULL;
     char *bus_name;
 
     /*
@@ -840,11 +841,13 @@ static int virtio_ccw_serial_init(VirtioCcwDevice *ccw_dev)
     }
 
     qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
-    if (qdev_init(vdev) < 0) {
-        return -1;
+    object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
     }
 
-    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
+    virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp);
 }
 
 
@@ -856,17 +859,20 @@ static void virtio_ccw_serial_instance_init(Object *obj)
                                 TYPE_VIRTIO_SERIAL);
 }
 
-static int virtio_ccw_balloon_init(VirtioCcwDevice *ccw_dev)
+static void virtio_ccw_balloon_realize(VirtioCcwDevice *ccw_dev, Error **errp)
 {
     VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
+    Error *err = NULL;
 
     qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
-    if (qdev_init(vdev) < 0) {
-        return -1;
+    object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
     }
 
-    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
+    virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp);
 }
 
 static void balloon_ccw_stats_get_all(Object *obj, struct Visitor *v,
@@ -909,11 +915,12 @@ static void virtio_ccw_balloon_instance_init(Object *obj)
                         NULL, dev, NULL);
 }
 
-static int virtio_ccw_scsi_init(VirtioCcwDevice *ccw_dev)
+static void virtio_ccw_scsi_realize(VirtioCcwDevice *ccw_dev, Error **errp)
 {
     VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
     DeviceState *qdev = DEVICE(ccw_dev);
+    Error *err = NULL;
     char *bus_name;
 
     /*
@@ -927,11 +934,13 @@ static int virtio_ccw_scsi_init(VirtioCcwDevice *ccw_dev)
     }
 
     qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
-    if (qdev_init(vdev) < 0) {
-        return -1;
+    object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
     }
 
-    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
+    virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp);
 }
 
 static void virtio_ccw_scsi_instance_init(Object *obj)
@@ -945,17 +954,20 @@ static void virtio_ccw_scsi_instance_init(Object *obj)
 }
 
 #ifdef CONFIG_VHOST_SCSI
-static int vhost_ccw_scsi_init(VirtioCcwDevice *ccw_dev)
+static void vhost_ccw_scsi_realize(VirtioCcwDevice *ccw_dev, Error **errp)
 {
     VHostSCSICcw *dev = VHOST_SCSI_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
+    Error *err = NULL;
 
     qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
-    if (qdev_init(vdev) < 0) {
-        return -1;
+    object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
     }
 
-    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
+    virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp);
 }
 
 static void vhost_ccw_scsi_instance_init(Object *obj)
@@ -967,21 +979,24 @@ static void vhost_ccw_scsi_instance_init(Object *obj)
 }
 #endif
 
-static int virtio_ccw_rng_init(VirtioCcwDevice *ccw_dev)
+static void virtio_ccw_rng_realize(VirtioCcwDevice *ccw_dev, Error **errp)
 {
     VirtIORNGCcw *dev = VIRTIO_RNG_CCW(ccw_dev);
     DeviceState *vdev = DEVICE(&dev->vdev);
+    Error *err = NULL;
 
     qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
-    if (qdev_init(vdev) < 0) {
-        return -1;
+    object_property_set_bool(OBJECT(vdev), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
     }
 
     object_property_set_link(OBJECT(dev),
                              OBJECT(dev->vdev.conf.rng), "rng",
                              NULL);
 
-    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
+    virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp);
 }
 
 /* DeviceState to VirtioCcwDevice. Note: used on datapath,
@@ -1391,7 +1406,7 @@ static void virtio_ccw_net_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
-    k->init = virtio_ccw_net_init;
+    k->realize = virtio_ccw_net_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = virtio_ccw_net_properties;
@@ -1417,7 +1432,7 @@ static void virtio_ccw_blk_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
-    k->init = virtio_ccw_blk_init;
+    k->realize = virtio_ccw_blk_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = virtio_ccw_blk_properties;
@@ -1443,7 +1458,7 @@ static void virtio_ccw_serial_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
-    k->init = virtio_ccw_serial_init;
+    k->realize = virtio_ccw_serial_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = virtio_ccw_serial_properties;
@@ -1469,7 +1484,7 @@ static void virtio_ccw_balloon_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
-    k->init = virtio_ccw_balloon_init;
+    k->realize = virtio_ccw_balloon_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = virtio_ccw_balloon_properties;
@@ -1496,7 +1511,7 @@ static void virtio_ccw_scsi_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
-    k->init = virtio_ccw_scsi_init;
+    k->realize = virtio_ccw_scsi_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = virtio_ccw_scsi_properties;
@@ -1521,7 +1536,7 @@ static void vhost_ccw_scsi_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
-    k->init = vhost_ccw_scsi_init;
+    k->realize = vhost_ccw_scsi_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = vhost_ccw_scsi_properties;
@@ -1558,7 +1573,7 @@ static void virtio_ccw_rng_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
-    k->init = virtio_ccw_rng_init;
+    k->realize = virtio_ccw_rng_realize;
     k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = virtio_ccw_rng_properties;
@@ -1572,14 +1587,13 @@ static const TypeInfo virtio_ccw_rng = {
     .class_init    = virtio_ccw_rng_class_init,
 };
 
-static int virtio_ccw_busdev_init(DeviceState *dev)
+static void virtio_ccw_busdev_realize(DeviceState *dev, Error **errp)
 {
     VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
     VirtIOCCWDeviceClass *_info = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
 
     virtio_ccw_bus_new(&_dev->bus, sizeof(_dev->bus), _dev);
-
-    return _info->init(_dev);
+    _info->realize(_dev, errp);
 }
 
 static int virtio_ccw_busdev_exit(DeviceState *dev)
@@ -1622,7 +1636,7 @@ static void virtio_ccw_device_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->props = virtio_ccw_properties;
-    dc->init = virtio_ccw_busdev_init;
+    dc->realize = virtio_ccw_busdev_realize;
     dc->exit = virtio_ccw_busdev_exit;
     dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
 }
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 5a1f16ee5d..4fceda735a 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -64,7 +64,7 @@ typedef struct VirtioCcwDevice VirtioCcwDevice;
 
 typedef struct VirtIOCCWDeviceClass {
     DeviceClass parent_class;
-    int (*init)(VirtioCcwDevice *dev);
+    void (*realize)(VirtioCcwDevice *dev, Error **errp);
     int (*exit)(VirtioCcwDevice *dev);
 } VirtIOCCWDeviceClass;