qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/4] qdev: init() callback retval + error reporting
@ 2009-08-26 13:19 Gerd Hoffmann
  2009-08-26 13:19 ` [Qemu-devel] [PATCH 1/4] qdev: add return value to init() callbacks Gerd Hoffmann
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2009-08-26 13:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

  Hi,

This is a respin of the qdev init callback patch series. 
Rebased to master, fixed a few build failures.  No other changes.

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 1/4] qdev: add return value to init() callbacks.
  2009-08-26 13:19 [Qemu-devel] [PATCH 0/4] qdev: init() callback retval + error reporting Gerd Hoffmann
@ 2009-08-26 13:19 ` Gerd Hoffmann
  2009-08-26 13:19 ` [Qemu-devel] [PATCH 2/4] add qemu_error() + friends Gerd Hoffmann
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2009-08-26 13:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Sorry folks, but it has to be.  One more of these invasive qdev patches.

We have a serious design bug in the qdev interface:  device init
callbacks can't signal failure because the init() callback has no
return value.  This patch fixes it.

We have already one case in-tree where this is needed:
Try -device virtio-blk-pci (without drive= specified) and watch qemu
segfault.  This patch fixes it.

With usb+scsi being converted to qdev we'll get more devices where the
init callback can fail for various reasons.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/ac97.c                  |    3 ++-
 hw/ads7846.c               |    3 ++-
 hw/apb_pci.c               |    6 ++++--
 hw/arm_sysctl.c            |    3 ++-
 hw/arm_timer.c             |    6 ++++--
 hw/armv7m.c                |    3 ++-
 hw/armv7m_nvic.c           |    3 ++-
 hw/bitbang_i2c.c           |    3 ++-
 hw/cirrus_vga.c            |    3 ++-
 hw/cs4231.c                |    3 ++-
 hw/e1000.c                 |    3 ++-
 hw/eccmemctl.c             |    3 ++-
 hw/eepro100.c              |   15 ++++++++-------
 hw/es1370.c                |    3 ++-
 hw/escc.c                  |    3 ++-
 hw/esp.c                   |    3 ++-
 hw/etraxfs_pic.c           |    3 ++-
 hw/etraxfs_ser.c           |    3 ++-
 hw/etraxfs_timer.c         |    3 ++-
 hw/fdc.c                   |   15 ++++++++-------
 hw/grackle_pci.c           |   12 ++++++++----
 hw/i2c.c                   |    4 ++--
 hw/i2c.h                   |    2 +-
 hw/integratorcp.c          |    6 ++++--
 hw/iommu.c                 |    3 ++-
 hw/isa-bus.c               |    4 ++--
 hw/isa.h                   |    2 +-
 hw/lm832x.c                |    3 ++-
 hw/lsi53c895a.c            |    3 ++-
 hw/m48t59.c                |    3 ++-
 hw/marvell_88w8618_audio.c |    3 ++-
 hw/max111x.c               |   11 ++++++-----
 hw/max7310.c               |    3 ++-
 hw/mpcore.c                |    6 ++++--
 hw/musicpal.c              |   24 ++++++++++++++++--------
 hw/ne2000.c                |    3 ++-
 hw/pci.c                   |    4 ++--
 hw/pci.h                   |    2 +-
 hw/pckbd.c                 |    3 ++-
 hw/pcnet.c                 |   11 ++++++-----
 hw/piix_pci.c              |   12 ++++++++----
 hw/pl011.c                 |   11 ++++++-----
 hw/pl022.c                 |    3 ++-
 hw/pl031.c                 |    3 ++-
 hw/pl050.c                 |   11 ++++++-----
 hw/pl061.c                 |    3 ++-
 hw/pl080.c                 |   11 ++++++-----
 hw/pl110.c                 |    7 ++++---
 hw/pl181.c                 |    3 ++-
 hw/pl190.c                 |    3 ++-
 hw/pxa2xx.c                |    6 ++++--
 hw/qdev.c                  |    9 ++++++---
 hw/qdev.h                  |    4 ++--
 hw/realview_gic.c          |    3 ++-
 hw/rtl8139.c               |    3 ++-
 hw/sbi.c                   |    3 ++-
 hw/slavio_intctl.c         |    3 ++-
 hw/slavio_misc.c           |    6 ++++--
 hw/slavio_timer.c          |    3 ++-
 hw/smbus.c                 |    4 ++--
 hw/smbus.h                 |    2 +-
 hw/smbus_eeprom.c          |    3 ++-
 hw/smc91c111.c             |    3 ++-
 hw/sparc32_dma.c           |    3 ++-
 hw/spitz.c                 |    6 ++++--
 hw/ssd0303.c               |    3 ++-
 hw/ssd0323.c               |    3 ++-
 hw/ssi-sd.c                |    3 ++-
 hw/ssi.c                   |    4 ++--
 hw/ssi.h                   |    2 +-
 hw/stellaris.c             |   19 ++++++++++++-------
 hw/stellaris_enet.c        |    3 ++-
 hw/sun4c_intctl.c          |    3 ++-
 hw/sun4m.c                 |    9 ++++++---
 hw/sun4u.c                 |    9 ++++++---
 hw/syborg_fb.c             |    3 ++-
 hw/syborg_interrupt.c      |    3 ++-
 hw/syborg_keyboard.c       |    3 ++-
 hw/syborg_pointer.c        |    3 ++-
 hw/syborg_rtc.c            |    3 ++-
 hw/syborg_serial.c         |    3 ++-
 hw/syborg_timer.c          |    3 ++-
 hw/syborg_virtio.c         |    7 ++++---
 hw/sysbus.c                |    4 ++--
 hw/sysbus.h                |    2 +-
 hw/tcx.c                   |    3 ++-
 hw/tmp105.c                |    3 ++-
 hw/tosa.c                  |    6 ++++--
 hw/twl92230.c              |    3 ++-
 hw/unin_pci.c              |   24 ++++++++++++++++--------
 hw/versatile_pci.c         |   10 ++++++----
 hw/versatilepb.c           |    3 ++-
 hw/vga.c                   |    5 +++--
 hw/virtio-pci.c            |   13 +++++++++----
 hw/vmware_vga.c            |    3 ++-
 hw/wm8750.c                |    3 ++-
 hw/xilinx_ethlite.c        |    3 ++-
 hw/xilinx_intc.c           |    3 ++-
 hw/xilinx_timer.c          |    3 ++-
 hw/xilinx_uartlite.c       |    3 ++-
 100 files changed, 320 insertions(+), 190 deletions(-)

diff --git a/hw/ac97.c b/hw/ac97.c
index 3c70d8c..610ca60 100644
--- a/hw/ac97.c
+++ b/hw/ac97.c
@@ -1291,7 +1291,7 @@ static void ac97_on_reset (void *opaque)
     mixer_reset (s);
 }
 
-static void ac97_initfn (PCIDevice *dev)
+static int ac97_initfn (PCIDevice *dev)
 {
     AC97LinkState *s = DO_UPCAST (AC97LinkState, dev, dev);
     uint8_t *c = s->dev.config;
@@ -1337,6 +1337,7 @@ static void ac97_initfn (PCIDevice *dev)
     qemu_register_reset (ac97_on_reset, s);
     AUD_register_card ("ac97", &s->card);
     ac97_on_reset (s);
+    return 0;
 }
 
 int ac97_init (PCIBus *bus)
diff --git a/hw/ads7846.c b/hw/ads7846.c
index 7d1cbc7..184b3dd 100644
--- a/hw/ads7846.c
+++ b/hw/ads7846.c
@@ -134,7 +134,7 @@ static int ads7846_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void ads7846_init(SSISlave *dev)
+static int ads7846_init(SSISlave *dev)
 {
     ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, dev);
 
@@ -152,6 +152,7 @@ static void ads7846_init(SSISlave *dev)
     ads7846_int_update(s);
 
     register_savevm("ads7846", -1, 0, ads7846_save, ads7846_load, s);
+    return 0;
 }
 
 static SSISlaveInfo ads7846_info = {
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 13284c6..d114e55 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -260,7 +260,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
     return d->host_state.bus;
 }
 
-static void pci_pbm_init_device(SysBusDevice *dev)
+static int pci_pbm_init_device(SysBusDevice *dev)
 {
 
     APBState *s;
@@ -283,9 +283,10 @@ static void pci_pbm_init_device(SysBusDevice *dev)
     pci_mem_data = cpu_register_io_memory(pci_apb_read,
                                           pci_apb_write, &s->host_state);
     sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
+    return 0;
 }
 
-static void pbm_pci_host_init(PCIDevice *d)
+static int pbm_pci_host_init(PCIDevice *d)
 {
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_SUN);
     pci_config_set_device_id(d->config, PCI_DEVICE_ID_SUN_SABRE);
@@ -298,6 +299,7 @@ static void pbm_pci_host_init(PCIDevice *d)
     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
     d->config[0x0D] = 0x10; // latency_timer
     d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
+    return 0;
 }
 
 static PCIDeviceInfo pbm_pci_host_info = {
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 2b494e4..686c1cc 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -189,7 +189,7 @@ static CPUWriteMemoryFunc * const arm_sysctl_writefn[] = {
    arm_sysctl_write
 };
 
-static void arm_sysctl_init1(SysBusDevice *dev)
+static int arm_sysctl_init1(SysBusDevice *dev)
 {
     arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
     int iomemtype;
@@ -201,6 +201,7 @@ static void arm_sysctl_init1(SysBusDevice *dev)
                                        arm_sysctl_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     /* ??? Save/restore.  */
+    return 0;
 }
 
 /* Legacy helper function.  */
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 25cbf66..9fef191 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -254,7 +254,7 @@ static int sp804_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void sp804_init(SysBusDevice *dev)
+static int sp804_init(SysBusDevice *dev)
 {
     int iomemtype;
     sp804_state *s = FROM_SYSBUS(sp804_state, dev);
@@ -272,6 +272,7 @@ static void sp804_init(SysBusDevice *dev)
                                        sp804_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     register_savevm("sp804", -1, 1, sp804_save, sp804_load, s);
+    return 0;
 }
 
 
@@ -323,7 +324,7 @@ static CPUWriteMemoryFunc * const icp_pit_writefn[] = {
    icp_pit_write
 };
 
-static void icp_pit_init(SysBusDevice *dev)
+static int icp_pit_init(SysBusDevice *dev)
 {
     int iomemtype;
     icp_pit_state *s = FROM_SYSBUS(icp_pit_state, dev);
@@ -343,6 +344,7 @@ static void icp_pit_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     /* This device has no state to save/restore.  The component timers will
        save themselves.  */
+    return 0;
 }
 
 static void arm_timer_register_devices(void)
diff --git a/hw/armv7m.c b/hw/armv7m.c
index bf91331..059a356 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -122,7 +122,7 @@ typedef struct {
     uint32_t base;
 } BitBandState;
 
-static void bitband_init(SysBusDevice *dev)
+static int bitband_init(SysBusDevice *dev)
 {
     BitBandState *s = FROM_SYSBUS(BitBandState, dev);
     int iomemtype;
@@ -130,6 +130,7 @@ static void bitband_init(SysBusDevice *dev)
     iomemtype = cpu_register_io_memory(bitband_readfn, bitband_writefn,
                                        &s->base);
     sysbus_init_mmio(dev, 0x02000000, iomemtype);
+    return 0;
 }
 
 static void armv7m_bitband_init(void)
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index f789c78..3360808 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -390,7 +390,7 @@ static int nvic_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void armv7m_nvic_init(SysBusDevice *dev)
+static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
 
@@ -398,6 +398,7 @@ static void armv7m_nvic_init(SysBusDevice *dev)
     cpu_register_physical_memory(0xe000e000, 0x1000, s->gic.iomemtype);
     s->systick.timer = qemu_new_timer(vm_clock, systick_timer_tick, s);
     register_savevm("armv7m_nvic", -1, 1, nvic_save, nvic_load, s);
+    return 0;
 }
 
 static void armv7m_nvic_register_devices(void)
diff --git a/hw/bitbang_i2c.c b/hw/bitbang_i2c.c
index 9ab04cc..0bd9eb6 100644
--- a/hw/bitbang_i2c.c
+++ b/hw/bitbang_i2c.c
@@ -153,7 +153,7 @@ static void bitbang_i2c_gpio_set(void *opaque, int irq, int level)
     i2c->last_clock = clock;
 }
 
-static void bitbang_i2c_init(SysBusDevice *dev)
+static int bitbang_i2c_init(SysBusDevice *dev)
 {
     bitbang_i2c_interface *s = FROM_SYSBUS(bitbang_i2c_interface, dev);
     i2c_bus *bus;
@@ -168,6 +168,7 @@ static void bitbang_i2c_init(SysBusDevice *dev)
 
     qdev_init_gpio_in(&dev->qdev, bitbang_i2c_gpio_set, 2);
     qdev_init_gpio_out(&dev->qdev, &s->out, 1);
+    return 0;
 }
 
 static void bitbang_i2c_register(void)
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 64ff524..6e9cbd4 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3302,7 +3302,7 @@ static void pci_cirrus_write_config(PCIDevice *d,
     cirrus_update_memory_access(s);
 }
 
-static void pci_cirrus_vga_initfn(PCIDevice *dev)
+static int pci_cirrus_vga_initfn(PCIDevice *dev)
 {
      PCICirrusVGAState *d = DO_UPCAST(PCICirrusVGAState, dev, dev);
      CirrusVGAState *s = &d->cirrus_vga;
@@ -3335,6 +3335,7 @@ static void pci_cirrus_vga_initfn(PCIDevice *dev)
                           PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
      }
      /* XXX: ROM BIOS */
+     return 0;
 }
 
 void pci_cirrus_vga_init(PCIBus *bus)
diff --git a/hw/cs4231.c b/hw/cs4231.c
index 82e2f52..843f86e 100644
--- a/hw/cs4231.c
+++ b/hw/cs4231.c
@@ -167,7 +167,7 @@ static int cs_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void cs4231_init1(SysBusDevice *dev)
+static int cs4231_init1(SysBusDevice *dev)
 {
     int io;
     CSState *s = FROM_SYSBUS(CSState, dev);
@@ -179,6 +179,7 @@ static void cs4231_init1(SysBusDevice *dev)
     register_savevm("cs4231", -1, 1, cs_save, cs_load, s);
     qemu_register_reset(cs_reset, s);
     cs_reset(s);
+    return 0;
 }
 
 static SysBusDeviceInfo cs4231_info = {
diff --git a/hw/e1000.c b/hw/e1000.c
index d95a6c8..0253d3b 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -1081,7 +1081,7 @@ static void e1000_reset(void *opaque)
     memset(&d->tx, 0, sizeof d->tx);
 }
 
-static void pci_e1000_init(PCIDevice *pci_dev)
+static int pci_e1000_init(PCIDevice *pci_dev)
 {
     E1000State *d = (E1000State *)pci_dev;
     uint8_t *pci_conf;
@@ -1132,6 +1132,7 @@ static void pci_e1000_init(PCIDevice *pci_dev)
     d->dev.unregister = pci_e1000_uninit;
     qemu_register_reset(e1000_reset, d);
     e1000_reset(d);
+    return 0;
 }
 
 static PCIDeviceInfo e1000_info = {
diff --git a/hw/eccmemctl.c b/hw/eccmemctl.c
index c8eac38..0d85084 100644
--- a/hw/eccmemctl.c
+++ b/hw/eccmemctl.c
@@ -315,7 +315,7 @@ static void ecc_reset(void *opaque)
     s->regs[ECC_ECR1] = 0;
 }
 
-static void ecc_init1(SysBusDevice *dev)
+static int ecc_init1(SysBusDevice *dev)
 {
     int ecc_io_memory;
     ECCState *s = FROM_SYSBUS(ECCState, dev);
@@ -333,6 +333,7 @@ static void ecc_init1(SysBusDevice *dev)
     register_savevm("ECC", -1, 3, ecc_save, ecc_load, s);
     qemu_register_reset(ecc_reset, s);
     ecc_reset(s);
+    return 0;
 }
 
 static SysBusDeviceInfo ecc_info = {
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 8988b3f..708f4b5 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1728,7 +1728,7 @@ static int pci_nic_uninit(PCIDevice *dev)
     return 0;
 }
 
-static void nic_init(PCIDevice *pci_dev, uint32_t device)
+static int nic_init(PCIDevice *pci_dev, uint32_t device)
 {
     PCIEEPRO100State *d = (PCIEEPRO100State *)pci_dev;
     EEPRO100State *s;
@@ -1774,21 +1774,22 @@ static void nic_init(PCIDevice *pci_dev, uint32_t device)
     qemu_register_reset(nic_reset, s);
 
     register_savevm(s->vc->model, -1, 3, nic_save, nic_load, s);
+    return 0;
 }
 
-static void pci_i82551_init(PCIDevice *dev)
+static int pci_i82551_init(PCIDevice *dev)
 {
-    nic_init(dev, i82551);
+    return nic_init(dev, i82551);
 }
 
-static void pci_i82557b_init(PCIDevice *dev)
+static int pci_i82557b_init(PCIDevice *dev)
 {
-    nic_init(dev, i82557B);
+    return nic_init(dev, i82557B);
 }
 
-static void pci_i82559er_init(PCIDevice *dev)
+static int pci_i82559er_init(PCIDevice *dev)
 {
-    nic_init(dev, i82559ER);
+    return nic_init(dev, i82559ER);
 }
 
 static PCIDeviceInfo eepro100_info[] = {
diff --git a/hw/es1370.c b/hw/es1370.c
index 305b6e7..9071a48 100644
--- a/hw/es1370.c
+++ b/hw/es1370.c
@@ -998,7 +998,7 @@ static void es1370_on_reset (void *opaque)
     es1370_reset (s);
 }
 
-static void es1370_initfn (PCIDevice *dev)
+static int es1370_initfn (PCIDevice *dev)
 {
     ES1370State *s = DO_UPCAST (ES1370State, dev, dev);
     uint8_t *c = s->dev.config;
@@ -1033,6 +1033,7 @@ static void es1370_initfn (PCIDevice *dev)
 
     AUD_register_card ("es1370", &s->card);
     es1370_reset (s);
+    return 0;
 }
 
 int es1370_init (PCIBus *bus)
diff --git a/hw/escc.c b/hw/escc.c
index ae3b802..491c4cf 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -911,7 +911,7 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
     sysbus_mmio_map(s, 0, base);
 }
 
-static void escc_init1(SysBusDevice *dev)
+static int escc_init1(SysBusDevice *dev)
 {
     SerialState *s = FROM_SYSBUS(SerialState, dev);
     int io;
@@ -945,6 +945,7 @@ static void escc_init1(SysBusDevice *dev)
     register_savevm("escc", -1, 2, escc_save, escc_load, s);
     qemu_register_reset(escc_reset, s);
     escc_reset(s);
+    return 0;
 }
 
 static SysBusDeviceInfo escc_info = {
diff --git a/hw/esp.c b/hw/esp.c
index ed3cb58..aad547e 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -682,7 +682,7 @@ void esp_init(target_phys_addr_t espaddr, int it_shift,
     *reset = qdev_get_gpio_in(dev, 0);
 }
 
-static void esp_init1(SysBusDevice *dev)
+static int esp_init1(SysBusDevice *dev)
 {
     ESPState *s = FROM_SYSBUS(ESPState, dev);
     int esp_io_memory;
@@ -701,6 +701,7 @@ static void esp_init1(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, parent_esp_reset, 1);
 
     scsi_bus_new(&dev->qdev, esp_scsi_attach);
+    return 0;
 }
 
 static void esp_register_devices(void)
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index 6e063c8..b2c4859 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -136,7 +136,7 @@ static void irq_handler(void *opaque, int irq, int level)
     pic_update(fs);
 }
 
-static void etraxfs_pic_init(SysBusDevice *dev)
+static int etraxfs_pic_init(SysBusDevice *dev)
 {
     struct etrax_pic *s = FROM_SYSBUS(typeof (*s), dev);
     int intr_vect_regs;
@@ -147,6 +147,7 @@ static void etraxfs_pic_init(SysBusDevice *dev)
 
     intr_vect_regs = cpu_register_io_memory(pic_read, pic_write, s);
     sysbus_init_mmio(dev, R_MAX * 4, intr_vect_regs);
+    return 0;
 }
 
 static SysBusDeviceInfo etraxfs_pic_info = {
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index 5b5b6c0..e1f9615 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -161,7 +161,7 @@ static void serial_event(void *opaque, int event)
 
 }
 
-static void etraxfs_ser_init(SysBusDevice *dev)
+static int etraxfs_ser_init(SysBusDevice *dev)
 {
     struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
     int ser_regs;
@@ -178,6 +178,7 @@ static void etraxfs_ser_init(SysBusDevice *dev)
         qemu_chr_add_handlers(s->chr,
                       serial_can_receive, serial_receive,
                       serial_event, s);
+    return 0;
 }
 
 static void etraxfs_serial_register(void)
diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c
index c2b2b10..87700d4 100644
--- a/hw/etraxfs_timer.c
+++ b/hw/etraxfs_timer.c
@@ -308,7 +308,7 @@ static void etraxfs_timer_reset(void *opaque)
     qemu_irq_lower(t->irq);
 }
 
-static void etraxfs_timer_init(SysBusDevice *dev)
+static int etraxfs_timer_init(SysBusDevice *dev)
 {
     struct etrax_timer *t = FROM_SYSBUS(typeof (*t), dev);
     int timer_regs;
@@ -327,6 +327,7 @@ static void etraxfs_timer_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x5c, timer_regs);
 
     qemu_register_reset(etraxfs_timer_reset, t);
+    return 0;
 }
 
 static void etraxfs_timer_register(void)
diff --git a/hw/fdc.c b/hw/fdc.c
index dabbf3a..21feb27 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1925,7 +1925,7 @@ fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base,
     return fdctrl;
 }
 
-static void fdctrl_init_common(fdctrl_t *fdctrl)
+static int fdctrl_init_common(fdctrl_t *fdctrl)
 {
     int i, j;
     static int command_tables_inited = 0;
@@ -1953,9 +1953,10 @@ static void fdctrl_init_common(fdctrl_t *fdctrl)
     fdctrl_external_reset(fdctrl);
     register_savevm("fdc", -1, 2, fdc_save, fdc_load, fdctrl);
     qemu_register_reset(fdctrl_external_reset, fdctrl);
+    return 0;
 }
 
-static void isabus_fdc_init1(ISADevice *dev)
+static int isabus_fdc_init1(ISADevice *dev)
 {
     fdctrl_isabus_t *isa = DO_UPCAST(fdctrl_isabus_t, busdev, dev);
     fdctrl_t *fdctrl = &isa->state;
@@ -1970,10 +1971,10 @@ static void isabus_fdc_init1(ISADevice *dev)
                           &fdctrl_write_port, fdctrl);
     isa_init_irq(&isa->busdev, &fdctrl->irq);
 
-    fdctrl_init_common(fdctrl);
+    return fdctrl_init_common(fdctrl);
 }
 
-static void sysbus_fdc_init1(SysBusDevice *dev)
+static int sysbus_fdc_init1(SysBusDevice *dev)
 {
     fdctrl_t *fdctrl = &(FROM_SYSBUS(fdctrl_sysbus_t, dev)->state);
     int io;
@@ -1983,10 +1984,10 @@ static void sysbus_fdc_init1(SysBusDevice *dev)
     sysbus_init_irq(dev, &fdctrl->irq);
     qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
 
-    fdctrl_init_common(fdctrl);
+    return fdctrl_init_common(fdctrl);
 }
 
-static void sun4m_fdc_init1(SysBusDevice *dev)
+static int sun4m_fdc_init1(SysBusDevice *dev)
 {
     fdctrl_t *fdctrl = &(FROM_SYSBUS(fdctrl_sysbus_t, dev)->state);
     int io;
@@ -1998,7 +1999,7 @@ static void sun4m_fdc_init1(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
 
     fdctrl->sun4m = 1;
-    fdctrl_init_common(fdctrl);
+    return fdctrl_init_common(fdctrl);
 }
 
 static ISADeviceInfo isa_fdc_info = {
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 5b6778e..38e2fe4 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -152,7 +152,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
     return d->host_state.bus;
 }
 
-static void pci_grackle_init_device(SysBusDevice *dev)
+static int pci_grackle_init_device(SysBusDevice *dev)
 {
     GrackleState *s;
     int pci_mem_config, pci_mem_data;
@@ -171,9 +171,10 @@ static void pci_grackle_init_device(SysBusDevice *dev)
                     &s->host_state);
     qemu_register_reset(pci_grackle_reset, &s->host_state);
     pci_grackle_reset(&s->host_state);
+    return 0;
 }
 
-static void pci_dec_21154_init_device(SysBusDevice *dev)
+static int pci_dec_21154_init_device(SysBusDevice *dev)
 {
     GrackleState *s;
     int pci_mem_config, pci_mem_data;
@@ -187,9 +188,10 @@ static void pci_dec_21154_init_device(SysBusDevice *dev)
                                           &s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+    return 0;
 }
 
-static void grackle_pci_host_init(PCIDevice *d)
+static int grackle_pci_host_init(PCIDevice *d)
 {
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_MOTOROLA);
     pci_config_set_device_id(d->config, PCI_DEVICE_ID_MOTOROLA_MPC106);
@@ -197,9 +199,10 @@ static void grackle_pci_host_init(PCIDevice *d)
     d->config[0x09] = 0x01;
     pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
     d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
+    return 0;
 }
 
-static void dec_21154_pci_host_init(PCIDevice *d)
+static int dec_21154_pci_host_init(PCIDevice *d)
 {
     /* PCI2PCI bridge same values as PearPC - check this */
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_DEC);
@@ -223,6 +226,7 @@ static void dec_21154_pci_host_init(PCIDevice *d)
     d->config[0x25] = 0x84;
     d->config[0x26] = 0x00; // prefetchable_memory_limit
     d->config[0x27] = 0x85;
+    return 0;
 }
 
 static PCIDeviceInfo grackle_pci_host_info = {
diff --git a/hw/i2c.c b/hw/i2c.c
index 7a1b358..5473772 100644
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -149,14 +149,14 @@ void i2c_slave_load(QEMUFile *f, i2c_slave *dev)
     }
 }
 
-static void i2c_slave_qdev_init(DeviceState *dev, DeviceInfo *base)
+static int i2c_slave_qdev_init(DeviceState *dev, DeviceInfo *base)
 {
     I2CSlaveInfo *info = container_of(base, I2CSlaveInfo, qdev);
     i2c_slave *s = I2C_SLAVE_FROM_QDEV(dev);
 
     s->info = info;
 
-    info->init(s);
+    return info->init(s);
 }
 
 void i2c_register_slave(I2CSlaveInfo *info)
diff --git a/hw/i2c.h b/hw/i2c.h
index 479ff4b..238f256 100644
--- a/hw/i2c.h
+++ b/hw/i2c.h
@@ -22,7 +22,7 @@ typedef int (*i2c_recv_cb)(i2c_slave *s);
 /* Notify the slave of a bus state change.  */
 typedef void (*i2c_event_cb)(i2c_slave *s, enum i2c_event event);
 
-typedef void (*i2c_slave_initfn)(i2c_slave *dev);
+typedef int (*i2c_slave_initfn)(i2c_slave *dev);
 
 typedef struct {
     DeviceInfo qdev;
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index e8b5194..21e7712 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -227,7 +227,7 @@ static CPUWriteMemoryFunc * const integratorcm_writefn[] = {
    integratorcm_write
 };
 
-static void integratorcm_init(SysBusDevice *dev)
+static int integratorcm_init(SysBusDevice *dev)
 {
     int iomemtype;
     integratorcm_state *s = FROM_SYSBUS(integratorcm_state, dev);
@@ -260,6 +260,7 @@ static void integratorcm_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, 0x00800000, iomemtype);
     integratorcm_do_remap(s, 1);
     /* ??? Save/restore.  */
+    return 0;
 }
 
 /* Integrator/CP hardware emulation.  */
@@ -372,7 +373,7 @@ static CPUWriteMemoryFunc * const icp_pic_writefn[] = {
    icp_pic_write
 };
 
-static void icp_pic_init(SysBusDevice *dev)
+static int icp_pic_init(SysBusDevice *dev)
 {
     icp_pic_state *s = FROM_SYSBUS(icp_pic_state, dev);
     int iomemtype;
@@ -383,6 +384,7 @@ static void icp_pic_init(SysBusDevice *dev)
     iomemtype = cpu_register_io_memory(icp_pic_readfn,
                                        icp_pic_writefn, s);
     sysbus_init_mmio(dev, 0x00800000, iomemtype);
+    return 0;
 }
 
 /* CP control registers.  */
diff --git a/hw/iommu.c b/hw/iommu.c
index ff8b415..e15cc91 100644
--- a/hw/iommu.c
+++ b/hw/iommu.c
@@ -366,7 +366,7 @@ static void iommu_reset(void *opaque)
     s->regs[IOMMU_MASK_ID] = IOMMU_TS_MASK;
 }
 
-static void iommu_init1(SysBusDevice *dev)
+static int iommu_init1(SysBusDevice *dev)
 {
     IOMMUState *s = FROM_SYSBUS(IOMMUState, dev);
     int io;
@@ -379,6 +379,7 @@ static void iommu_init1(SysBusDevice *dev)
     register_savevm("iommu", -1, 2, iommu_save, iommu_load, s);
     qemu_register_reset(iommu_reset, s);
     iommu_reset(s);
+    return 0;
 }
 
 static SysBusDeviceInfo iommu_info = {
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 315efbb..2f68b3a 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -60,12 +60,12 @@ void isa_init_irq(ISADevice *dev, qemu_irq *p)
     dev->nirqs++;
 }
 
-static void isa_qdev_init(DeviceState *qdev, DeviceInfo *base)
+static int isa_qdev_init(DeviceState *qdev, DeviceInfo *base)
 {
     ISADevice *dev = DO_UPCAST(ISADevice, qdev, qdev);
     ISADeviceInfo *info = DO_UPCAST(ISADeviceInfo, qdev, base);
 
-    info->init(dev);
+    return info->init(dev);
 }
 
 void isa_qdev_register(ISADeviceInfo *info)
diff --git a/hw/isa.h b/hw/isa.h
index 49c58f8..1ad93bf 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -17,7 +17,7 @@ struct ISADevice {
     int nirqs;
 };
 
-typedef void (*isa_qdev_initfn)(ISADevice *dev);
+typedef int (*isa_qdev_initfn)(ISADevice *dev);
 struct ISADeviceInfo {
     DeviceInfo qdev;
     isa_qdev_initfn init;
diff --git a/hw/lm832x.c b/hw/lm832x.c
index 197fe7d..32bfcb0 100644
--- a/hw/lm832x.c
+++ b/hw/lm832x.c
@@ -488,7 +488,7 @@ static int lm_kbd_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void lm8323_init(i2c_slave *i2c)
+static int lm8323_init(i2c_slave *i2c)
 {
     LM823KbdState *s = FROM_I2C_SLAVE(LM823KbdState, i2c);
 
@@ -502,6 +502,7 @@ static void lm8323_init(i2c_slave *i2c)
 
     qemu_register_reset((void *) lm_kbd_reset, s);
     register_savevm("LM8323", -1, 0, lm_kbd_save, lm_kbd_load, s);
+    return 0;
 }
 
 void lm832x_key_event(struct i2c_slave *i2c, int key, int state)
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index d41b8ba..b486558 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -2163,7 +2163,7 @@ static int lsi_scsi_uninit(PCIDevice *d)
     return 0;
 }
 
-static void lsi_scsi_init(PCIDevice *dev)
+static int lsi_scsi_init(PCIDevice *dev)
 {
     LSIState *s = (LSIState *)dev;
     uint8_t *pci_conf;
@@ -2205,6 +2205,7 @@ static void lsi_scsi_init(PCIDevice *dev)
     scsi_bus_new(&dev->qdev, lsi_scsi_attach);
 
     register_savevm("lsiscsi", -1, 0, lsi_scsi_save, lsi_scsi_load, s);
+    return 0;
 }
 
 static PCIDeviceInfo lsi_info = {
diff --git a/hw/m48t59.c b/hw/m48t59.c
index 3f2e3e5..0fcf4f8 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -642,7 +642,7 @@ m48t59_t *m48t59_init (qemu_irq IRQ, target_phys_addr_t mem_base,
     return d;
 }
 
-static void m48t59_init1(SysBusDevice *dev)
+static int m48t59_init1(SysBusDevice *dev)
 {
     m48t59_t *s = FROM_SYSBUS(m48t59_t, dev);
     int mem_index;
@@ -661,6 +661,7 @@ static void m48t59_init1(SysBusDevice *dev)
 
     qemu_register_reset(m48t59_reset, s);
     register_savevm("m48t59", -1, 1, m48t59_save, m48t59_load, s);
+    return 0;
 }
 
 static SysBusDeviceInfo m48t59_info = {
diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c
index d6be2e7..f198c4b 100644
--- a/hw/marvell_88w8618_audio.c
+++ b/hw/marvell_88w8618_audio.c
@@ -233,7 +233,7 @@ static CPUWriteMemoryFunc * const mv88w8618_audio_writefn[] = {
     mv88w8618_audio_write
 };
 
-static void mv88w8618_audio_init(SysBusDevice *dev)
+static int mv88w8618_audio_init(SysBusDevice *dev)
 {
     mv88w8618_audio_state *s = FROM_SYSBUS(mv88w8618_audio_state, dev);
     int iomemtype;
@@ -247,6 +247,7 @@ static void mv88w8618_audio_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, MP_AUDIO_SIZE, iomemtype);
 
     qemu_register_reset(mv88w8618_audio_reset, s);
+    return 0;
 }
 
 static SysBusDeviceInfo mv88w8618_audio_info = {
diff --git a/hw/max111x.c b/hw/max111x.c
index f7023a8..bd656bb 100644
--- a/hw/max111x.c
+++ b/hw/max111x.c
@@ -125,7 +125,7 @@ static int max111x_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void max111x_init(SSISlave *dev, int inputs)
+static int max111x_init(SSISlave *dev, int inputs)
 {
     MAX111xState *s = FROM_SSI_SLAVE(MAX111xState, dev);
 
@@ -144,16 +144,17 @@ static void max111x_init(SSISlave *dev, int inputs)
     s->com = 0;
 
     register_savevm("max111x", -1, 0, max111x_save, max111x_load, s);
+    return 0;
 }
 
-static void max1110_init(SSISlave *dev)
+static int max1110_init(SSISlave *dev)
 {
-    max111x_init(dev, 8);
+    return max111x_init(dev, 8);
 }
 
-static void max1111_init(SSISlave *dev)
+static int max1111_init(SSISlave *dev)
 {
-    max111x_init(dev, 4);
+    return max111x_init(dev, 4);
 }
 
 void max111x_set_input(DeviceState *dev, int line, uint8_t value)
diff --git a/hw/max7310.c b/hw/max7310.c
index a571e57..e737133 100644
--- a/hw/max7310.c
+++ b/hw/max7310.c
@@ -190,7 +190,7 @@ static void max7310_gpio_set(void *opaque, int line, int level)
 
 /* MAX7310 is SMBus-compatible (can be used with only SMBus protocols),
  * but also accepts sequences that are not SMBus so return an I2C device.  */
-static void max7310_init(i2c_slave *i2c)
+static int max7310_init(i2c_slave *i2c)
 {
     MAX7310State *s = FROM_I2C_SLAVE(MAX7310State, i2c);
 
@@ -200,6 +200,7 @@ static void max7310_init(i2c_slave *i2c)
     max7310_reset(&s->i2c);
 
     register_savevm("max7310", -1, 0, max7310_save, max7310_load, s);
+    return 0;
 }
 
 qemu_irq *max7310_gpio_in_get(i2c_slave *i2c)
diff --git a/hw/mpcore.c b/hw/mpcore.c
index f286d5f..46c2b9d 100644
--- a/hw/mpcore.c
+++ b/hw/mpcore.c
@@ -262,7 +262,7 @@ static void mpcore_priv_map(SysBusDevice *dev, target_phys_addr_t base)
     cpu_register_physical_memory(base + 0x1000, 0x1000, s->gic.iomemtype);
 }
 
-static void mpcore_priv_init(SysBusDevice *dev)
+static int mpcore_priv_init(SysBusDevice *dev)
 {
     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
     int i;
@@ -274,6 +274,7 @@ static void mpcore_priv_init(SysBusDevice *dev)
     for (i = 0; i < 8; i++) {
         mpcore_timer_init(s, &s->timer[i], i);
     }
+    return 0;
 }
 
 /* Dummy PIC to route IRQ lines.  The baseboard has 4 independent IRQ
@@ -309,7 +310,7 @@ static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
     }
 }
 
-static void realview_mpcore_init(SysBusDevice *dev)
+static int realview_mpcore_init(SysBusDevice *dev)
 {
     mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev);
     DeviceState *gic;
@@ -331,6 +332,7 @@ static void realview_mpcore_init(SysBusDevice *dev)
         }
     }
     qdev_init_gpio_in(&dev->qdev, mpcore_rirq_set_irq, 64);
+    return 0;
 }
 
 static void mpcore_register_devices(void)
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 097a1f7..238fd8a 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -365,7 +365,7 @@ static void eth_cleanup(VLANClientState *vc)
     qemu_free(s);
 }
 
-static void mv88w8618_eth_init(SysBusDevice *dev)
+static int mv88w8618_eth_init(SysBusDevice *dev)
 {
     mv88w8618_eth_state *s = FROM_SYSBUS(mv88w8618_eth_state, dev);
 
@@ -376,6 +376,7 @@ static void mv88w8618_eth_init(SysBusDevice *dev)
     s->mmio_index = cpu_register_io_memory(mv88w8618_eth_readfn,
                                            mv88w8618_eth_writefn, s);
     sysbus_init_mmio(dev, MP_ETH_SIZE, s->mmio_index);
+    return 0;
 }
 
 /* LCD register offsets */
@@ -544,7 +545,7 @@ static CPUWriteMemoryFunc * const musicpal_lcd_writefn[] = {
     musicpal_lcd_write
 };
 
-static void musicpal_lcd_init(SysBusDevice *dev)
+static int musicpal_lcd_init(SysBusDevice *dev)
 {
     musicpal_lcd_state *s = FROM_SYSBUS(musicpal_lcd_state, dev);
     int iomemtype;
@@ -560,6 +561,7 @@ static void musicpal_lcd_init(SysBusDevice *dev)
     qemu_console_resize(s->ds, 128*3, 64*3);
 
     qdev_init_gpio_in(&dev->qdev, musicpal_lcd_gpio_brigthness_in, 3);
+    return 0;
 }
 
 /* PIC register offsets */
@@ -642,7 +644,7 @@ static CPUWriteMemoryFunc * const mv88w8618_pic_writefn[] = {
     mv88w8618_pic_write
 };
 
-static void mv88w8618_pic_init(SysBusDevice *dev)
+static int mv88w8618_pic_init(SysBusDevice *dev)
 {
     mv88w8618_pic_state *s = FROM_SYSBUS(mv88w8618_pic_state, dev);
     int iomemtype;
@@ -654,6 +656,7 @@ static void mv88w8618_pic_init(SysBusDevice *dev)
     sysbus_init_mmio(dev, MP_PIC_SIZE, iomemtype);
 
     qemu_register_reset(mv88w8618_pic_reset, s);
+    return 0;
 }
 
 /* PIT register offsets */
@@ -761,7 +764,7 @@ static CPUWriteMemoryFunc * const mv88w8618_pit_writefn[] = {
     mv88w8618_pit_write
 };
 
-static void mv88w8618_pit_init(SysBusDevice *dev)
+static int mv88w8618_pit_init(SysBusDevice *dev)
 {
     int iomemtype;
     mv88w8618_pit_state *s = FROM_SYSBUS(mv88w8618_pit_state, dev);
@@ -776,6 +779,7 @@ static void mv88w8618_pit_init(SysBusDevice *dev)
     iomemtype = cpu_register_io_memory(mv88w8618_pit_readfn,
                                        mv88w8618_pit_writefn, s);
     sysbus_init_mmio(dev, MP_PIT_SIZE, iomemtype);
+    return 0;
 }
 
 /* Flash config register offsets */
@@ -824,7 +828,7 @@ static CPUWriteMemoryFunc * const mv88w8618_flashcfg_writefn[] = {
     mv88w8618_flashcfg_write
 };
 
-static void mv88w8618_flashcfg_init(SysBusDevice *dev)
+static int mv88w8618_flashcfg_init(SysBusDevice *dev)
 {
     int iomemtype;
     mv88w8618_flashcfg_state *s = FROM_SYSBUS(mv88w8618_flashcfg_state, dev);
@@ -833,6 +837,7 @@ static void mv88w8618_flashcfg_init(SysBusDevice *dev)
     iomemtype = cpu_register_io_memory(mv88w8618_flashcfg_readfn,
                        mv88w8618_flashcfg_writefn, s);
     sysbus_init_mmio(dev, MP_FLASHCFG_SIZE, iomemtype);
+    return 0;
 }
 
 /* Misc register offsets */
@@ -913,13 +918,14 @@ static CPUWriteMemoryFunc * const mv88w8618_wlan_writefn[] = {
     mv88w8618_wlan_write,
 };
 
-static void mv88w8618_wlan_init(SysBusDevice *dev)
+static int mv88w8618_wlan_init(SysBusDevice *dev)
 {
     int iomemtype;
 
     iomemtype = cpu_register_io_memory(mv88w8618_wlan_readfn,
                                        mv88w8618_wlan_writefn, NULL);
     sysbus_init_mmio(dev, MP_WLAN_SIZE, iomemtype);
+    return 0;
 }
 
 /* GPIO register offsets */
@@ -1120,7 +1126,7 @@ static void musicpal_gpio_reset(musicpal_gpio_state *s)
     s->isr = 0;
 }
 
-static void musicpal_gpio_init(SysBusDevice *dev)
+static int musicpal_gpio_init(SysBusDevice *dev)
 {
     musicpal_gpio_state *s = FROM_SYSBUS(musicpal_gpio_state, dev);
     int iomemtype;
@@ -1137,6 +1143,7 @@ static void musicpal_gpio_init(SysBusDevice *dev)
     qdev_init_gpio_out(&dev->qdev, s->out, 5);
     /* 10 gpio button input + 1 I2C data input */
     qdev_init_gpio_in(&dev->qdev, musicpal_gpio_irq, 11);
+    return 0;
 }
 
 /* Keyboard codes & masks */
@@ -1244,7 +1251,7 @@ static void musicpal_key_event(void *opaque, int keycode)
     s->kbd_extended = 0;
 }
 
-static void musicpal_key_init(SysBusDevice *dev)
+static int musicpal_key_init(SysBusDevice *dev)
 {
     musicpal_key_state *s = FROM_SYSBUS(musicpal_key_state, dev);
 
@@ -1257,6 +1264,7 @@ static void musicpal_key_init(SysBusDevice *dev)
     qdev_init_gpio_out(&dev->qdev, s->out, 10);
 
     qemu_add_kbd_event_handler(musicpal_key_event, s);
+    return 0;
 }
 
 static struct arm_boot_info musicpal_binfo = {
diff --git a/hw/ne2000.c b/hw/ne2000.c
index b9c018a..9f685b4 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -803,7 +803,7 @@ static void ne2000_cleanup(VLANClientState *vc)
     unregister_savevm("ne2000", s);
 }
 
-static void pci_ne2000_init(PCIDevice *pci_dev)
+static int pci_ne2000_init(PCIDevice *pci_dev)
 {
     PCINE2000State *d = (PCINE2000State *)pci_dev;
     NE2000State *s;
@@ -830,6 +830,7 @@ static void pci_ne2000_init(PCIDevice *pci_dev)
     qemu_format_nic_info_str(s->vc, s->macaddr);
 
     register_savevm("ne2000", -1, 3, ne2000_save, ne2000_load, s);
+    return 0;
 }
 
 static PCIDeviceInfo ne2000_info = {
diff --git a/hw/pci.c b/hw/pci.c
index 27eac04..73a7f6e 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -892,7 +892,7 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
     return s->bus;
 }
 
-static void pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
+static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
 {
     PCIDevice *pci_dev = (PCIDevice *)qdev;
     PCIDeviceInfo *info = container_of(base, PCIDeviceInfo, qdev);
@@ -904,7 +904,7 @@ static void pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
     pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
                                      info->config_read, info->config_write);
     assert(pci_dev);
-    info->init(pci_dev);
+    return info->init(pci_dev);
 }
 
 void pci_qdev_register(PCIDeviceInfo *info)
diff --git a/hw/pci.h b/hw/pci.h
index a2ec16a..87b4665 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -313,7 +313,7 @@ pci_config_set_class(uint8_t *pci_config, uint16_t val)
     pci_set_word(&pci_config[PCI_CLASS_DEVICE], val);
 }
 
-typedef void (*pci_qdev_initfn)(PCIDevice *dev);
+typedef int (*pci_qdev_initfn)(PCIDevice *dev);
 typedef struct {
     DeviceInfo qdev;
     pci_qdev_initfn init;
diff --git a/hw/pckbd.c b/hw/pckbd.c
index 6d97e33..3f83320 100644
--- a/hw/pckbd.c
+++ b/hw/pckbd.c
@@ -446,7 +446,7 @@ typedef struct ISAKBDState {
     KBDState  kbd;
 } ISAKBDState;
 
-static void i8042_initfn(ISADevice *dev)
+static int i8042_initfn(ISADevice *dev)
 {
     KBDState *s = &(DO_UPCAST(ISAKBDState, dev, dev)->kbd);
 
@@ -466,6 +466,7 @@ static void i8042_initfn(ISADevice *dev)
     vmmouse_init(s->mouse);
 #endif
     qemu_register_reset(kbd_reset, s);
+    return 0;
 }
 
 static ISADeviceInfo i8042_info = {
diff --git a/hw/pcnet.c b/hw/pcnet.c
index 827f6bd..107b5b6 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -1948,7 +1948,7 @@ static void pcnet_common_cleanup(PCNetState *d)
     qemu_free_timer(d->poll_timer);
 }
 
-static void pcnet_common_init(DeviceState *dev, PCNetState *s,
+static int pcnet_common_init(DeviceState *dev, PCNetState *s,
                               NetCleanup *cleanup)
 {
     s->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, s);
@@ -1959,6 +1959,7 @@ static void pcnet_common_init(DeviceState *dev, PCNetState *s,
                                  cleanup, s);
     pcnet_h_reset(s);
     register_savevm("pcnet", -1, 2, pcnet_save, pcnet_load, s);
+    return 0;
 }
 
 /* PCI interface */
@@ -2015,7 +2016,7 @@ static int pci_pcnet_uninit(PCIDevice *dev)
     return 0;
 }
 
-static void pci_pcnet_init(PCIDevice *pci_dev)
+static int pci_pcnet_init(PCIDevice *pci_dev)
 {
     PCIPCNetState *d = (PCIPCNetState *)pci_dev;
     PCNetState *s = &d->state;
@@ -2061,7 +2062,7 @@ static void pci_pcnet_init(PCIDevice *pci_dev)
     s->phys_mem_write = pci_physical_memory_write;
     s->pci_dev = pci_dev;
 
-    pcnet_common_init(&pci_dev->qdev, s, pci_pcnet_cleanup);
+    return pcnet_common_init(&pci_dev->qdev, s, pci_pcnet_cleanup);
 }
 
 /* SPARC32 interface */
@@ -2120,7 +2121,7 @@ static void lance_cleanup(VLANClientState *vc)
     pcnet_common_cleanup(d);
 }
 
-static void lance_init(SysBusDevice *dev)
+static int lance_init(SysBusDevice *dev)
 {
     SysBusPCNetState *d = FROM_SYSBUS(SysBusPCNetState, dev);
     PCNetState *s = &d->state;
@@ -2137,7 +2138,7 @@ static void lance_init(SysBusDevice *dev)
     s->phys_mem_read = ledma_memory_read;
     s->phys_mem_write = ledma_memory_write;
 
-    pcnet_common_init(&dev->qdev, s, lance_cleanup);
+    return pcnet_common_init(&dev->qdev, s, lance_cleanup);
 }
 
 static SysBusDeviceInfo lance_info = {
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index e2ddf4b..c9fef92 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -171,7 +171,7 @@ static int i440fx_load(QEMUFile* f, void *opaque, int version_id)
     return 0;
 }
 
-static void i440fx_pcihost_initfn(SysBusDevice *dev)
+static int i440fx_pcihost_initfn(SysBusDevice *dev)
 {
     I440FXState *s = FROM_SYSBUS(I440FXState, dev);
 
@@ -184,9 +184,10 @@ static void i440fx_pcihost_initfn(SysBusDevice *dev)
     register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
     register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
     register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
+    return 0;
 }
 
-static void i440fx_initfn(PCIDevice *d)
+static int i440fx_initfn(PCIDevice *d)
 {
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_INTEL);
     pci_config_set_device_id(d->config, PCI_DEVICE_ID_INTEL_82441);
@@ -197,6 +198,7 @@ static void i440fx_initfn(PCIDevice *d)
     d->config[0x72] = 0x02; /* SMRAM */
 
     register_savevm("I440FX", 0, 2, i440fx_save, i440fx_load, d);
+    return 0;
 }
 
 PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic)
@@ -339,7 +341,7 @@ static int piix_load(QEMUFile* f, void *opaque, int version_id)
     return pci_device_load(d, f);
 }
 
-static void piix3_initfn(PCIDevice *d)
+static int piix3_initfn(PCIDevice *d)
 {
     uint8_t *pci_conf;
 
@@ -356,9 +358,10 @@ static void piix3_initfn(PCIDevice *d)
     piix3_dev = d;
     piix3_reset(d);
     qemu_register_reset(piix3_reset, d);
+    return 0;
 }
 
-static void piix4_initfn(PCIDevice *d)
+static int piix4_initfn(PCIDevice *d)
 {
     uint8_t *pci_conf;
 
@@ -374,6 +377,7 @@ static void piix4_initfn(PCIDevice *d)
     piix4_dev = d;
     piix4_reset(d);
     qemu_register_reset(piix4_reset, d);
+    return 0;
 }
 
 int piix3_init(PCIBus *bus, int devfn)
diff --git a/hw/pl011.c b/hw/pl011.c
index 08a55ac..81de91e 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -286,7 +286,7 @@ static int pl011_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void pl011_init(SysBusDevice *dev, const unsigned char *id)
+static int pl011_init(SysBusDevice *dev, const unsigned char *id)
 {
     int iomemtype;
     pl011_state *s = FROM_SYSBUS(pl011_state, dev);
@@ -307,16 +307,17 @@ static void pl011_init(SysBusDevice *dev, const unsigned char *id)
                               pl011_event, s);
     }
     register_savevm("pl011_uart", -1, 1, pl011_save, pl011_load, s);
+    return 0;
 }
 
-static void pl011_init_arm(SysBusDevice *dev)
+static int pl011_init_arm(SysBusDevice *dev)
 {
-    pl011_init(dev, pl011_id_arm);
+    return pl011_init(dev, pl011_id_arm);
 }
 
-static void pl011_init_luminary(SysBusDevice *dev)
+static int pl011_init_luminary(SysBusDevice *dev)
 {
-    pl011_init(dev, pl011_id_luminary);
+    return pl011_init(dev, pl011_id_luminary);
 }
 
 static void pl011_register_devices(void)
diff --git a/hw/pl022.c b/hw/pl022.c
index 62e22d0..c2e2dda 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -288,7 +288,7 @@ static int pl022_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void pl022_init(SysBusDevice *dev)
+static int pl022_init(SysBusDevice *dev)
 {
     pl022_state *s = FROM_SYSBUS(pl022_state, dev);
     int iomemtype;
@@ -300,6 +300,7 @@ static void pl022_init(SysBusDevice *dev)
     s->ssi = ssi_create_bus(&dev->qdev, "ssi");
     pl022_reset(s);
     register_savevm("pl022_ssp", -1, 1, pl022_save, pl022_load, s);
+    return 0;
 }
 
 static void pl022_register_devices(void)
diff --git a/hw/pl031.c b/hw/pl031.c
index 671491f..19577dd 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -183,7 +183,7 @@ static CPUReadMemoryFunc * const  pl031_readfn[] = {
     pl031_read
 };
 
-static void pl031_init(SysBusDevice *dev)
+static int pl031_init(SysBusDevice *dev)
 {
     int iomemtype;
     pl031_state *s = FROM_SYSBUS(pl031_state, dev);
@@ -202,6 +202,7 @@ static void pl031_init(SysBusDevice *dev)
     s->tick_offset = mktimegm(&tm);
 
     s->timer = qemu_new_timer(vm_clock, pl031_interrupt, s);
+    return 0;
 }
 
 static void pl031_register_devices(void)
diff --git a/hw/pl050.c b/hw/pl050.c
index 011edf2..a47786c 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -122,7 +122,7 @@ static CPUWriteMemoryFunc * const pl050_writefn[] = {
    pl050_write
 };
 
-static void pl050_init(SysBusDevice *dev, int is_mouse)
+static int pl050_init(SysBusDevice *dev, int is_mouse)
 {
     pl050_state *s = FROM_SYSBUS(pl050_state, dev);
     int iomemtype;
@@ -137,16 +137,17 @@ static void pl050_init(SysBusDevice *dev, int is_mouse)
     else
         s->dev = ps2_kbd_init(pl050_update, s);
     /* ??? Save/restore.  */
+    return 0;
 }
 
-static void pl050_init_keyboard(SysBusDevice *dev)
+static int pl050_init_keyboard(SysBusDevice *dev)
 {
-    pl050_init(dev, 0);
+    return pl050_init(dev, 0);
 }
 
-static void pl050_init_mouse(SysBusDevice *dev)
+static int pl050_init_mouse(SysBusDevice *dev)
 {
-    pl050_init(dev, 1);
+    return pl050_init(dev, 1);
 }
 
 static void pl050_register_devices(void)
diff --git a/hw/pl061.c b/hw/pl061.c
index 2f31517..7b1b636 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -291,7 +291,7 @@ static int pl061_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void pl061_init(SysBusDevice *dev)
+static int pl061_init(SysBusDevice *dev)
 {
     int iomemtype;
     pl061_state *s = FROM_SYSBUS(pl061_state, dev);
@@ -304,6 +304,7 @@ static void pl061_init(SysBusDevice *dev)
     qdev_init_gpio_out(&dev->qdev, s->out, 8);
     pl061_reset(s);
     register_savevm("pl061_gpio", -1, 1, pl061_save, pl061_load, s);
+    return 0;
 }
 
 static void pl061_register_devices(void)
diff --git a/hw/pl080.c b/hw/pl080.c
index a6ea8eb..2df65fa 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -319,7 +319,7 @@ static CPUWriteMemoryFunc * const pl080_writefn[] = {
    pl080_write
 };
 
-static void pl08x_init(SysBusDevice *dev, int nchannels)
+static int pl08x_init(SysBusDevice *dev, int nchannels)
 {
     int iomemtype;
     pl080_state *s = FROM_SYSBUS(pl080_state, dev);
@@ -330,16 +330,17 @@ static void pl08x_init(SysBusDevice *dev, int nchannels)
     sysbus_init_irq(dev, &s->irq);
     s->nchannels = nchannels;
     /* ??? Save/restore.  */
+    return 0;
 }
 
-static void pl080_init(SysBusDevice *dev)
+static int pl080_init(SysBusDevice *dev)
 {
-    pl08x_init(dev, 8);
+    return pl08x_init(dev, 8);
 }
 
-static void pl081_init(SysBusDevice *dev)
+static int pl081_init(SysBusDevice *dev)
 {
-    pl08x_init(dev, 2);
+    return pl08x_init(dev, 2);
 }
 
 /* The PL080 and PL081 are the same except for the number of channels
diff --git a/hw/pl110.c b/hw/pl110.c
index 9b5724b..173458a 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -352,7 +352,7 @@ static CPUWriteMemoryFunc * const pl110_writefn[] = {
    pl110_write
 };
 
-static void pl110_init(SysBusDevice *dev)
+static int pl110_init(SysBusDevice *dev)
 {
     pl110_state *s = FROM_SYSBUS(pl110_state, dev);
     int iomemtype;
@@ -365,13 +365,14 @@ static void pl110_init(SysBusDevice *dev)
                                  pl110_invalidate_display,
                                  NULL, NULL, s);
     /* ??? Save/restore.  */
+    return 0;
 }
 
-static void pl110_versatile_init(SysBusDevice *dev)
+static int pl110_versatile_init(SysBusDevice *dev)
 {
     pl110_state *s = FROM_SYSBUS(pl110_state, dev);
     s->versatile = 1;
-    pl110_init(dev);
+    return pl110_init(dev);
 }
 
 static void pl110_register_devices(void)
diff --git a/hw/pl181.c b/hw/pl181.c
index 955e5ec..7282053 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -445,7 +445,7 @@ static void pl181_reset(void *opaque)
     s->mask[1] = 0;
 }
 
-static void pl181_init(SysBusDevice *dev)
+static int pl181_init(SysBusDevice *dev)
 {
     int iomemtype;
     pl181_state *s = FROM_SYSBUS(pl181_state, dev);
@@ -461,6 +461,7 @@ static void pl181_init(SysBusDevice *dev)
     qemu_register_reset(pl181_reset, s);
     pl181_reset(s);
     /* ??? Save/restore.  */
+    return 0;
 }
 
 static void pl181_register_devices(void)
diff --git a/hw/pl190.c b/hw/pl190.c
index da5b4b3..a4bc9c1 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -227,7 +227,7 @@ static void pl190_reset(pl190_state *s)
   pl190_update_vectors(s);
 }
 
-static void pl190_init(SysBusDevice *dev)
+static int pl190_init(SysBusDevice *dev)
 {
     pl190_state *s = FROM_SYSBUS(pl190_state, dev);
     int iomemtype;
@@ -240,6 +240,7 @@ static void pl190_init(SysBusDevice *dev)
     sysbus_init_irq(dev, &s->fiq);
     pl190_reset(s);
     /* ??? Save/restore.  */
+    return 0;
 }
 
 static void pl190_register_devices(void)
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 5546ee2..e38a125 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -850,7 +850,7 @@ static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void pxa2xx_ssp_init(SysBusDevice *dev)
+static int pxa2xx_ssp_init(SysBusDevice *dev)
 {
     int iomemtype;
     PXA2xxSSPState *s = FROM_SYSBUS(PXA2xxSSPState, dev);
@@ -864,6 +864,7 @@ static void pxa2xx_ssp_init(SysBusDevice *dev)
                     pxa2xx_ssp_save, pxa2xx_ssp_load, s);
 
     s->bus = ssi_create_bus(&dev->qdev, "ssi");
+    return 0;
 }
 
 /* Real-Time Clock */
@@ -1479,9 +1480,10 @@ static int pxa2xx_i2c_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void pxa2xx_i2c_slave_init(i2c_slave *i2c)
+static int pxa2xx_i2c_slave_init(i2c_slave *i2c)
 {
     /* Nothing to do.  */
+    return 0;
 }
 
 static I2CSlaveInfo pxa2xx_i2c_slave_info = {
diff --git a/hw/qdev.c b/hw/qdev.c
index c1a7779..1b7d963 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -199,16 +199,19 @@ DeviceState *qdev_device_add(QemuOpts *opts)
         qdev_free(qdev);
         return NULL;
     }
-    qdev_init(qdev);
+    if (qdev_init(qdev) != 0) {
+        qdev_free(qdev);
+        return NULL;
+    }
     return qdev;
 }
 
 /* Initialize a device.  Device properties should be set before calling
    this function.  IRQs and MMIO regions should be connected/mapped after
    calling this function.  */
-void qdev_init(DeviceState *dev)
+int qdev_init(DeviceState *dev)
 {
-    dev->info->init(dev, dev->info);
+    return dev->info->init(dev, dev->info);
 }
 
 /* Unlink device from bus and free the structure.  */
diff --git a/hw/qdev.h b/hw/qdev.h
index 204c4e5..cefb681 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -88,7 +88,7 @@ struct CompatProperty {
 
 DeviceState *qdev_create(BusState *bus, const char *name);
 DeviceState *qdev_device_add(QemuOpts *opts);
-void qdev_init(DeviceState *dev);
+int qdev_init(DeviceState *dev);
 void qdev_free(DeviceState *dev);
 
 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
@@ -98,7 +98,7 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
 
 /*** Device API.  ***/
 
-typedef void (*qdev_initfn)(DeviceState *dev, DeviceInfo *info);
+typedef int (*qdev_initfn)(DeviceState *dev, DeviceInfo *info);
 typedef void (*SCSIAttachFn)(DeviceState *host, BlockDriverState *bdrv,
               int unit);
 
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 3dd6ae7..bd02b09 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -58,7 +58,7 @@ static void realview_gic_map(SysBusDevice *dev, target_phys_addr_t base)
     cpu_register_physical_memory(base + 0x1000, 0x1000, s->gic.iomemtype);
 }
 
-static void realview_gic_init(SysBusDevice *dev)
+static int realview_gic_init(SysBusDevice *dev)
 {
     RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
 
@@ -66,6 +66,7 @@ static void realview_gic_init(SysBusDevice *dev)
     s->iomemtype = cpu_register_io_memory(realview_gic_cpu_readfn,
                                           realview_gic_cpu_writefn, s);
     sysbus_init_mmio_cb(dev, 0x2000, realview_gic_map);
+    return 0;
 }
 
 static void realview_gic_register_devices(void)
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 8e15743..b9dfa30 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -3445,7 +3445,7 @@ static int pci_rtl8139_uninit(PCIDevice *dev)
     return 0;
 }
 
-static void pci_rtl8139_init(PCIDevice *dev)
+static int pci_rtl8139_init(PCIDevice *dev)
 {
     PCIRTL8139State *d = (PCIRTL8139State *)dev;
     RTL8139State *s;
@@ -3497,6 +3497,7 @@ static void pci_rtl8139_init(PCIDevice *dev)
     qemu_mod_timer(s->timer,
         rtl8139_get_next_tctr_time(s,qemu_get_clock(vm_clock)));
 #endif /* RTL8139_ONBOARD_TIMER */
+    return 0;
 }
 
 static PCIDeviceInfo rtl8139_info = {
diff --git a/hw/sbi.c b/hw/sbi.c
index e6ced8b..bad9afd 100644
--- a/hw/sbi.c
+++ b/hw/sbi.c
@@ -131,7 +131,7 @@ static void sbi_reset(void *opaque)
     }
 }
 
-static void sbi_init1(SysBusDevice *dev)
+static int sbi_init1(SysBusDevice *dev)
 {
     SBIState *s = FROM_SYSBUS(SBIState, dev);
     int sbi_io_memory;
@@ -148,6 +148,7 @@ static void sbi_init1(SysBusDevice *dev)
     register_savevm("sbi", -1, 1, sbi_save, sbi_load, s);
     qemu_register_reset(sbi_reset, s);
     sbi_reset(s);
+    return 0;
 }
 
 static SysBusDeviceInfo sbi_info = {
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index 6961cb0..b81ad57 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -420,7 +420,7 @@ static void slavio_intctl_reset(void *opaque)
     slavio_check_interrupts(s, 0);
 }
 
-static void slavio_intctl_init1(SysBusDevice *dev)
+static int slavio_intctl_init1(SysBusDevice *dev)
 {
     SLAVIO_INTCTLState *s = FROM_SYSBUS(SLAVIO_INTCTLState, dev);
     int io_memory;
@@ -446,6 +446,7 @@ static void slavio_intctl_init1(SysBusDevice *dev)
                     slavio_intctl_load, s);
     qemu_register_reset(slavio_intctl_reset, s);
     slavio_intctl_reset(s);
+    return 0;
 }
 
 static SysBusDeviceInfo slavio_intctl_info = {
diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index 4c9337c..a25d678 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -434,7 +434,7 @@ static int slavio_misc_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void apc_init1(SysBusDevice *dev)
+static int apc_init1(SysBusDevice *dev)
 {
     APCState *s = FROM_SYSBUS(APCState, dev);
     int io;
@@ -444,9 +444,10 @@ static void apc_init1(SysBusDevice *dev)
     /* Power management (APC) XXX: not a Slavio device */
     io = cpu_register_io_memory(apc_mem_read, apc_mem_write, s);
     sysbus_init_mmio(dev, MISC_SIZE, io);
+    return 0;
 }
 
-static void slavio_misc_init1(SysBusDevice *dev)
+static int slavio_misc_init1(SysBusDevice *dev)
 {
     MiscState *s = FROM_SYSBUS(MiscState, dev);
     int io;
@@ -498,6 +499,7 @@ static void slavio_misc_init1(SysBusDevice *dev)
                     s);
     qemu_register_reset(slavio_misc_reset, s);
     slavio_misc_reset(s);
+    return 0;
 }
 
 static SysBusDeviceInfo slavio_misc_info = {
diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c
index 08302e0..f3af4e4 100644
--- a/hw/slavio_timer.c
+++ b/hw/slavio_timer.c
@@ -412,7 +412,7 @@ static void slavio_timer_reset(void *opaque)
     s->cputimer_mode = 0;
 }
 
-static void slavio_timer_init1(SysBusDevice *dev)
+static int slavio_timer_init1(SysBusDevice *dev)
 {
     int io;
     SLAVIO_TIMERState *s = FROM_SYSBUS(SLAVIO_TIMERState, dev);
@@ -444,6 +444,7 @@ static void slavio_timer_init1(SysBusDevice *dev)
                     slavio_timer_load, s);
     qemu_register_reset(slavio_timer_reset, s);
     slavio_timer_reset(s);
+    return 0;
 }
 
 static SysBusDeviceInfo slavio_timer_info = {
diff --git a/hw/smbus.c b/hw/smbus.c
index 5618902..6c1149b 100644
--- a/hw/smbus.c
+++ b/hw/smbus.c
@@ -198,12 +198,12 @@ static int smbus_i2c_send(i2c_slave *s, uint8_t data)
     return 0;
 }
 
-static void smbus_device_init(i2c_slave *i2c)
+static int smbus_device_init(i2c_slave *i2c)
 {
     SMBusDeviceInfo *t = container_of(i2c->info, SMBusDeviceInfo, i2c);
     SMBusDevice *dev = FROM_I2C_SLAVE(SMBusDevice, i2c);
 
-    t->init(dev);
+    return t->init(dev);
 }
 
 void smbus_register_device(SMBusDeviceInfo *info)
diff --git a/hw/smbus.h b/hw/smbus.h
index d8c8059..d582e6d 100644
--- a/hw/smbus.h
+++ b/hw/smbus.h
@@ -37,7 +37,7 @@ struct SMBusDevice {
 
 typedef struct {
     I2CSlaveInfo i2c;
-    void (*init)(SMBusDevice *dev);
+    int (*init)(SMBusDevice *dev);
     void (*quick_cmd)(SMBusDevice *dev, uint8_t read);
     void (*send_byte)(SMBusDevice *dev, uint8_t val);
     uint8_t (*receive_byte)(SMBusDevice *dev);
diff --git a/hw/smbus_eeprom.c b/hw/smbus_eeprom.c
index 9785cc2..52463e0 100644
--- a/hw/smbus_eeprom.c
+++ b/hw/smbus_eeprom.c
@@ -96,11 +96,12 @@ static uint8_t eeprom_read_data(SMBusDevice *dev, uint8_t cmd, int n)
     return eeprom_receive_byte(dev);
 }
 
-static void smbus_eeprom_init(SMBusDevice *dev)
+static int smbus_eeprom_init(SMBusDevice *dev)
 {
     SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *)dev;
 
     eeprom->offset = 0;
+    return 0;
 }
 
 static SMBusDeviceInfo smbus_eeprom_info = {
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index fd288d4..a08bdb0 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -700,7 +700,7 @@ static void smc91c111_cleanup(VLANClientState *vc)
     qemu_free(s);
 }
 
-static void smc91c111_init1(SysBusDevice *dev)
+static int smc91c111_init1(SysBusDevice *dev)
 {
     smc91c111_state *s = FROM_SYSBUS(smc91c111_state, dev);
 
@@ -717,6 +717,7 @@ static void smc91c111_init1(SysBusDevice *dev)
                                  smc91c111_cleanup, s);
     qemu_format_nic_info_str(s->vc, s->macaddr);
     /* ??? Save/restore.  */
+    return 0;
 }
 
 static void smc91c111_register_devices(void)
diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index 6b04d24..7f3150e 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -244,7 +244,7 @@ static int dma_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void sparc32_dma_init1(SysBusDevice *dev)
+static int sparc32_dma_init1(SysBusDevice *dev)
 {
     DMAState *s = FROM_SYSBUS(DMAState, dev);
     int dma_io_memory;
@@ -259,6 +259,7 @@ static void sparc32_dma_init1(SysBusDevice *dev)
 
     qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1);
     qdev_init_gpio_out(&dev->qdev, &s->dev_reset, 1);
+    return 0;
 }
 
 static SysBusDeviceInfo sparc32_dma_info = {
diff --git a/hw/spitz.c b/hw/spitz.c
index c1d629f..b9b59ef 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -604,7 +604,7 @@ static int spitz_lcdtg_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void spitz_lcdtg_init(SSISlave *dev)
+static int spitz_lcdtg_init(SSISlave *dev)
 {
     SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
 
@@ -614,6 +614,7 @@ static void spitz_lcdtg_init(SSISlave *dev)
 
     register_savevm("spitz-lcdtg", -1, 1,
                     spitz_lcdtg_save, spitz_lcdtg_load, s);
+    return 0;
 }
 
 /* SSP devices */
@@ -697,7 +698,7 @@ static int spitz_ssp_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void corgi_ssp_init(SSISlave *dev)
+static int corgi_ssp_init(SSISlave *dev)
 {
     CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev);
 
@@ -707,6 +708,7 @@ static void corgi_ssp_init(SSISlave *dev)
     s->bus[2] = ssi_create_bus(&dev->qdev, "ssi2");
 
     register_savevm("spitz_ssp", -1, 1, spitz_ssp_save, spitz_ssp_load, s);
+    return 0;
 }
 
 static void spitz_ssp_attach(PXA2xxState *cpu)
diff --git a/hw/ssd0303.c b/hw/ssd0303.c
index 6872ef5..16aed58 100644
--- a/hw/ssd0303.c
+++ b/hw/ssd0303.c
@@ -304,7 +304,7 @@ static int ssd0303_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void ssd0303_init(i2c_slave *i2c)
+static int ssd0303_init(i2c_slave *i2c)
 {
     ssd0303_state *s = FROM_I2C_SLAVE(ssd0303_state, i2c);
 
@@ -313,6 +313,7 @@ static void ssd0303_init(i2c_slave *i2c)
                                  NULL, NULL, s);
     qemu_console_resize(s->ds, 96 * MAGNIFY, 16 * MAGNIFY);
     register_savevm("ssd0303_oled", -1, 1, ssd0303_save, ssd0303_load, s);
+    return 0;
 }
 
 static I2CSlaveInfo ssd0303_info = {
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index 319ab87..b632825 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -322,7 +322,7 @@ static int ssd0323_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void ssd0323_init(SSISlave *dev)
+static int ssd0323_init(SSISlave *dev)
 {
     ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev);
 
@@ -336,6 +336,7 @@ static void ssd0323_init(SSISlave *dev)
     qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1);
 
     register_savevm("ssd0323_oled", -1, 1, ssd0323_save, ssd0323_load, s);
+    return 0;
 }
 
 static SSISlaveInfo ssd0323_info = {
diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c
index 4e67f14..5e74e5d 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -229,7 +229,7 @@ static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void ssi_sd_init(SSISlave *dev)
+static int ssi_sd_init(SSISlave *dev)
 {
     ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, dev);
     BlockDriverState *bs;
@@ -238,6 +238,7 @@ static void ssi_sd_init(SSISlave *dev)
     bs = qdev_init_bdrv(&dev->qdev, IF_SD);
     s->sd = sd_init(bs, 1);
     register_savevm("ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
+    return 0;
 }
 
 static SSISlaveInfo ssi_sd_info = {
diff --git a/hw/ssi.c b/hw/ssi.c
index a5133be..54ad1a1 100644
--- a/hw/ssi.c
+++ b/hw/ssi.c
@@ -18,7 +18,7 @@ static struct BusInfo ssi_bus_info = {
     .size = sizeof(SSIBus),
 };
 
-static void ssi_slave_init(DeviceState *dev, DeviceInfo *base_info)
+static int ssi_slave_init(DeviceState *dev, DeviceInfo *base_info)
 {
     SSISlaveInfo *info = container_of(base_info, SSISlaveInfo, qdev);
     SSISlave *s = SSI_SLAVE_FROM_QDEV(dev);
@@ -31,7 +31,7 @@ static void ssi_slave_init(DeviceState *dev, DeviceInfo *base_info)
     }
 
     s->info = info;
-    info->init(s);
+    return info->init(s);
 }
 
 void ssi_register_slave(SSISlaveInfo *info)
diff --git a/hw/ssi.h b/hw/ssi.h
index 6ff71e9..24610a8 100644
--- a/hw/ssi.h
+++ b/hw/ssi.h
@@ -18,7 +18,7 @@ typedef struct SSISlave SSISlave;
 /* Slave devices.  */
 typedef struct {
     DeviceInfo qdev;
-    void (*init)(SSISlave *dev);
+    int (*init)(SSISlave *dev);
     uint32_t (*transfer)(SSISlave *dev, uint32_t val);
 } SSISlaveInfo;
 
diff --git a/hw/stellaris.c b/hw/stellaris.c
index aa923ef..0ea7652 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -339,7 +339,7 @@ static int gptm_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void stellaris_gptm_init(SysBusDevice *dev)
+static int stellaris_gptm_init(SysBusDevice *dev)
 {
     int iomemtype;
     gptm_state *s = FROM_SYSBUS(gptm_state, dev);
@@ -355,6 +355,7 @@ static void stellaris_gptm_init(SysBusDevice *dev)
     s->timer[0] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[0]);
     s->timer[1] = qemu_new_timer(vm_clock, gptm_tick, &s->opaque[1]);
     register_savevm("stellaris_gptm", -1, 1, gptm_save, gptm_load, s);
+    return 0;
 }
 
 
@@ -654,9 +655,9 @@ static int ssys_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void stellaris_sys_init(uint32_t base, qemu_irq irq,
-                               stellaris_board_info * board,
-                               uint8_t *macaddr)
+static int stellaris_sys_init(uint32_t base, qemu_irq irq,
+                              stellaris_board_info * board,
+                              uint8_t *macaddr)
 {
     int iomemtype;
     ssys_state *s;
@@ -673,6 +674,7 @@ static void stellaris_sys_init(uint32_t base, qemu_irq irq,
     cpu_register_physical_memory(base, 0x00001000, iomemtype);
     ssys_reset(s);
     register_savevm("stellaris_sys", -1, 1, ssys_save, ssys_load, s);
+    return 0;
 }
 
 
@@ -870,7 +872,7 @@ static int stellaris_i2c_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void stellaris_i2c_init(SysBusDevice * dev)
+static int stellaris_i2c_init(SysBusDevice * dev)
 {
     stellaris_i2c_state *s = FROM_SYSBUS(stellaris_i2c_state, dev);
     i2c_bus *bus;
@@ -887,6 +889,7 @@ static void stellaris_i2c_init(SysBusDevice * dev)
     stellaris_i2c_reset(s);
     register_savevm("stellaris_i2c", -1, 1,
                     stellaris_i2c_save, stellaris_i2c_load, s);
+    return 0;
 }
 
 /* Analogue to Digital Converter.  This is only partially implemented,
@@ -1178,7 +1181,7 @@ static int stellaris_adc_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void stellaris_adc_init(SysBusDevice *dev)
+static int stellaris_adc_init(SysBusDevice *dev)
 {
     stellaris_adc_state *s = FROM_SYSBUS(stellaris_adc_state, dev);
     int iomemtype;
@@ -1195,6 +1198,7 @@ static void stellaris_adc_init(SysBusDevice *dev)
     qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
     register_savevm("stellaris_adc", -1, 1,
                     stellaris_adc_save, stellaris_adc_load, s);
+    return 0;
 }
 
 /* Some boards have both an OLED controller and SD card connected to
@@ -1244,7 +1248,7 @@ static int stellaris_ssi_bus_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void stellaris_ssi_bus_init(SSISlave *dev)
+static int stellaris_ssi_bus_init(SSISlave *dev)
 {
     stellaris_ssi_bus_state *s = FROM_SSI_SLAVE(stellaris_ssi_bus_state, dev);
 
@@ -1254,6 +1258,7 @@ static void stellaris_ssi_bus_init(SSISlave *dev)
 
     register_savevm("stellaris_ssi_bus", -1, 1,
                     stellaris_ssi_bus_save, stellaris_ssi_bus_load, s);
+    return 0;
 }
 
 /* Board init.  */
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index ae0f099..4596a69 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -396,7 +396,7 @@ static void stellaris_enet_cleanup(VLANClientState *vc)
     qemu_free(s);
 }
 
-static void stellaris_enet_init(SysBusDevice *dev)
+static int stellaris_enet_init(SysBusDevice *dev)
 {
     stellaris_enet_state *s = FROM_SYSBUS(stellaris_enet_state, dev);
 
@@ -415,6 +415,7 @@ static void stellaris_enet_init(SysBusDevice *dev)
     stellaris_enet_reset(s);
     register_savevm("stellaris_enet", -1, 1,
                     stellaris_enet_save, stellaris_enet_load, s);
+    return 0;
 }
 
 static void stellaris_enet_register_devices(void)
diff --git a/hw/sun4c_intctl.c b/hw/sun4c_intctl.c
index 20c093c..a0d0e97 100644
--- a/hw/sun4c_intctl.c
+++ b/hw/sun4c_intctl.c
@@ -198,7 +198,7 @@ static void sun4c_intctl_reset(void *opaque)
     s->pending = 0;
 }
 
-static void sun4c_intctl_init1(SysBusDevice *dev)
+static int sun4c_intctl_init1(SysBusDevice *dev)
 {
     Sun4c_INTCTLState *s = FROM_SYSBUS(Sun4c_INTCTLState, dev);
     int io_memory;
@@ -216,6 +216,7 @@ static void sun4c_intctl_init1(SysBusDevice *dev)
                     sun4c_intctl_load, s);
     qemu_register_reset(sun4c_intctl_reset, s);
     sun4c_intctl_reset(s);
+    return 0;
 }
 
 static SysBusDeviceInfo sun4c_intctl_info = {
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 17854db..d970723 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -566,12 +566,13 @@ static void idreg_init(target_phys_addr_t addr)
     cpu_physical_memory_write_rom(addr, idreg_data, sizeof(idreg_data));
 }
 
-static void idreg_init1(SysBusDevice *dev)
+static int idreg_init1(SysBusDevice *dev)
 {
     ram_addr_t idreg_offset;
 
     idreg_offset = qemu_ram_alloc(sizeof(idreg_data));
     sysbus_init_mmio(dev, sizeof(idreg_data), idreg_offset | IO_MEM_ROM);
+    return 0;
 }
 
 static SysBusDeviceInfo idreg_info = {
@@ -621,12 +622,13 @@ static void prom_init(target_phys_addr_t addr, const char *bios_name)
     }
 }
 
-static void prom_init1(SysBusDevice *dev)
+static int prom_init1(SysBusDevice *dev)
 {
     ram_addr_t prom_offset;
 
     prom_offset = qemu_ram_alloc(PROM_SIZE_MAX);
     sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM);
+    return 0;
 }
 
 static SysBusDeviceInfo prom_info = {
@@ -652,7 +654,7 @@ typedef struct RamDevice
 } RamDevice;
 
 /* System RAM */
-static void ram_init1(SysBusDevice *dev)
+static int ram_init1(SysBusDevice *dev)
 {
     ram_addr_t RAM_size, ram_offset;
     RamDevice *d = FROM_SYSBUS(RamDevice, dev);
@@ -661,6 +663,7 @@ static void ram_init1(SysBusDevice *dev)
 
     ram_offset = qemu_ram_alloc(RAM_size);
     sysbus_init_mmio(dev, RAM_size, ram_offset);
+    return 0;
 }
 
 static void ram_init(target_phys_addr_t addr, ram_addr_t RAM_size,
diff --git a/hw/sun4u.c b/hw/sun4u.c
index bc83255..7a7ec4b 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -358,7 +358,7 @@ pci_ebus_init(PCIBus *bus, int devfn)
     pci_create_simple(bus, devfn, "ebus");
 }
 
-static void
+static int
 pci_ebus_init1(PCIDevice *s)
 {
     isa_bus_new(&s->qdev);
@@ -379,6 +379,7 @@ pci_ebus_init1(PCIDevice *s)
                            ebus_mmio_mapfunc);
     pci_register_bar(s, 1, 0x800000,  PCI_ADDRESS_SPACE_MEM,
                            ebus_mmio_mapfunc);
+    return 0;
 }
 
 static PCIDeviceInfo ebus_info = {
@@ -428,12 +429,13 @@ static void prom_init(target_phys_addr_t addr, const char *bios_name)
     }
 }
 
-static void prom_init1(SysBusDevice *dev)
+static int prom_init1(SysBusDevice *dev)
 {
     ram_addr_t prom_offset;
 
     prom_offset = qemu_ram_alloc(PROM_SIZE_MAX);
     sysbus_init_mmio(dev, PROM_SIZE_MAX, prom_offset | IO_MEM_ROM);
+    return 0;
 }
 
 static SysBusDeviceInfo prom_info = {
@@ -460,7 +462,7 @@ typedef struct RamDevice
 } RamDevice;
 
 /* System RAM */
-static void ram_init1(SysBusDevice *dev)
+static int ram_init1(SysBusDevice *dev)
 {
     ram_addr_t RAM_size, ram_offset;
     RamDevice *d = FROM_SYSBUS(RamDevice, dev);
@@ -469,6 +471,7 @@ static void ram_init1(SysBusDevice *dev)
 
     ram_offset = qemu_ram_alloc(RAM_size);
     sysbus_init_mmio(dev, RAM_size, ram_offset);
+    return 0;
 }
 
 static void ram_init(target_phys_addr_t addr, ram_addr_t RAM_size)
diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c
index 11d90bf..7be04a3 100644
--- a/hw/syborg_fb.c
+++ b/hw/syborg_fb.c
@@ -503,7 +503,7 @@ static int syborg_fb_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void syborg_fb_init(SysBusDevice *dev)
+static int syborg_fb_init(SysBusDevice *dev)
 {
     SyborgFBState *s = FROM_SYSBUS(SyborgFBState, dev);
     int iomemtype;
@@ -528,6 +528,7 @@ static void syborg_fb_init(SysBusDevice *dev)
 
     register_savevm("syborg_framebuffer", -1, 1,
                     syborg_fb_save, syborg_fb_load, s);
+    return 0;
 }
 
 static SysBusDeviceInfo syborg_fb_info = {
diff --git a/hw/syborg_interrupt.c b/hw/syborg_interrupt.c
index ae202c6..f3a1767 100644
--- a/hw/syborg_interrupt.c
+++ b/hw/syborg_interrupt.c
@@ -202,7 +202,7 @@ static int syborg_int_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void syborg_int_init(SysBusDevice *dev)
+static int syborg_int_init(SysBusDevice *dev)
 {
     SyborgIntState *s = FROM_SYSBUS(SyborgIntState, dev);
     int iomemtype;
@@ -215,6 +215,7 @@ static void syborg_int_init(SysBusDevice *dev)
     s->flags = qemu_mallocz(s->num_irqs * sizeof(syborg_int_flags));
 
     register_savevm("syborg_int", -1, 1, syborg_int_save, syborg_int_load, s);
+    return 0;
 }
 
 static SysBusDeviceInfo syborg_int_info = {
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index 96f35ce..4a562f8 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -203,7 +203,7 @@ static int syborg_keyboard_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void syborg_keyboard_init(SysBusDevice *dev)
+static int syborg_keyboard_init(SysBusDevice *dev)
 {
     SyborgKeyboardState *s = FROM_SYSBUS(SyborgKeyboardState, dev);
     int iomemtype;
@@ -222,6 +222,7 @@ static void syborg_keyboard_init(SysBusDevice *dev)
 
     register_savevm("syborg_keyboard", -1, 1,
                     syborg_keyboard_save, syborg_keyboard_load, s);
+    return 0;
 }
 
 static SysBusDeviceInfo syborg_keyboard_info = {
diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
index 5bd44f4..563d730 100644
--- a/hw/syborg_pointer.c
+++ b/hw/syborg_pointer.c
@@ -199,7 +199,7 @@ static int syborg_pointer_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void syborg_pointer_init(SysBusDevice *dev)
+static int syborg_pointer_init(SysBusDevice *dev)
 {
     SyborgPointerState *s = FROM_SYSBUS(SyborgPointerState, dev);
     int iomemtype;
@@ -220,6 +220,7 @@ static void syborg_pointer_init(SysBusDevice *dev)
 
     register_savevm("syborg_pointer", -1, 1,
                     syborg_pointer_save, syborg_pointer_load, s);
+    return 0;
 }
 
 static SysBusDeviceInfo syborg_pointer_info = {
diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
index 5fa8653..b066213 100644
--- a/hw/syborg_rtc.c
+++ b/hw/syborg_rtc.c
@@ -123,7 +123,7 @@ static int syborg_rtc_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void syborg_rtc_init(SysBusDevice *dev)
+static int syborg_rtc_init(SysBusDevice *dev)
 {
     SyborgRTCState *s = FROM_SYSBUS(SyborgRTCState, dev);
     struct tm tm;
@@ -137,6 +137,7 @@ static void syborg_rtc_init(SysBusDevice *dev)
     s->offset = (uint64_t)mktime(&tm) * 1000000000;
 
     register_savevm("syborg_rtc", -1, 1, syborg_rtc_save, syborg_rtc_load, s);
+    return 0;
 }
 
 static void syborg_rtc_register_devices(void)
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index 63f0447..cac00ea 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -315,7 +315,7 @@ static int syborg_serial_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void syborg_serial_init(SysBusDevice *dev)
+static int syborg_serial_init(SysBusDevice *dev)
 {
     SyborgSerialState *s = FROM_SYSBUS(SyborgSerialState, dev);
     int iomemtype;
@@ -337,6 +337,7 @@ static void syborg_serial_init(SysBusDevice *dev)
 
     register_savevm("syborg_serial", -1, 1,
                     syborg_serial_save, syborg_serial_load, s);
+    return 0;
 }
 
 static SysBusDeviceInfo syborg_serial_info = {
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index 7477a17..3e4a447 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -203,7 +203,7 @@ static int syborg_timer_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void syborg_timer_init(SysBusDevice *dev)
+static int syborg_timer_init(SysBusDevice *dev)
 {
     SyborgTimerState *s = FROM_SYSBUS(SyborgTimerState, dev);
     QEMUBH *bh;
@@ -223,6 +223,7 @@ static void syborg_timer_init(SysBusDevice *dev)
     ptimer_set_freq(s->timer, s->freq);
     register_savevm("syborg_timer", -1, 1,
                     syborg_timer_save, syborg_timer_load, s);
+    return 0;
 }
 
 static SysBusDeviceInfo syborg_timer_info = {
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index fc45b35..c1faf3d 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -245,7 +245,7 @@ static VirtIOBindings syborg_virtio_bindings = {
     .notify = syborg_virtio_update_irq
 };
 
-static void syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
+static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
 {
     int iomemtype;
 
@@ -263,17 +263,18 @@ static void syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
     qemu_register_reset(virtio_reset, vdev);
 
     virtio_bind_device(vdev, &syborg_virtio_bindings, proxy);
+    return 0;
 }
 
 /* Device specific bindings.  */
 
-static void syborg_virtio_net_init(SysBusDevice *dev)
+static int syborg_virtio_net_init(SysBusDevice *dev)
 {
     VirtIODevice *vdev;
     SyborgVirtIOProxy *proxy = FROM_SYSBUS(SyborgVirtIOProxy, dev);
 
     vdev = virtio_net_init(&dev->qdev);
-    syborg_virtio_init(proxy, vdev);
+    return syborg_virtio_init(proxy, vdev);
 }
 
 static void syborg_virtio_register_devices(void)
diff --git a/hw/sysbus.c b/hw/sysbus.c
index 269be77..f6516fd 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -105,11 +105,11 @@ void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
     dev->mmio[n].cb = cb;
 }
 
-static void sysbus_device_init(DeviceState *dev, DeviceInfo *base)
+static int sysbus_device_init(DeviceState *dev, DeviceInfo *base)
 {
     SysBusDeviceInfo *info = container_of(base, SysBusDeviceInfo, qdev);
 
-    info->init(sysbus_from_qdev(dev));
+    return info->init(sysbus_from_qdev(dev));
 }
 
 void sysbus_register_withprop(SysBusDeviceInfo *info)
diff --git a/hw/sysbus.h b/hw/sysbus.h
index d48ca8c..1a8f289 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -25,7 +25,7 @@ struct SysBusDevice {
     } mmio[QDEV_MAX_MMIO];
 };
 
-typedef void (*sysbus_initfn)(SysBusDevice *dev);
+typedef int (*sysbus_initfn)(SysBusDevice *dev);
 
 /* Macros to compensate for lack of type inheritance in C.  */
 #define sysbus_from_qdev(dev) ((SysBusDevice *)(dev))
diff --git a/hw/tcx.c b/hw/tcx.c
index 754751c..cb32070 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -515,7 +515,7 @@ static CPUWriteMemoryFunc * const tcx_dummy_write[3] = {
     tcx_dummy_writel,
 };
 
-static void tcx_init1(SysBusDevice *dev)
+static int tcx_init1(SysBusDevice *dev)
 {
     TCXState *s = FROM_SYSBUS(TCXState, dev);
     int io_memory, dummy_memory;
@@ -576,6 +576,7 @@ static void tcx_init1(SysBusDevice *dev)
     qemu_register_reset(tcx_reset, s);
     tcx_reset(s);
     qemu_console_resize(s->ds, s->width, s->height);
+    return 0;
 }
 
 static void tcx_screen_dump(void *opaque, const char *filename)
diff --git a/hw/tmp105.c b/hw/tmp105.c
index c9756c5..0113f8d 100644
--- a/hw/tmp105.c
+++ b/hw/tmp105.c
@@ -226,7 +226,7 @@ static void tmp105_reset(i2c_slave *i2c)
     tmp105_interrupt_update(s);
 }
 
-static void tmp105_init(i2c_slave *i2c)
+static int tmp105_init(i2c_slave *i2c)
 {
     TMP105State *s = FROM_I2C_SLAVE(TMP105State, i2c);
 
@@ -235,6 +235,7 @@ static void tmp105_init(i2c_slave *i2c)
     tmp105_reset(&s->i2c);
 
     register_savevm("TMP105", -1, 0, tmp105_save, tmp105_load, s);
+    return 0;
 }
 
 static I2CSlaveInfo tmp105_info = {
diff --git a/hw/tosa.c b/hw/tosa.c
index b932efc..4c463e6 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -121,9 +121,10 @@ static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value)
     return 0;
 }
 
-static void tosa_ssp_init(SSISlave *dev)
+static int tosa_ssp_init(SSISlave *dev)
 {
     /* Nothing to do.  */
+    return 0;
 }
 
 typedef struct {
@@ -180,9 +181,10 @@ static int tosa_dac_recv(i2c_slave *s)
     return -1;
 }
 
-static void tosa_dac_init(i2c_slave *i2c)
+static int tosa_dac_init(i2c_slave *i2c)
 {
     /* Nothing to do.  */
+    return 0;
 }
 
 static void tosa_tg_init(PXA2xxState *cpu)
diff --git a/hw/twl92230.c b/hw/twl92230.c
index 519a583..b15a8bf 100644
--- a/hw/twl92230.c
+++ b/hw/twl92230.c
@@ -875,7 +875,7 @@ static int menelaus_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void twl92230_init(i2c_slave *i2c)
+static int twl92230_init(i2c_slave *i2c)
 {
     MenelausState *s = FROM_I2C_SLAVE(MenelausState, i2c);
 
@@ -888,6 +888,7 @@ static void twl92230_init(i2c_slave *i2c)
     menelaus_reset(&s->i2c);
 
     register_savevm("menelaus", -1, 0, menelaus_save, menelaus_load, s);
+    return 0;
 }
 
 static I2CSlaveInfo twl92230_info = {
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 908e046..9b5b8c8 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -167,7 +167,7 @@ static void pci_unin_reset(void *opaque)
 {
 }
 
-static void pci_unin_main_init_device(SysBusDevice *dev)
+static int pci_unin_main_init_device(SysBusDevice *dev)
 {
     UNINState *s;
     int pci_mem_config, pci_mem_data;
@@ -187,9 +187,10 @@ static void pci_unin_main_init_device(SysBusDevice *dev)
     register_savevm("uninorth", 0, 1, pci_unin_save, pci_unin_load, &s->host_state);
     qemu_register_reset(pci_unin_reset, &s->host_state);
     pci_unin_reset(&s->host_state);
+    return 0;
 }
 
-static void pci_dec_21154_init_device(SysBusDevice *dev)
+static int pci_dec_21154_init_device(SysBusDevice *dev)
 {
     UNINState *s;
     int pci_mem_config, pci_mem_data;
@@ -204,9 +205,10 @@ static void pci_dec_21154_init_device(SysBusDevice *dev)
                                           pci_unin_main_write, &s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+    return 0;
 }
 
-static void pci_unin_agp_init_device(SysBusDevice *dev)
+static int pci_unin_agp_init_device(SysBusDevice *dev)
 {
     UNINState *s;
     int pci_mem_config, pci_mem_data;
@@ -220,9 +222,10 @@ static void pci_unin_agp_init_device(SysBusDevice *dev)
                                           pci_unin_main_write, &s->host_state);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+    return 0;
 }
 
-static void pci_unin_internal_init_device(SysBusDevice *dev)
+static int pci_unin_internal_init_device(SysBusDevice *dev)
 {
     UNINState *s;
     int pci_mem_config, pci_mem_data;
@@ -236,6 +239,7 @@ static void pci_unin_internal_init_device(SysBusDevice *dev)
                                           pci_unin_write, s);
     sysbus_init_mmio(dev, 0x1000, pci_mem_config);
     sysbus_init_mmio(dev, 0x1000, pci_mem_data);
+    return 0;
 }
 
 PCIBus *pci_pmac_init(qemu_irq *pic)
@@ -277,7 +281,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
     return d->host_state.bus;
 }
 
-static void unin_main_pci_host_init(PCIDevice *d)
+static int unin_main_pci_host_init(PCIDevice *d)
 {
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
     pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_PCI);
@@ -287,9 +291,10 @@ static void unin_main_pci_host_init(PCIDevice *d)
     d->config[0x0D] = 0x10; // latency_timer
     d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
     d->config[0x34] = 0x00; // capabilities_pointer
+    return 0;
 }
 
-static void dec_21154_pci_host_init(PCIDevice *d)
+static int dec_21154_pci_host_init(PCIDevice *d)
 {
     /* pci-to-pci bridge */
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_DEC);
@@ -315,9 +320,10 @@ static void dec_21154_pci_host_init(PCIDevice *d)
     d->config[0x26] = 0xF1; // prefectchable_memory_limit
     d->config[0x27] = 0x7F;
     // d->config[0x34] = 0xdc // capabilities_pointer
+    return 0;
 }
 
-static void unin_agp_pci_host_init(PCIDevice *d)
+static int unin_agp_pci_host_init(PCIDevice *d)
 {
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
     pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_AGP);
@@ -327,9 +333,10 @@ static void unin_agp_pci_host_init(PCIDevice *d)
     d->config[0x0D] = 0x10; // latency_timer
     d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
     //    d->config[0x34] = 0x80; // capabilities_pointer
+    return 0;
 }
 
-static void unin_internal_pci_host_init(PCIDevice *d)
+static int unin_internal_pci_host_init(PCIDevice *d)
 {
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
     pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_I_PCI);
@@ -339,6 +346,7 @@ static void unin_internal_pci_host_init(PCIDevice *d)
     d->config[0x0D] = 0x10; // latency_timer
     d->config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
     d->config[0x34] = 0x00; // capabilities_pointer
+    return 0;
 }
 
 static PCIDeviceInfo unin_main_pci_host_info = {
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index e36b10f..6f9151c 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -109,7 +109,7 @@ static void pci_vpb_map(SysBusDevice *dev, target_phys_addr_t base)
     }
 }
 
-static void pci_vpb_init(SysBusDevice *dev)
+static int pci_vpb_init(SysBusDevice *dev)
 {
     PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev);
     PCIBus *bus;
@@ -129,16 +129,17 @@ static void pci_vpb_init(SysBusDevice *dev)
     sysbus_init_mmio_cb(dev, 0x04000000, pci_vpb_map);
 
     pci_create_simple(bus, -1, "versatile_pci_host");
+    return 0;
 }
 
-static void pci_realview_init(SysBusDevice *dev)
+static int pci_realview_init(SysBusDevice *dev)
 {
     PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev);
     s->realview = 1;
-    pci_vpb_init(dev);
+    return pci_vpb_init(dev);
 }
 
-static void versatile_pci_host_init(PCIDevice *d)
+static int versatile_pci_host_init(PCIDevice *d)
 {
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_XILINX);
     /* Both boards have the same device ID.  Oh well.  */
@@ -151,6 +152,7 @@ static void versatile_pci_host_init(PCIDevice *d)
     d->config[0x09] = 0x00; // programming i/f
     pci_config_set_class(d->config, PCI_CLASS_PROCESSOR_CO);
     d->config[0x0D] = 0x10; // latency_timer
+    return 0;
 }
 
 static PCIDeviceInfo versatile_pci_host_info = {
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 27e43d4..4c01720 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -129,7 +129,7 @@ static CPUWriteMemoryFunc * const vpb_sic_writefn[] = {
    vpb_sic_write
 };
 
-static void vpb_sic_init(SysBusDevice *dev)
+static int vpb_sic_init(SysBusDevice *dev)
 {
     vpb_sic_state *s = FROM_SYSBUS(vpb_sic_state, dev);
     int iomemtype;
@@ -144,6 +144,7 @@ static void vpb_sic_init(SysBusDevice *dev)
                                        vpb_sic_writefn, s);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     /* ??? Save/restore.  */
+    return 0;
 }
 
 /* Board init.  */
diff --git a/hw/vga.c b/hw/vga.c
index 791d8f5..98891ff 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2482,7 +2482,7 @@ static void pci_vga_write_config(PCIDevice *d,
         s->map_addr = 0;
 }
 
-static void pci_vga_initfn(PCIDevice *dev)
+static int pci_vga_initfn(PCIDevice *dev)
 {
      PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
      VGAState *s = &d->vga_state;
@@ -2513,7 +2513,8 @@ static void pci_vga_initfn(PCIDevice *dev)
             bios_total_size <<= 1;
         pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size,
                          PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
-    }
+     }
+     return 0;
 }
 
 int pci_vga_init(PCIBus *bus,
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index e95700a..50765d1 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -424,7 +424,7 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
     virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
 }
 
-static void virtio_blk_init_pci(PCIDevice *pci_dev)
+static int virtio_blk_init_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
     VirtIODevice *vdev;
@@ -435,6 +435,7 @@ static void virtio_blk_init_pci(PCIDevice *pci_dev)
 
     if (!proxy->dinfo) {
         fprintf(stderr, "drive property not set\n");
+        return -1;
     }
     vdev = virtio_blk_init(&pci_dev->qdev, proxy->dinfo);
     vdev->nvectors = proxy->nvectors;
@@ -444,9 +445,10 @@ static void virtio_blk_init_pci(PCIDevice *pci_dev)
                     proxy->class_code, 0x00);
     /* make the actual value visible */
     proxy->nvectors = vdev->nvectors;
+    return 0;
 }
 
-static void virtio_console_init_pci(PCIDevice *pci_dev)
+static int virtio_console_init_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
     VirtIODevice *vdev;
@@ -461,9 +463,10 @@ static void virtio_console_init_pci(PCIDevice *pci_dev)
                     PCI_VENDOR_ID_REDHAT_QUMRANET,
                     PCI_DEVICE_ID_VIRTIO_CONSOLE,
                     proxy->class_code, 0x00);
+    return 0;
 }
 
-static void virtio_net_init_pci(PCIDevice *pci_dev)
+static int virtio_net_init_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
     VirtIODevice *vdev;
@@ -484,9 +487,10 @@ static void virtio_net_init_pci(PCIDevice *pci_dev)
 
     /* make the actual value visible */
     proxy->nvectors = vdev->nvectors;
+    return 0;
 }
 
-static void virtio_balloon_init_pci(PCIDevice *pci_dev)
+static int virtio_balloon_init_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
     VirtIODevice *vdev;
@@ -497,6 +501,7 @@ static void virtio_balloon_init_pci(PCIDevice *pci_dev)
                     PCI_DEVICE_ID_VIRTIO_BALLOON,
                     PCI_CLASS_MEMORY_RAM,
                     0x00);
+    return 0;
 }
 
 static PCIDeviceInfo virtio_info[] = {
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index a856059..a6c6dc6 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1210,7 +1210,7 @@ static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
                     iomemtype);
 }
 
-static void pci_vmsvga_initfn(PCIDevice *dev)
+static int pci_vmsvga_initfn(PCIDevice *dev)
 {
     struct pci_vmsvga_state_s *s =
         DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
@@ -1236,6 +1236,7 @@ static void pci_vmsvga_initfn(PCIDevice *dev)
     vmsvga_init(&s->chip, VGA_RAM_SIZE);
 
     register_savevm("vmware_vga", 0, 0, pci_vmsvga_save, pci_vmsvga_load, s);
+    return 0;
 }
 
 void pci_vmsvga_init(PCIBus *bus)
diff --git a/hw/wm8750.c b/hw/wm8750.c
index 0c0dbba..f55eae7 100644
--- a/hw/wm8750.c
+++ b/hw/wm8750.c
@@ -645,7 +645,7 @@ static int wm8750_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void wm8750_init(i2c_slave *i2c)
+static int wm8750_init(i2c_slave *i2c)
 {
     WM8750State *s = FROM_I2C_SLAVE(WM8750State, i2c);
 
@@ -653,6 +653,7 @@ static void wm8750_init(i2c_slave *i2c)
     wm8750_reset(&s->i2c);
 
     register_savevm(CODEC, -1, 0, wm8750_save, wm8750_load, s);
+    return 0;
 }
 
 #if 0
diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c
index 851b5ae..9b0074c 100644
--- a/hw/xilinx_ethlite.c
+++ b/hw/xilinx_ethlite.c
@@ -207,7 +207,7 @@ static void eth_cleanup(VLANClientState *vc)
     qemu_free(s);
 }
 
-static void xilinx_ethlite_init(SysBusDevice *dev)
+static int xilinx_ethlite_init(SysBusDevice *dev)
 {
     struct xlx_ethlite *s = FROM_SYSBUS(typeof (*s), dev);
     int regs;
@@ -221,6 +221,7 @@ static void xilinx_ethlite_init(SysBusDevice *dev)
     qdev_get_macaddr(&dev->qdev, s->macaddr);
     s->vc = qdev_get_vlan_client(&dev->qdev,
                                  eth_can_rx, eth_rx, NULL, eth_cleanup, s);
+    return 0;
 }
 
 static SysBusDeviceInfo xilinx_ethlite_info = {
diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c
index 2ecf962..8ef6474 100644
--- a/hw/xilinx_intc.c
+++ b/hw/xilinx_intc.c
@@ -145,7 +145,7 @@ static void irq_handler(void *opaque, int irq, int level)
     update_irq(p);
 }
 
-static void xilinx_intc_init(SysBusDevice *dev)
+static int xilinx_intc_init(SysBusDevice *dev)
 {
     struct xlx_pic *p = FROM_SYSBUS(typeof (*p), dev);
     int pic_regs;
@@ -155,6 +155,7 @@ static void xilinx_intc_init(SysBusDevice *dev)
 
     pic_regs = cpu_register_io_memory(pic_read, pic_write, p);
     sysbus_init_mmio(dev, R_MAX * 4, pic_regs);
+    return 0;
 }
 
 static SysBusDeviceInfo xilinx_intc_info = {
diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c
index 0c20889..e2d9541 100644
--- a/hw/xilinx_timer.c
+++ b/hw/xilinx_timer.c
@@ -189,7 +189,7 @@ static void timer_hit(void *opaque)
     timer_update_irq(t);
 }
 
-static void xilinx_timer_init(SysBusDevice *dev)
+static int xilinx_timer_init(SysBusDevice *dev)
 {
     struct timerblock *t = FROM_SYSBUS(typeof (*t), dev);
     unsigned int i;
@@ -212,6 +212,7 @@ static void xilinx_timer_init(SysBusDevice *dev)
 
     timer_regs = cpu_register_io_memory(timer_read, timer_write, t);
     sysbus_init_mmio(dev, R_MAX * 4 * t->nr_timers, timer_regs);
+    return 0;
 }
 
 static SysBusDeviceInfo xilinx_timer_info = {
diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
index 175f3ee..adab759 100644
--- a/hw/xilinx_uartlite.c
+++ b/hw/xilinx_uartlite.c
@@ -193,7 +193,7 @@ static void uart_event(void *opaque, int event)
 
 }
 
-static void xilinx_uartlite_init(SysBusDevice *dev)
+static int xilinx_uartlite_init(SysBusDevice *dev)
 {
     struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev);
     int uart_regs;
@@ -207,6 +207,7 @@ static void xilinx_uartlite_init(SysBusDevice *dev)
     s->chr = qdev_init_chardev(&dev->qdev);
     if (s->chr)
         qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+    return 0;
 }
 
 static void xilinx_uart_register(void)
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 2/4] add qemu_error() + friends
  2009-08-26 13:19 [Qemu-devel] [PATCH 0/4] qdev: init() callback retval + error reporting Gerd Hoffmann
  2009-08-26 13:19 ` [Qemu-devel] [PATCH 1/4] qdev: add return value to init() callbacks Gerd Hoffmann
@ 2009-08-26 13:19 ` Gerd Hoffmann
  2009-08-26 13:19 ` [Qemu-devel] [PATCH 3/4] virtio-pci error logging Gerd Hoffmann
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2009-08-26 13:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This patch adds some functions for error reporting to address the
problem that error messages should be routed to different destinations
depending on the context of the caller, i.e. monitor command errors
should go to the monitor, command line errors to stderr.

qemu_error() is a printf-like function to report errors.

qemu_errors_to_file() and qemu_errors_to_mon() switch the destination
for the error message to the specified file or monitor.  When setting a
new destination the old one will be kept.  One can switch back using
qemu_errors_to_previous().  i.e. it works like a stack.

main() calls qemu_errors_to_file(stderr), so errors go to stderr by
default.  monitor callbacks are wrapped into qemu_errors_to_mon() +
qemu_errors_to_previous(), so any errors triggered by monitor commands
will go to the monitor.

Each thread has its own error message destination.  qemu-kvm probably
should add a qemu_errors_to_file(stderr) call to the i/o-thread
initialization code.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 monitor.c |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 sysemu.h  |    5 ++++
 vl.c      |    1 +
 3 files changed, 76 insertions(+), 1 deletions(-)

diff --git a/monitor.c b/monitor.c
index 967171b..6f7c940 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2782,6 +2782,7 @@ static void monitor_handle_command(Monitor *mon, const char *cmdline)
         goto fail;
     }
 
+    qemu_errors_to_mon(mon);
     switch(nb_args) {
     case 0:
         handler_0 = cmd->handler;
@@ -2833,8 +2834,10 @@ static void monitor_handle_command(Monitor *mon, const char *cmdline)
         break;
     default:
         monitor_printf(mon, "unsupported number of arguments: %d\n", nb_args);
-        goto fail;
+        break;
     }
+    qemu_errors_to_previous();
+
  fail:
     for(i = 0; i < MAX_ARGS; i++)
         qemu_free(str_allocated[i]);
@@ -3202,3 +3205,69 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
     if (err && completion_cb)
         completion_cb(opaque, err);
 }
+
+typedef struct QemuErrorSink QemuErrorSink;
+struct QemuErrorSink {
+    enum {
+        ERR_SINK_FILE,
+        ERR_SINK_MONITOR,
+    } dest;
+    union {
+        FILE    *fp;
+        Monitor *mon;
+    };
+    QemuErrorSink *previous;
+};
+
+static __thread QemuErrorSink *qemu_error_sink;
+
+void qemu_errors_to_file(FILE *fp)
+{
+    QemuErrorSink *sink;
+
+    sink = qemu_mallocz(sizeof(*sink));
+    sink->dest = ERR_SINK_FILE;
+    sink->fp = fp;
+    sink->previous = qemu_error_sink;
+    qemu_error_sink = sink;
+}
+
+void qemu_errors_to_mon(Monitor *mon)
+{
+    QemuErrorSink *sink;
+
+    sink = qemu_mallocz(sizeof(*sink));
+    sink->dest = ERR_SINK_MONITOR;
+    sink->mon = mon;
+    sink->previous = qemu_error_sink;
+    qemu_error_sink = sink;
+}
+
+void qemu_errors_to_previous(void)
+{
+    QemuErrorSink *sink;
+
+    assert(qemu_error_sink != NULL);
+    sink = qemu_error_sink;
+    qemu_error_sink = sink->previous;
+    qemu_free(sink);
+}
+
+void qemu_error(const char *fmt, ...)
+{
+    va_list args;
+
+    assert(qemu_error_sink != NULL);
+    switch (qemu_error_sink->dest) {
+    case ERR_SINK_FILE:
+        va_start(args, fmt);
+        vfprintf(qemu_error_sink->fp, fmt, args);
+        va_end(args);
+        break;
+    case ERR_SINK_MONITOR:
+        va_start(args, fmt);
+        monitor_vprintf(qemu_error_sink->mon, fmt, args);
+        va_end(args);
+        break;
+    }
+}
diff --git a/sysemu.h b/sysemu.h
index 1df0872..eaf7f58 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -65,6 +65,11 @@ int qemu_savevm_state_complete(QEMUFile *f);
 int qemu_savevm_state(QEMUFile *f);
 int qemu_loadvm_state(QEMUFile *f);
 
+void qemu_errors_to_file(FILE *fp);
+void qemu_errors_to_mon(Monitor *mon);
+void qemu_errors_to_previous(void);
+void qemu_error(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
+
 #ifdef _WIN32
 /* Polling handling */
 
diff --git a/vl.c b/vl.c
index c164f45..7bbd273 100644
--- a/vl.c
+++ b/vl.c
@@ -4801,6 +4801,7 @@ int main(int argc, char **argv, char **envp)
     CPUState *env;
     int show_vnc_port = 0;
 
+    qemu_errors_to_file(stderr);
     qemu_cache_utils_init(envp);
 
     LIST_INIT (&vm_change_state_head);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 3/4] virtio-pci error logging
  2009-08-26 13:19 [Qemu-devel] [PATCH 0/4] qdev: init() callback retval + error reporting Gerd Hoffmann
  2009-08-26 13:19 ` [Qemu-devel] [PATCH 1/4] qdev: add return value to init() callbacks Gerd Hoffmann
  2009-08-26 13:19 ` [Qemu-devel] [PATCH 2/4] add qemu_error() + friends Gerd Hoffmann
@ 2009-08-26 13:19 ` Gerd Hoffmann
  2009-08-26 13:19 ` [Qemu-devel] [PATCH 4/4] qdev " Gerd Hoffmann
  2009-08-28  0:46 ` [Qemu-devel] [PATCH 0/4] qdev: init() callback retval + error reporting Anthony Liguori
  4 siblings, 0 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2009-08-26 13:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Use the new qemu_error() function for virtio-blk-pci.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/virtio-pci.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 50765d1..f812ab7 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -434,7 +434,7 @@ static int virtio_blk_init_pci(PCIDevice *pci_dev)
         proxy->class_code = PCI_CLASS_STORAGE_SCSI;
 
     if (!proxy->dinfo) {
-        fprintf(stderr, "drive property not set\n");
+        qemu_error("virtio-blk-pci: drive property not set\n");
         return -1;
     }
     vdev = virtio_blk_init(&pci_dev->qdev, proxy->dinfo);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [PATCH 4/4] qdev error logging
  2009-08-26 13:19 [Qemu-devel] [PATCH 0/4] qdev: init() callback retval + error reporting Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2009-08-26 13:19 ` [Qemu-devel] [PATCH 3/4] virtio-pci error logging Gerd Hoffmann
@ 2009-08-26 13:19 ` Gerd Hoffmann
  2009-08-28  0:46 ` [Qemu-devel] [PATCH 0/4] qdev: init() callback retval + error reporting Anthony Liguori
  4 siblings, 0 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2009-08-26 13:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Use the new qemu_error() function in qdev.c

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/qdev.c |   34 +++++++++++++++++-----------------
 1 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/hw/qdev.c b/hw/qdev.c
index 1b7d963..ff2f096 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -138,8 +138,8 @@ static int set_property(const char *name, const char *value, void *opaque)
         return 0;
 
     if (-1 == qdev_prop_parse(dev, name, value)) {
-        fprintf(stderr, "can't set property \"%s\" to \"%s\" for \"%s\"\n",
-                name, value, dev->info->name);
+        qemu_error("can't set property \"%s\" to \"%s\" for \"%s\"\n",
+                   name, value, dev->info->name);
         return -1;
     }
     return 0;
@@ -154,14 +154,14 @@ DeviceState *qdev_device_add(QemuOpts *opts)
 
     driver = qemu_opt_get(opts, "driver");
     if (!driver) {
-        fprintf(stderr, "-device: no driver specified\n");
+        qemu_error("-device: no driver specified\n");
         return NULL;
     }
     if (strcmp(driver, "?") == 0) {
         char msg[256];
         for (info = device_info_list; info != NULL; info = info->next) {
             qdev_print_devinfo(info, msg, sizeof(msg));
-            fprintf(stderr, "%s\n", msg);
+            qemu_error("%s\n", msg);
         }
         return NULL;
     }
@@ -169,13 +169,13 @@ DeviceState *qdev_device_add(QemuOpts *opts)
     /* find driver */
     info = qdev_find_info(NULL, driver);
     if (!info) {
-        fprintf(stderr, "Device \"%s\" not found.  Try -device '?' for a list.\n",
-                driver);
+        qemu_error("Device \"%s\" not found.  Try -device '?' for a list.\n",
+                   driver);
         return NULL;
     }
     if (info->no_user) {
-        fprintf(stderr, "device \"%s\" can't be added via command line\n",
-                info->name);
+        qemu_error("device \"%s\" can't be added via command line\n",
+                   info->name);
         return NULL;
     }
 
@@ -442,12 +442,12 @@ static BusState *qbus_find(const char *path)
         pos = 0;
     } else {
         if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
-            fprintf(stderr, "path parse error (\"%s\")\n", path);
+            qemu_error("path parse error (\"%s\")\n", path);
             return NULL;
         }
         bus = qbus_find_recursive(main_system_bus, elem, NULL);
         if (!bus) {
-            fprintf(stderr, "bus \"%s\" not found\n", elem);
+            qemu_error("bus \"%s\" not found\n", elem);
             return NULL;
         }
         pos = len;
@@ -461,14 +461,14 @@ static BusState *qbus_find(const char *path)
 
         /* find device */
         if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
-            fprintf(stderr, "path parse error (\"%s\" pos %d)\n", path, pos);
+            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
             return NULL;
         }
         pos += len;
         dev = qbus_find_dev(bus, elem);
         if (!dev) {
             qbus_list_dev(bus, msg, sizeof(msg));
-            fprintf(stderr, "device \"%s\" not found\n%s\n", elem, msg);
+            qemu_error("device \"%s\" not found\n%s\n", elem, msg);
             return NULL;
         }
         if (path[pos] == '\0') {
@@ -476,28 +476,28 @@ static BusState *qbus_find(const char *path)
              * one child bus accept it nevertheless */
             switch (dev->num_child_bus) {
             case 0:
-                fprintf(stderr, "device has no child bus (%s)\n", path);
+                qemu_error("device has no child bus (%s)\n", path);
                 return NULL;
             case 1:
                 return LIST_FIRST(&dev->child_bus);
             default:
                 qbus_list_bus(dev, msg, sizeof(msg));
-                fprintf(stderr, "device has multiple child busses (%s)\n%s\n",
-                        path, msg);
+                qemu_error("device has multiple child busses (%s)\n%s\n",
+                           path, msg);
                 return NULL;
             }
         }
 
         /* find bus */
         if (sscanf(path+pos, "/%127[^/]%n", elem, &len) != 1) {
-            fprintf(stderr, "path parse error (\"%s\" pos %d)\n", path, pos);
+            qemu_error("path parse error (\"%s\" pos %d)\n", path, pos);
             return NULL;
         }
         pos += len;
         bus = qbus_find_bus(dev, elem);
         if (!bus) {
             qbus_list_bus(dev, msg, sizeof(msg));
-            fprintf(stderr, "child bus \"%s\" not found\n%s\n", elem, msg);
+            qemu_error("child bus \"%s\" not found\n%s\n", elem, msg);
             return NULL;
         }
     }
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH 0/4] qdev: init() callback retval + error reporting
  2009-08-26 13:19 [Qemu-devel] [PATCH 0/4] qdev: init() callback retval + error reporting Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2009-08-26 13:19 ` [Qemu-devel] [PATCH 4/4] qdev " Gerd Hoffmann
@ 2009-08-28  0:46 ` Anthony Liguori
  4 siblings, 0 replies; 6+ messages in thread
From: Anthony Liguori @ 2009-08-28  0:46 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

Gerd Hoffmann wrote:
>   Hi,
>
> This is a respin of the qdev init callback patch series. 
> Rebased to master, fixed a few build failures.  No other changes.
>   

I've got this in staging and had already fixed the build issues.  Has 
taken me a while to review the patches from when I was out.

Regards,

Anthony Liguori

> cheers,
>   Gerd
>
>
>   

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2009-08-28  0:53 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-26 13:19 [Qemu-devel] [PATCH 0/4] qdev: init() callback retval + error reporting Gerd Hoffmann
2009-08-26 13:19 ` [Qemu-devel] [PATCH 1/4] qdev: add return value to init() callbacks Gerd Hoffmann
2009-08-26 13:19 ` [Qemu-devel] [PATCH 2/4] add qemu_error() + friends Gerd Hoffmann
2009-08-26 13:19 ` [Qemu-devel] [PATCH 3/4] virtio-pci error logging Gerd Hoffmann
2009-08-26 13:19 ` [Qemu-devel] [PATCH 4/4] qdev " Gerd Hoffmann
2009-08-28  0:46 ` [Qemu-devel] [PATCH 0/4] qdev: init() callback retval + error reporting Anthony Liguori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).