[Spice-commits] 34 commits - arch_init.c configure hw/Makefile.objs hw/a15mpcore.c hw/a9mpcore.c hw/acpi.c hw/apb_pci.c hw/arm11mpcore.c hw/arm_gic_common.c hw/arm_mptimer.c hw/arm_sysctl.c hw/armv7m.c hw/axis_dev88.c hw/cadence_gem.c hw/empty_slot.c hw/escc.c hw/esp.c hw/etraxfs.h hw/exynos4210.c hw/exynos4210_gic.c hw/exynos4210_uart.c hw/exynos4_boards.c hw/fw_cfg.c hw/grlib.h hw/grlib_irqmp.c hw/highbank.c hw/hpet.c hw/imx_serial.c hw/lan9118.c hw/lm32.h hw/m48t59.c hw/marvell_88w8618_audio.c hw/milkymist-hw.h hw/mips_jazz.c hw/mips_mipssim.c hw/mpc8544_guts.c hw/musicpal.c hw/nand.c hw/nseries.c hw/omap1.c hw/omap2.c hw/omap_gpio.c hw/omap_i2c.c hw/omap_intc.c hw/onenand.c hw/openpic.c hw/openrisc_sim.c hw/pc.c hw/petalogix_ml605_mmu.c hw/pflash_cfi01.c hw/pflash_cfi02.c hw/ppc hw/ppc_newworld.c hw/ppce500_spin.c hw/pxa2xx.c hw/pxa2xx_dma.c hw/pxa2xx_gpio.c hw/pxa2xx_pic.c hw/qdev-core.h hw/qdev-monitor.c hw/r2d.c hw/realview.c hw/realview_gic.c hw/s390-virtio-bus.c hw/s390-vir tio-bus.h hw/slavio_intctl.c hw/sm501.c hw/smc91c111.c hw/spapr_pci.c hw/spitz.c hw/stellaris.c hw/strongarm.c hw/sun4m.c hw/sun4u.c hw/sysbus.c hw/sysbus.h hw/tpci200.c hw/tusb6010.c hw/versatilepb.c hw/vexpress.c hw/virtio-bus.c hw/virtio-bus.h hw/virtio-pci.c hw/virtio-pci.h hw/virtio.c hw/virtio.h hw/xilinx.h hw/xilinx_zynq.c hw/xtensa_lx60.c hw/zynq_slcr.c include/migration include/sysemu migration.c pc-bios/acpi-dsdt.aml pc-bios/bios.bin pc-bios/q35-acpi-dsdt.aml qemu-options.hx roms/seabios savevm.c target-cris/cpu.h target-i386/cpu.c target-microblaze/cpu.h ui/Makefile.objs ui/vnc-ws.c ui/vnc-ws.h ui/vnc.c ui/vnc.h

Gerd Hoffmann kraxel at kemper.freedesktop.org
Tue Jan 22 02:01:44 PST 2013


 arch_init.c                   |    6 
 configure                     |   29 +++-
 hw/Makefile.objs              |    1 
 hw/a15mpcore.c                |    2 
 hw/a9mpcore.c                 |    6 
 hw/acpi.c                     |    2 
 hw/apb_pci.c                  |    2 
 hw/arm11mpcore.c              |    8 -
 hw/arm_gic_common.c           |    2 
 hw/arm_mptimer.c              |    2 
 hw/arm_sysctl.c               |    2 
 hw/armv7m.c                   |    6 
 hw/axis_dev88.c               |    2 
 hw/cadence_gem.c              |    2 
 hw/empty_slot.c               |    2 
 hw/escc.c                     |    4 
 hw/esp.c                      |    2 
 hw/etraxfs.h                  |    2 
 hw/exynos4210.c               |   14 +-
 hw/exynos4210_gic.c           |    2 
 hw/exynos4210_uart.c          |    2 
 hw/exynos4_boards.c           |    2 
 hw/fw_cfg.c                   |    2 
 hw/grlib.h                    |   10 -
 hw/grlib_irqmp.c              |    4 
 hw/highbank.c                 |   26 +--
 hw/hpet.c                     |    4 
 hw/imx_serial.c               |    2 
 hw/lan9118.c                  |    4 
 hw/lm32.h                     |    2 
 hw/m48t59.c                   |    2 
 hw/marvell_88w8618_audio.c    |    2 
 hw/milkymist-hw.h             |   52 +++----
 hw/mips_jazz.c                |    4 
 hw/mips_mipssim.c             |    2 
 hw/mpc8544_guts.c             |    2 
 hw/musicpal.c                 |   14 +-
 hw/nand.c                     |    2 
 hw/nseries.c                  |    6 
 hw/omap1.c                    |   10 -
 hw/omap2.c                    |    8 -
 hw/omap_gpio.c                |    4 
 hw/omap_i2c.c                 |    4 
 hw/omap_intc.c                |    2 
 hw/onenand.c                  |    4 
 hw/openpic.c                  |    2 
 hw/openrisc_sim.c             |    4 
 hw/pc.c                       |    4 
 hw/petalogix_ml605_mmu.c      |    2 
 hw/pflash_cfi01.c             |    2 
 hw/pflash_cfi02.c             |    2 
 hw/ppc/e500.c                 |    4 
 hw/ppc_newworld.c             |    2 
 hw/ppce500_spin.c             |    2 
 hw/pxa2xx.c                   |    2 
 hw/pxa2xx_dma.c               |    8 -
 hw/pxa2xx_gpio.c              |   10 -
 hw/pxa2xx_pic.c               |    6 
 hw/qdev-core.h                |    2 
 hw/qdev-monitor.c             |   12 +
 hw/r2d.c                      |    2 
 hw/realview.c                 |   10 -
 hw/realview_gic.c             |    2 
 hw/s390-virtio-bus.c          |   31 ++++
 hw/s390-virtio-bus.h          |   18 ++
 hw/slavio_intctl.c            |    4 
 hw/sm501.c                    |    4 
 hw/smc91c111.c                |    4 
 hw/spapr_pci.c                |    2 
 hw/spitz.c                    |    4 
 hw/stellaris.c                |    4 
 hw/strongarm.c                |    8 -
 hw/sun4m.c                    |   30 ++--
 hw/sun4u.c                    |    4 
 hw/sysbus.c                   |    8 -
 hw/sysbus.h                   |    1 
 hw/tpci200.c                  |    6 
 hw/tusb6010.c                 |    2 
 hw/versatilepb.c              |   10 -
 hw/vexpress.c                 |   10 -
 hw/virtio-bus.c               |  164 ++++++++++++++++++++++++
 hw/virtio-bus.h               |   94 +++++++++++++
 hw/virtio-pci.c               |  155 ++++++++++++++++++++++
 hw/virtio-pci.h               |   38 +++++
 hw/virtio.c                   |   70 ++++++++--
 hw/virtio.h                   |   30 ++++
 hw/xilinx.h                   |   22 +--
 hw/xilinx_zynq.c              |    8 -
 hw/xtensa_lx60.c              |    2 
 hw/zynq_slcr.c                |    2 
 include/migration/migration.h |    3 
 include/sysemu/sysemu.h       |    2 
 migration.c                   |  149 ++++++++++------------
 pc-bios/acpi-dsdt.aml         |binary
 pc-bios/bios.bin              |binary
 pc-bios/q35-acpi-dsdt.aml     |binary
 qemu-options.hx               |    8 +
 roms/seabios                  |    2 
 savevm.c                      |   12 +
 target-cris/cpu.h             |    1 
 target-i386/cpu.c             |    2 
 target-microblaze/cpu.h       |    1 
 ui/Makefile.objs              |    1 
 ui/vnc-ws.c                   |  284 ++++++++++++++++++++++++++++++++++++++++++
 ui/vnc-ws.h                   |   86 ++++++++++++
 ui/vnc.c                      |  211 +++++++++++++++++++++++++++----
 ui/vnc.h                      |   21 +++
 107 files changed, 1513 insertions(+), 357 deletions(-)

New commits:
commit 1356b98d3e95a85071e6bf9a99e8799e1ae1bbee
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Jan 20 02:47:33 2013 +0100

    sysbus: Drop sysbus_from_qdev() cast macro
    
    Replace by SYS_BUS_DEVICE() QOM cast macro using a scripted conversion.
    Avoids the old macro creeping into new code.
    
    Resolve a Coding Style warning in openpic code.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Cc: Anthony Liguori <anthony at codemonkey.ws>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/a15mpcore.c b/hw/a15mpcore.c
index 30983ef..fe6c34c 100644
--- a/hw/a15mpcore.c
+++ b/hw/a15mpcore.c
@@ -46,7 +46,7 @@ static int a15mp_priv_init(SysBusDevice *dev)
     qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
     qdev_prop_set_uint32(s->gic, "revision", 2);
     qdev_init_nofail(s->gic);
-    busdev = sysbus_from_qdev(s->gic);
+    busdev = SYS_BUS_DEVICE(s->gic);
 
     /* Pass through outbound IRQ lines from the GIC */
     sysbus_pass_irq(dev, busdev);
diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 184734f..673bbd8 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -112,7 +112,7 @@ static const MemoryRegionOps a9_scu_ops = {
 
 static void a9mp_priv_reset(DeviceState *dev)
 {
-    a9mp_priv_state *s = FROM_SYSBUS(a9mp_priv_state, sysbus_from_qdev(dev));
+    a9mp_priv_state *s = FROM_SYSBUS(a9mp_priv_state, SYS_BUS_DEVICE(dev));
     int i;
     s->scu_control = 0;
     for (i = 0; i < ARRAY_SIZE(s->old_timer_status); i++) {
@@ -136,7 +136,7 @@ static int a9mp_priv_init(SysBusDevice *dev)
     qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
     qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
     qdev_init_nofail(s->gic);
-    gicbusdev = sysbus_from_qdev(s->gic);
+    gicbusdev = SYS_BUS_DEVICE(s->gic);
 
     /* Pass through outbound IRQ lines from the GIC */
     sysbus_pass_irq(dev, gicbusdev);
@@ -147,7 +147,7 @@ static int a9mp_priv_init(SysBusDevice *dev)
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
-    busdev = sysbus_from_qdev(s->mptimer);
+    busdev = SYS_BUS_DEVICE(s->mptimer);
 
     /* Memory map (addresses are offsets from PERIPHBASE):
      *  0x0000-0x00ff -- Snoop Control Unit
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index b9a7ee6..7eb0c2b 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -365,7 +365,7 @@ PCIBus *pci_apb_init(hwaddr special_base,
     /* Ultrasparc PBM main bus */
     dev = qdev_create(NULL, "pbm");
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     /* apb_config */
     sysbus_mmio_map(s, 0, special_base);
     /* PCI configuration space */
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index 469f6bf..324e503 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -83,8 +83,8 @@ static void mpcore_priv_set_irq(void *opaque, int irq, int level)
 static void mpcore_priv_map_setup(mpcore_priv_state *s)
 {
     int i;
-    SysBusDevice *gicbusdev = sysbus_from_qdev(s->gic);
-    SysBusDevice *busdev = sysbus_from_qdev(s->mptimer);
+    SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic);
+    SysBusDevice *busdev = SYS_BUS_DEVICE(s->mptimer);
     memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
     memory_region_init_io(&s->iomem, &mpcore_scu_ops, s, "mpcore-scu", 0x100);
     memory_region_add_subregion(&s->container, 0, &s->iomem);
@@ -131,7 +131,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
     qdev_init_nofail(s->gic);
 
     /* Pass through outbound IRQ lines from the GIC */
-    sysbus_pass_irq(dev, sysbus_from_qdev(s->gic));
+    sysbus_pass_irq(dev, SYS_BUS_DEVICE(s->gic));
 
     /* Pass through inbound GPIO lines to the GIC */
     qdev_init_gpio_in(&s->busdev.qdev, mpcore_priv_set_irq, s->num_irq - 32);
@@ -190,7 +190,7 @@ static int realview_mpcore_init(SysBusDevice *dev)
     priv = qdev_create(NULL, "arm11mpcore_priv");
     qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
     qdev_init_nofail(priv);
-    s->priv = sysbus_from_qdev(priv);
+    s->priv = SYS_BUS_DEVICE(priv);
     sysbus_pass_irq(dev, s->priv);
     for (i = 0; i < 32; i++) {
         s->cpuic[i] = qdev_get_gpio_in(priv, i);
diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c
index 41799ad..40e8dd7 100644
--- a/hw/arm_gic_common.c
+++ b/hw/arm_gic_common.c
@@ -123,7 +123,7 @@ static int arm_gic_common_init(SysBusDevice *dev)
 
 static void arm_gic_common_reset(DeviceState *dev)
 {
-    GICState *s = FROM_SYSBUS(GICState, sysbus_from_qdev(dev));
+    GICState *s = FROM_SYSBUS(GICState, SYS_BUS_DEVICE(dev));
     int i;
     memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
     for (i = 0 ; i < s->num_cpu; i++) {
diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c
index cdfd623..32817d3 100644
--- a/hw/arm_mptimer.c
+++ b/hw/arm_mptimer.c
@@ -238,7 +238,7 @@ static void timerblock_reset(timerblock *tb)
 static void arm_mptimer_reset(DeviceState *dev)
 {
     arm_mptimer_state *s =
-        FROM_SYSBUS(arm_mptimer_state, sysbus_from_qdev(dev));
+        FROM_SYSBUS(arm_mptimer_state, SYS_BUS_DEVICE(dev));
     int i;
     /* We reset every timer in the array, not just the ones we're using,
      * because vmsave will look at every array element.
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index a196fcc..755a5df 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -75,7 +75,7 @@ static int board_id(arm_sysctl_state *s)
 
 static void arm_sysctl_reset(DeviceState *d)
 {
-    arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, sysbus_from_qdev(d));
+    arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, SYS_BUS_DEVICE(d));
 
     s->leds = 0;
     s->lockval = 0;
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 98fe483..904696c 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -137,12 +137,12 @@ static void armv7m_bitband_init(void)
     dev = qdev_create(NULL, "ARM,bitband-memory");
     qdev_prop_set_uint32(dev, "base", 0x20000000);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x22000000);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x22000000);
 
     dev = qdev_create(NULL, "ARM,bitband-memory");
     qdev_prop_set_uint32(dev, "base", 0x40000000);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x42000000);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x42000000);
 }
 
 /* Board init.  */
@@ -216,7 +216,7 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem,
     env->nvic = nvic;
     qdev_init_nofail(nvic);
     cpu_pic = arm_pic_init_cpu(cpu);
-    sysbus_connect_irq(sysbus_from_qdev(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
+    sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
     for (i = 0; i < 64; i++) {
         pic[i] = qdev_get_gpio_in(nvic, i);
     }
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 9418981..dd37fa1 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -300,7 +300,7 @@ void axisdev88_init(QEMUMachineInitArgs *args)
     /* FIXME: Is there a proper way to signal vectors to the CPU core?  */
     qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(s, 0, 0x3001c000);
     sysbus_connect_irq(s, 0, cpu_irq[0]);
     sysbus_connect_irq(s, 1, cpu_irq[1]);
diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c
index 2beee62..0d83442 100644
--- a/hw/cadence_gem.c
+++ b/hw/cadence_gem.c
@@ -959,7 +959,7 @@ static void gem_phy_reset(GemState *s)
 
 static void gem_reset(DeviceState *d)
 {
-    GemState *s = FROM_SYSBUS(GemState, sysbus_from_qdev(d));
+    GemState *s = FROM_SYSBUS(GemState, SYS_BUS_DEVICE(d));
 
     DB_PRINT("\n");
 
diff --git a/hw/empty_slot.c b/hw/empty_slot.c
index 3cb6ccb..d7b5497 100644
--- a/hw/empty_slot.c
+++ b/hw/empty_slot.c
@@ -56,7 +56,7 @@ void empty_slot_init(hwaddr addr, uint64_t slot_size)
         EmptySlot *e;
 
         dev = qdev_create(NULL, "empty_slot");
-        s = sysbus_from_qdev(dev);
+        s = SYS_BUS_DEVICE(dev);
         e = FROM_SYSBUS(EmptySlot, s);
         e->size = slot_size;
 
diff --git a/hw/escc.c b/hw/escc.c
index c81088b..18c0292 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -700,7 +700,7 @@ MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB,
     qdev_prop_set_uint32(dev, "chnBtype", ser);
     qdev_prop_set_uint32(dev, "chnAtype", ser);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_connect_irq(s, 0, irqB);
     sysbus_connect_irq(s, 1, irqA);
     if (base) {
@@ -861,7 +861,7 @@ void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq,
     qdev_prop_set_uint32(dev, "chnBtype", mouse);
     qdev_prop_set_uint32(dev, "chnAtype", kbd);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_connect_irq(s, 0, irq);
     sysbus_connect_irq(s, 1, irq);
     sysbus_mmio_map(s, 0, base);
diff --git a/hw/esp.c b/hw/esp.c
index 0e4e430..2af48aa 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -633,7 +633,7 @@ void esp_init(hwaddr espaddr, int it_shift,
     /* XXX for now until rc4030 has been changed to use DMA enable signal */
     esp->dma_enabled = 1;
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_connect_irq(s, 0, irq);
     sysbus_mmio_map(s, 0, espaddr);
     *reset = qdev_get_gpio_in(dev, 0);
diff --git a/hw/etraxfs.h b/hw/etraxfs.h
index cc1d7a1..180de5a 100644
--- a/hw/etraxfs.h
+++ b/hw/etraxfs.h
@@ -44,7 +44,7 @@ etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr,
     qdev_prop_set_ptr(dev, "dma_out", dma_out);
     qdev_prop_set_ptr(dev, "dma_in", dma_in);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
     return dev;
 }
 
diff --git a/hw/exynos4210.c b/hw/exynos4210.c
index 246a0fc..fa54e42 100644
--- a/hw/exynos4210.c
+++ b/hw/exynos4210.c
@@ -154,7 +154,7 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
         for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
             gate_irq[i][n] = qdev_get_gpio_in(dev, n);
         }
-        busdev = sysbus_from_qdev(dev);
+        busdev = SYS_BUS_DEVICE(dev);
 
         /* Connect IRQ Gate output to cpu_irq */
         sysbus_connect_irq(busdev, 0, cpu_irq[i]);
@@ -164,7 +164,7 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
     dev = qdev_create(NULL, "a9mpcore_priv");
     qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
     qdev_init_nofail(dev);
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
     for (n = 0; n < EXYNOS4210_NCPUS; n++) {
         sysbus_connect_irq(busdev, n, gate_irq[n][0]);
@@ -180,7 +180,7 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
     dev = qdev_create(NULL, "exynos4210.gic");
     qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
     qdev_init_nofail(dev);
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     /* Map CPU interface */
     sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
     /* Map Distributer interface */
@@ -195,7 +195,7 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
     /* Internal Interrupt Combiner */
     dev = qdev_create(NULL, "exynos4210.combiner");
     qdev_init_nofail(dev);
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
         sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
     }
@@ -206,7 +206,7 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
     dev = qdev_create(NULL, "exynos4210.combiner");
     qdev_prop_set_uint32(dev, "external", 1);
     qdev_init_nofail(dev);
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
         sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
     }
@@ -285,7 +285,7 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
     /* Multi Core Timer */
     dev = qdev_create(NULL, "exynos4210.mct");
     qdev_init_nofail(dev);
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     for (n = 0; n < 4; n++) {
         /* Connect global timer interrupts to Combiner gpio_in */
         sysbus_connect_irq(busdev, n,
@@ -311,7 +311,7 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
 
         dev = qdev_create(NULL, "exynos4210.i2c");
         qdev_init_nofail(dev);
-        busdev = sysbus_from_qdev(dev);
+        busdev = SYS_BUS_DEVICE(dev);
         sysbus_connect_irq(busdev, 0, i2c_irq);
         sysbus_mmio_map(busdev, 0, addr);
         s->i2c_if[n] = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
diff --git a/hw/exynos4210_gic.c b/hw/exynos4210_gic.c
index f67906e..94b138f 100644
--- a/hw/exynos4210_gic.c
+++ b/hw/exynos4210_gic.c
@@ -290,7 +290,7 @@ static int exynos4210_gic_init(SysBusDevice *dev)
     qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
     qdev_prop_set_uint32(s->gic, "num-irq", EXYNOS4210_GIC_NIRQ);
     qdev_init_nofail(s->gic);
-    busdev = sysbus_from_qdev(s->gic);
+    busdev = SYS_BUS_DEVICE(s->gic);
 
     /* Pass through outbound IRQ lines from the GIC */
     sysbus_pass_irq(dev, busdev);
diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c
index adaab24..bdf797a 100644
--- a/hw/exynos4210_uart.c
+++ b/hw/exynos4210_uart.c
@@ -615,7 +615,7 @@ DeviceState *exynos4210_uart_create(hwaddr addr,
     qdev_prop_set_uint32(dev, "rx-size", fifo_size);
     qdev_prop_set_uint32(dev, "tx-size", fifo_size);
 
-    bus = sysbus_from_qdev(dev);
+    bus = SYS_BUS_DEVICE(dev);
     qdev_init_nofail(dev);
     if (addr != (hwaddr)-1) {
         sysbus_mmio_map(bus, 0, addr);
diff --git a/hw/exynos4_boards.c b/hw/exynos4_boards.c
index 968bcc3..b59e6aa 100644
--- a/hw/exynos4_boards.c
+++ b/hw/exynos4_boards.c
@@ -87,7 +87,7 @@ static void lan9215_init(uint32_t base, qemu_irq irq)
         qdev_set_nic_properties(dev, &nd_table[0]);
         qdev_prop_set_uint32(dev, "mode_16bit", 1);
         qdev_init_nofail(dev);
-        s = sysbus_from_qdev(dev);
+        s = SYS_BUS_DEVICE(dev);
         sysbus_mmio_map(s, 0, base);
         sysbus_connect_irq(s, 0, irq);
     }
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index 3b31d77..e4dc7c3 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -489,7 +489,7 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
     qdev_prop_set_uint32(dev, "ctl_iobase", ctl_port);
     qdev_prop_set_uint32(dev, "data_iobase", data_port);
     qdev_init_nofail(dev);
-    d = sysbus_from_qdev(dev);
+    d = SYS_BUS_DEVICE(dev);
 
     s = DO_UPCAST(FWCfgState, busdev.qdev, dev);
 
diff --git a/hw/grlib.h b/hw/grlib.h
index 35c22f5..afd5389 100644
--- a/hw/grlib.h
+++ b/hw/grlib.h
@@ -61,7 +61,7 @@ DeviceState *grlib_irqmp_create(hwaddr   base,
 
     env->irq_manager = dev;
 
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
 
     *cpu_irqs = qemu_allocate_irqs(grlib_irqmp_set_irq,
                                    dev,
@@ -91,10 +91,10 @@ DeviceState *grlib_gptimer_create(hwaddr  base,
         return NULL;
     }
 
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
 
     for (i = 0; i < nr_timers; i++) {
-        sysbus_connect_irq(sysbus_from_qdev(dev), i, cpu_irqs[base_irq + i]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, cpu_irqs[base_irq + i]);
     }
 
     return dev;
@@ -116,9 +116,9 @@ DeviceState *grlib_apbuart_create(hwaddr  base,
         return NULL;
     }
 
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
 
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
 
     return dev;
 }
diff --git a/hw/grlib_irqmp.c b/hw/grlib_irqmp.c
index b5427c8..ef8dd95 100644
--- a/hw/grlib_irqmp.c
+++ b/hw/grlib_irqmp.c
@@ -109,7 +109,7 @@ void grlib_irqmp_ack(DeviceState *dev, int intno)
 
     assert(dev != NULL);
 
-    sdev = sysbus_from_qdev(dev);
+    sdev = SYS_BUS_DEVICE(dev);
     assert(sdev != NULL);
 
     irqmp = FROM_SYSBUS(typeof(*irqmp), sdev);
@@ -138,7 +138,7 @@ void grlib_irqmp_set_irq(void *opaque, int irq, int level)
 
     assert(opaque != NULL);
 
-    irqmp = FROM_SYSBUS(typeof(*irqmp), sysbus_from_qdev(opaque));
+    irqmp = FROM_SYSBUS(typeof(*irqmp), SYS_BUS_DEVICE(opaque));
     assert(irqmp != NULL);
 
     s = irqmp->state;
diff --git a/hw/highbank.c b/hw/highbank.c
index 7bc6b44..defcc09 100644
--- a/hw/highbank.c
+++ b/hw/highbank.c
@@ -136,7 +136,7 @@ static VMStateDescription vmstate_highbank_regs = {
 
 static void highbank_regs_reset(DeviceState *dev)
 {
-    SysBusDevice *sys_dev = sysbus_from_qdev(dev);
+    SysBusDevice *sys_dev = SYS_BUS_DEVICE(dev);
     HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, sys_dev);
 
     s->regs[0x40] = 0x05F20121;
@@ -251,7 +251,7 @@ static void highbank_init(QEMUMachineInitArgs *args)
     qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
     qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
     qdev_init_nofail(dev);
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(busdev, 0, GIC_BASE_ADDR);
     for (n = 0; n < smp_cpus; n++) {
         sysbus_connect_irq(busdev, n, cpu_irq[n]);
@@ -263,21 +263,21 @@ static void highbank_init(QEMUMachineInitArgs *args)
 
     dev = qdev_create(NULL, "l2x0");
     qdev_init_nofail(dev);
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(busdev, 0, 0xfff12000);
 
     dev = qdev_create(NULL, "sp804");
     qdev_prop_set_uint32(dev, "freq0", 150000000);
     qdev_prop_set_uint32(dev, "freq1", 150000000);
     qdev_init_nofail(dev);
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(busdev, 0, 0xfff34000);
     sysbus_connect_irq(busdev, 0, pic[18]);
     sysbus_create_simple("pl011", 0xfff36000, pic[20]);
 
     dev = qdev_create(NULL, "highbank-regs");
     qdev_init_nofail(dev);
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(busdev, 0, 0xfff3c000);
 
     sysbus_create_simple("pl061", 0xfff30000, pic[14]);
@@ -294,19 +294,19 @@ static void highbank_init(QEMUMachineInitArgs *args)
         dev = qdev_create(NULL, "xgmac");
         qdev_set_nic_properties(dev, &nd_table[0]);
         qdev_init_nofail(dev);
-        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff50000);
-        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[77]);
-        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[78]);
-        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[79]);
+        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff50000);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[77]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[78]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[79]);
 
         qemu_check_nic_model(&nd_table[1], "xgmac");
         dev = qdev_create(NULL, "xgmac");
         qdev_set_nic_properties(dev, &nd_table[1]);
         qdev_init_nofail(dev);
-        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff51000);
-        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[80]);
-        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[81]);
-        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[82]);
+        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xfff51000);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[80]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, pic[81]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, pic[82]);
     }
 
     highbank_binfo.ram_size = ram_size;
diff --git a/hw/hpet.c b/hw/hpet.c
index 6efae55..97eaa2f 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -634,7 +634,7 @@ static const MemoryRegionOps hpet_ram_ops = {
 
 static void hpet_reset(DeviceState *d)
 {
-    HPETState *s = FROM_SYSBUS(HPETState, sysbus_from_qdev(d));
+    HPETState *s = FROM_SYSBUS(HPETState, SYS_BUS_DEVICE(d));
     int i;
 
     for (i = 0; i < s->num_timers; i++) {
@@ -657,7 +657,7 @@ static void hpet_reset(DeviceState *d)
     s->hpet_offset = 0ULL;
     s->config = 0ULL;
     hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
-    hpet_cfg.hpet[s->hpet_id].address = sysbus_from_qdev(d)->mmio[0].addr;
+    hpet_cfg.hpet[s->hpet_id].address = SYS_BUS_DEVICE(d)->mmio[0].addr;
 
     /* to document that the RTC lowers its output on reset as well */
     s->rtc_irq_level = 0;
diff --git a/hw/imx_serial.c b/hw/imx_serial.c
index 77ed693..2d8253e 100644
--- a/hw/imx_serial.c
+++ b/hw/imx_serial.c
@@ -425,7 +425,7 @@ void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq)
     }
 
     qdev_prop_set_chr(dev, "chardev", chr);
-    bus = sysbus_from_qdev(dev);
+    bus = SYS_BUS_DEVICE(dev);
     qdev_init_nofail(dev);
     if (addr != (hwaddr)-1) {
         sysbus_mmio_map(bus, 0, addr);
diff --git a/hw/lan9118.c b/hw/lan9118.c
index 969b634..6596979 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -401,7 +401,7 @@ static void phy_reset(lan9118_state *s)
 
 static void lan9118_reset(DeviceState *d)
 {
-    lan9118_state *s = FROM_SYSBUS(lan9118_state, sysbus_from_qdev(d));
+    lan9118_state *s = FROM_SYSBUS(lan9118_state, SYS_BUS_DEVICE(d));
     s->irq_cfg &= (IRQ_TYPE | IRQ_POL);
     s->int_sts = 0;
     s->int_en = 0;
@@ -1391,7 +1391,7 @@ void lan9118_init(NICInfo *nd, uint32_t base, qemu_irq irq)
     dev = qdev_create(NULL, "lan9118");
     qdev_set_nic_properties(dev, nd);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(s, 0, base);
     sysbus_connect_irq(s, 0, irq);
 }
diff --git a/hw/lm32.h b/hw/lm32.h
index 4194c9a..236686e 100644
--- a/hw/lm32.h
+++ b/hw/lm32.h
@@ -11,7 +11,7 @@ static inline DeviceState *lm32_pic_init(qemu_irq cpu_irq)
 
     dev = qdev_create(NULL, "lm32-pic");
     qdev_init_nofail(dev);
-    d = sysbus_from_qdev(dev);
+    d = SYS_BUS_DEVICE(dev);
     sysbus_connect_irq(d, 0, cpu_irq);
 
     return dev;
diff --git a/hw/m48t59.c b/hw/m48t59.c
index 8f1ca3c..427d95b 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -646,7 +646,7 @@ M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base,
     qdev_prop_set_uint32(dev, "size", size);
     qdev_prop_set_uint32(dev, "io_base", io_base);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     d = FROM_SYSBUS(M48t59SysBusState, s);
     state = &d->state;
     sysbus_connect_irq(s, 0, IRQ);
diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c
index 511004b..c792caf 100644
--- a/hw/marvell_88w8618_audio.c
+++ b/hw/marvell_88w8618_audio.c
@@ -222,7 +222,7 @@ static void mv88w8618_audio_write(void *opaque, hwaddr offset,
 static void mv88w8618_audio_reset(DeviceState *d)
 {
     mv88w8618_audio_state *s = FROM_SYSBUS(mv88w8618_audio_state,
-                                           sysbus_from_qdev(d));
+                                           SYS_BUS_DEVICE(d));
 
     s->playback_mode = 0;
     s->status = 0;
diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h
index 812ddd2..c8bd7e9 100644
--- a/hw/milkymist-hw.h
+++ b/hw/milkymist-hw.h
@@ -12,8 +12,8 @@ static inline DeviceState *milkymist_uart_create(hwaddr base,
 
     dev = qdev_create(NULL, "milkymist-uart");
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
 
     return dev;
 }
@@ -24,7 +24,7 @@ static inline DeviceState *milkymist_hpdmc_create(hwaddr base)
 
     dev = qdev_create(NULL, "milkymist-hpdmc");
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
 
     return dev;
 }
@@ -35,7 +35,7 @@ static inline DeviceState *milkymist_memcard_create(hwaddr base)
 
     dev = qdev_create(NULL, "milkymist-memcard");
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
 
     return dev;
 }
@@ -49,7 +49,7 @@ static inline DeviceState *milkymist_vgafb_create(hwaddr base,
     qdev_prop_set_uint32(dev, "fb_offset", fb_offset);
     qdev_prop_set_uint32(dev, "fb_mask", fb_mask);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
 
     return dev;
 }
@@ -67,10 +67,10 @@ static inline DeviceState *milkymist_sysctl_create(hwaddr base,
     qdev_prop_set_uint32(dev, "capabilities", capabilities);
     qdev_prop_set_uint32(dev, "gpio_strappings", gpio_strappings);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, gpio_irq);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 1, timer0_irq);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 2, timer1_irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, gpio_irq);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, timer0_irq);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, timer1_irq);
 
     return dev;
 }
@@ -82,8 +82,8 @@ static inline DeviceState *milkymist_pfpu_create(hwaddr base,
 
     dev = qdev_create(NULL, "milkymist-pfpu");
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
     return dev;
 }
 
@@ -144,8 +144,8 @@ static inline DeviceState *milkymist_tmu2_create(hwaddr base,
 
     dev = qdev_create(NULL, "milkymist-tmu2");
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
 
     return dev;
 #else
@@ -161,11 +161,11 @@ static inline DeviceState *milkymist_ac97_create(hwaddr base,
 
     dev = qdev_create(NULL, "milkymist-ac97");
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, crrequest_irq);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 1, crreply_irq);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 2, dmar_irq);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 3, dmaw_irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, crrequest_irq);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, crreply_irq);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2, dmar_irq);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 3, dmaw_irq);
 
     return dev;
 }
@@ -179,9 +179,9 @@ static inline DeviceState *milkymist_minimac_create(hwaddr base,
     dev = qdev_create(NULL, "milkymist-minimac");
     qdev_set_nic_properties(dev, &nd_table[0]);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, rx_irq);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 1, tx_irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, rx_irq);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, tx_irq);
 
     return dev;
 }
@@ -196,9 +196,9 @@ static inline DeviceState *milkymist_minimac2_create(hwaddr base,
     qdev_prop_set_taddr(dev, "buffers_base", buffers_base);
     qdev_set_nic_properties(dev, &nd_table[0]);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, rx_irq);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 1, tx_irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, rx_irq);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, tx_irq);
 
     return dev;
 }
@@ -215,8 +215,8 @@ static inline DeviceState *milkymist_softusb_create(hwaddr base,
     qdev_prop_set_uint32(dev, "dmem_base", dmem_base);
     qdev_prop_set_uint32(dev, "dmem_size", dmem_size);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
 
     return dev;
 }
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 72f70ca..17fbdde 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -209,7 +209,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
     case JAZZ_MAGNUM:
         dev = qdev_create(NULL, "sysbus-g364");
         qdev_init_nofail(dev);
-        sysbus = sysbus_from_qdev(dev);
+        sysbus = SYS_BUS_DEVICE(dev);
         sysbus_mmio_map(sysbus, 0, 0x60080000);
         sysbus_mmio_map(sysbus, 1, 0x40000000);
         sysbus_connect_irq(sysbus, 0, rc4030[3]);
@@ -295,7 +295,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
     /* NVRAM */
     dev = qdev_create(NULL, "ds1225y");
     qdev_init_nofail(dev);
-    sysbus = sysbus_from_qdev(dev);
+    sysbus = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(sysbus, 0, 0x80009000);
 
     /* LED indicator */
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 8fd6692..b0ab8f6 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -123,7 +123,7 @@ static void mipsnet_init(int base, qemu_irq irq, NICInfo *nd)
     qdev_set_nic_properties(dev, nd);
     qdev_init_nofail(dev);
 
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_connect_irq(s, 0, irq);
     memory_region_add_subregion(get_system_io(),
                                 base,
diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c
index 9c57d76..728723c 100644
--- a/hw/mpc8544_guts.c
+++ b/hw/mpc8544_guts.c
@@ -112,7 +112,7 @@ static int mpc8544_guts_initfn(SysBusDevice *dev)
 {
     GutsState *s;
 
-    s = FROM_SYSBUS(GutsState, sysbus_from_qdev(dev));
+    s = FROM_SYSBUS(GutsState, SYS_BUS_DEVICE(dev));
 
     memory_region_init_io(&s->iomem, &mpc8544_guts_ops, s,
                           "mpc6544.guts", MPC8544_GUTS_MMIO_SIZE);
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 035865f..7ac0a91 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -716,7 +716,7 @@ static void mv88w8618_pic_write(void *opaque, hwaddr offset,
 static void mv88w8618_pic_reset(DeviceState *d)
 {
     mv88w8618_pic_state *s = FROM_SYSBUS(mv88w8618_pic_state,
-                                         sysbus_from_qdev(d));
+                                         SYS_BUS_DEVICE(d));
 
     s->level = 0;
     s->enabled = 0;
@@ -873,7 +873,7 @@ static void mv88w8618_pit_write(void *opaque, hwaddr offset,
 static void mv88w8618_pit_reset(DeviceState *d)
 {
     mv88w8618_pit_state *s = FROM_SYSBUS(mv88w8618_pit_state,
-                                         sysbus_from_qdev(d));
+                                         SYS_BUS_DEVICE(d));
     int i;
 
     for (i = 0; i < 4; i++) {
@@ -1288,7 +1288,7 @@ static const MemoryRegionOps musicpal_gpio_ops = {
 static void musicpal_gpio_reset(DeviceState *d)
 {
     musicpal_gpio_state *s = FROM_SYSBUS(musicpal_gpio_state,
-                                         sysbus_from_qdev(d));
+                                         SYS_BUS_DEVICE(d));
 
     s->lcd_brightness = 0;
     s->out_state = 0;
@@ -1607,12 +1607,12 @@ static void musicpal_init(QEMUMachineInitArgs *args)
     dev = qdev_create(NULL, "mv88w8618_eth");
     qdev_set_nic_properties(dev, &nd_table[0]);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, MP_ETH_BASE);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[MP_ETH_IRQ]);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, MP_ETH_BASE);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[MP_ETH_IRQ]);
 
     sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL);
 
-    musicpal_misc_init(sysbus_from_qdev(dev));
+    musicpal_misc_init(SYS_BUS_DEVICE(dev));
 
     dev = sysbus_create_simple("musicpal_gpio", MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
     i2c_dev = sysbus_create_simple("gpio_i2c", -1, NULL);
@@ -1641,7 +1641,7 @@ static void musicpal_init(QEMUMachineInitArgs *args)
 
     wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
     dev = qdev_create(NULL, "mv88w8618_audio");
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     qdev_prop_set_ptr(dev, "wm8750", wm8750_dev);
     qdev_init_nofail(dev);
     sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
diff --git a/hw/nand.c b/hw/nand.c
index 6054f46..4a71265 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -224,7 +224,7 @@ static const struct {
 
 static void nand_reset(DeviceState *dev)
 {
-    NANDFlashState *s = FROM_SYSBUS(NANDFlashState, sysbus_from_qdev(dev));
+    NANDFlashState *s = FROM_SYSBUS(NANDFlashState, SYS_BUS_DEVICE(dev));
     s->cmd = NAND_CMD_READ0;
     s->addr = 0;
     s->addrlen = 0;
diff --git a/hw/nseries.c b/hw/nseries.c
index 6b717cf..99d353a 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -178,10 +178,10 @@ static void n8x0_nand_setup(struct n800_s *s)
         qdev_prop_set_drive_nofail(s->nand, "drive", dinfo->bdrv);
     }
     qdev_init_nofail(s->nand);
-    sysbus_connect_irq(sysbus_from_qdev(s->nand), 0,
+    sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0,
                        qdev_get_gpio_in(s->mpu->gpio, N8X0_ONENAND_GPIO));
     omap_gpmc_attach(s->mpu->gpmc, N8X0_ONENAND_CS,
-                     sysbus_mmio_get_region(sysbus_from_qdev(s->nand), 0));
+                     sysbus_mmio_get_region(SYS_BUS_DEVICE(s->nand), 0));
     otp_region = onenand_raw_otp(s->nand);
 
     memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
@@ -783,7 +783,7 @@ static void n8x0_usb_setup(struct n800_s *s)
 {
     SysBusDevice *dev;
     s->usb = qdev_create(NULL, "tusb6010");
-    dev = sysbus_from_qdev(s->usb);
+    dev = SYS_BUS_DEVICE(s->usb);
     qdev_init_nofail(s->usb);
     sysbus_connect_irq(dev, 0,
                        qdev_get_gpio_in(s->mpu->gpio, N8X0_TUSB_INT_GPIO));
diff --git a/hw/omap1.c b/hw/omap1.c
index e85f2e2..1870f4d 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -3859,7 +3859,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
     qdev_prop_set_uint32(s->ih[0], "size", 0x100);
     qdev_prop_set_ptr(s->ih[0], "clk", omap_findclk(s, "arminth_ck"));
     qdev_init_nofail(s->ih[0]);
-    busdev = sysbus_from_qdev(s->ih[0]);
+    busdev = SYS_BUS_DEVICE(s->ih[0]);
     sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
     sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
     sysbus_mmio_map(busdev, 0, 0xfffecb00);
@@ -3867,7 +3867,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
     qdev_prop_set_uint32(s->ih[1], "size", 0x800);
     qdev_prop_set_ptr(s->ih[1], "clk", omap_findclk(s, "arminth_ck"));
     qdev_init_nofail(s->ih[1]);
-    busdev = sysbus_from_qdev(s->ih[1]);
+    busdev = SYS_BUS_DEVICE(s->ih[1]);
     sysbus_connect_irq(busdev, 0,
                        qdev_get_gpio_in(s->ih[0], OMAP_INT_15XX_IH2_IRQ));
     /* The second interrupt controller's FIQ output is not wired up */
@@ -3980,9 +3980,9 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
     qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
     qdev_prop_set_ptr(s->gpio, "clk", omap_findclk(s, "arm_gpio_ck"));
     qdev_init_nofail(s->gpio);
-    sysbus_connect_irq(sysbus_from_qdev(s->gpio), 0,
+    sysbus_connect_irq(SYS_BUS_DEVICE(s->gpio), 0,
                        qdev_get_gpio_in(s->ih[0], OMAP_INT_GPIO_BANK1));
-    sysbus_mmio_map(sysbus_from_qdev(s->gpio), 0, 0xfffce000);
+    sysbus_mmio_map(SYS_BUS_DEVICE(s->gpio), 0, 0xfffce000);
 
     s->microwire = omap_uwire_init(system_memory, 0xfffb3000,
                                    qdev_get_gpio_in(s->ih[1], OMAP_INT_uWireTX),
@@ -3998,7 +3998,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
     qdev_prop_set_uint8(s->i2c[0], "revision", 0x11);
     qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "mpuper_ck"));
     qdev_init_nofail(s->i2c[0]);
-    busdev = sysbus_from_qdev(s->i2c[0]);
+    busdev = SYS_BUS_DEVICE(s->i2c[0]);
     sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C));
     sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_I2C_TX]);
     sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_I2C_RX]);
diff --git a/hw/omap2.c b/hw/omap2.c
index c835850..038a82a 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2283,7 +2283,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
     qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk"));
     qdev_prop_set_ptr(s->ih[0], "iclk", omap_findclk(s, "mpu_intc_iclk"));
     qdev_init_nofail(s->ih[0]);
-    busdev = sysbus_from_qdev(s->ih[0]);
+    busdev = SYS_BUS_DEVICE(s->ih[0]);
     sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
     sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
     sysbus_mmio_map(busdev, 0, 0x480fe000);
@@ -2398,7 +2398,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
     qdev_prop_set_ptr(s->i2c[0], "iclk", omap_findclk(s, "i2c1.iclk"));
     qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "i2c1.fclk"));
     qdev_init_nofail(s->i2c[0]);
-    busdev = sysbus_from_qdev(s->i2c[0]);
+    busdev = SYS_BUS_DEVICE(s->i2c[0]);
     sysbus_connect_irq(busdev, 0,
                        qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ));
     sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C1_TX]);
@@ -2410,7 +2410,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
     qdev_prop_set_ptr(s->i2c[1], "iclk", omap_findclk(s, "i2c2.iclk"));
     qdev_prop_set_ptr(s->i2c[1], "fclk", omap_findclk(s, "i2c2.fclk"));
     qdev_init_nofail(s->i2c[1]);
-    busdev = sysbus_from_qdev(s->i2c[1]);
+    busdev = SYS_BUS_DEVICE(s->i2c[1]);
     sysbus_connect_irq(busdev, 0,
                        qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ));
     sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C2_TX]);
@@ -2428,7 +2428,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
         qdev_prop_set_ptr(s->gpio, "fclk4", omap_findclk(s, "gpio5_dbclk"));
     }
     qdev_init_nofail(s->gpio);
-    busdev = sysbus_from_qdev(s->gpio);
+    busdev = SYS_BUS_DEVICE(s->gpio);
     sysbus_connect_irq(busdev, 0,
                        qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK1));
     sysbus_connect_irq(busdev, 3,
diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index 15bdd62..aadf1cc 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -588,7 +588,7 @@ static const MemoryRegionOps omap2_gpio_module_ops = {
 static void omap_gpif_reset(DeviceState *dev)
 {
     struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s,
-                    sysbus_from_qdev(dev));
+                    SYS_BUS_DEVICE(dev));
     omap_gpio_reset(&s->omap1);
 }
 
@@ -596,7 +596,7 @@ static void omap2_gpif_reset(DeviceState *dev)
 {
     int i;
     struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s,
-                    sysbus_from_qdev(dev));
+                    SYS_BUS_DEVICE(dev));
     for (i = 0; i < s->modulecount; i++) {
         omap2_gpio_module_reset(&s->modules[i]);
     }
diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c
index e0a5087..143b198 100644
--- a/hw/omap_i2c.c
+++ b/hw/omap_i2c.c
@@ -131,7 +131,7 @@ static void omap_i2c_fifo_run(OMAPI2CState *s)
 static void omap_i2c_reset(DeviceState *dev)
 {
     OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState,
-                                  sysbus_from_qdev(dev));
+                                  SYS_BUS_DEVICE(dev));
     s->mask = 0;
     s->stat = 0;
     s->dma = 0;
@@ -485,7 +485,7 @@ static void omap_i2c_register_types(void)
 
 i2c_bus *omap_i2c_bus(DeviceState *omap_i2c)
 {
-    OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, sysbus_from_qdev(omap_i2c));
+    OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, SYS_BUS_DEVICE(omap_i2c));
     return s->bus;
 }
 
diff --git a/hw/omap_intc.c b/hw/omap_intc.c
index 113725e..4b0acd0 100644
--- a/hw/omap_intc.c
+++ b/hw/omap_intc.c
@@ -329,7 +329,7 @@ static const MemoryRegionOps omap_inth_mem_ops = {
 static void omap_inth_reset(DeviceState *dev)
 {
     struct omap_intr_handler_s *s = FROM_SYSBUS(struct omap_intr_handler_s,
-                                                sysbus_from_qdev(dev));
+                                                SYS_BUS_DEVICE(dev));
     int i;
 
     for (i = 0; i < s->nbanks; ++i){
diff --git a/hw/onenand.c b/hw/onenand.c
index b82bf7d..00a8738 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -224,7 +224,7 @@ static void onenand_reset(OneNANDState *s, int cold)
 
 static void onenand_system_reset(DeviceState *dev)
 {
-    onenand_reset(FROM_SYSBUS(OneNANDState, sysbus_from_qdev(dev)), 1);
+    onenand_reset(FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(dev)), 1);
 }
 
 static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
@@ -835,7 +835,7 @@ static void onenand_register_types(void)
 
 void *onenand_raw_otp(DeviceState *onenand_device)
 {
-    return FROM_SYSBUS(OneNANDState, sysbus_from_qdev(onenand_device))->otp;
+    return FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(onenand_device))->otp;
 }
 
 type_init(onenand_register_types)
diff --git a/hw/openpic.c b/hw/openpic.c
index cc8ec35..d414f47 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -506,7 +506,7 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
 
 static void openpic_reset(DeviceState *d)
 {
-    OpenPICState *opp = FROM_SYSBUS(typeof (*opp), sysbus_from_qdev(d));
+    OpenPICState *opp = FROM_SYSBUS(typeof(*opp), SYS_BUS_DEVICE(d));
     int i;
 
     opp->gcr = GCR_RESET;
diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c
index 6c443ba..30947de 100644
--- a/hw/openrisc_sim.c
+++ b/hw/openrisc_sim.c
@@ -50,7 +50,7 @@ static void openrisc_sim_net_init(MemoryRegion *address_space,
     qdev_set_nic_properties(dev, nd);
     qdev_init_nofail(dev);
 
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_connect_irq(s, 0, irq);
     memory_region_add_subregion(address_space, base,
                                 sysbus_mmio_get_region(s, 0));
diff --git a/hw/pc.c b/hw/pc.c
index 8fc69db..780b1e4 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1019,7 +1019,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
 
         if (hpet) {
             for (i = 0; i < GSI_NUM_PINS; i++) {
-                sysbus_connect_irq(sysbus_from_qdev(hpet), i, gsi[i]);
+                sysbus_connect_irq(SYS_BUS_DEVICE(hpet), i, gsi[i]);
             }
             pit_isa_irq = -1;
             pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT);
@@ -1122,7 +1122,7 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
                                   "ioapic", OBJECT(dev), NULL);
     }
     qdev_init_nofail(dev);
-    d = sysbus_from_qdev(dev);
+    d = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(d, 0, 0xfec00000);
 
     for (i = 0; i < IOAPIC_NUM_PINS; i++) {
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
index 9cad074..bdfc6ce 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -147,7 +147,7 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
         dev = qdev_create(NULL, "xlnx.xps-spi");
         qdev_prop_set_uint8(dev, "num-ss-bits", NUM_SPI_FLASHES);
         qdev_init_nofail(dev);
-        busdev = sysbus_from_qdev(dev);
+        busdev = SYS_BUS_DEVICE(dev);
         sysbus_mmio_map(busdev, 0, 0x40a00000);
         sysbus_connect_irq(busdev, 0, irq[4]);
 
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index aadedef..9e6ff52 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -729,7 +729,7 @@ pflash_t *pflash_cfi01_register(hwaddr base,
                                 uint16_t id2, uint16_t id3, int be)
 {
     DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
-    SysBusDevice *busdev = sysbus_from_qdev(dev);
+    SysBusDevice *busdev = SYS_BUS_DEVICE(dev);
     pflash_t *pfl = (pflash_t *)object_dynamic_cast(OBJECT(dev),
                                                     "cfi.pflash01");
 
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index cfb91cb..b4220c1 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -760,7 +760,7 @@ pflash_t *pflash_cfi02_register(hwaddr base,
                                 int be)
 {
     DeviceState *dev = qdev_create(NULL, "cfi.pflash02");
-    SysBusDevice *busdev = sysbus_from_qdev(dev);
+    SysBusDevice *busdev = SYS_BUS_DEVICE(dev);
     pflash_t *pfl = (pflash_t *)object_dynamic_cast(OBJECT(dev),
                                                     "cfi.pflash02");
 
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index c36821a..9ccf4d1 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -547,7 +547,7 @@ void ppce500_init(PPCE500Params *params)
     qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
     qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_FSL_MPIC_20);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
 
     k = 0;
     for (i = 0; i < smp_cpus; i++) {
@@ -599,7 +599,7 @@ void ppce500_init(PPCE500Params *params)
     if (!pci_bus)
         printf("couldn't create PCI controller!\n");
 
-    sysbus_mmio_map(sysbus_from_qdev(dev), 1, MPC8544_PCI_IO);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, MPC8544_PCI_IO);
 
     if (pci_bus) {
         /* Register network interfaces. */
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 7a465a7..b1973f1 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -329,7 +329,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
     dev = qdev_create(NULL, "openpic");
     qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_RAVEN);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     pic_mem = s->mmio[0].memory;
     k = 0;
     for (i = 0; i < smp_cpus; i++) {
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index 4c206e2..7e90fb9 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -196,7 +196,7 @@ static int ppce500_spin_initfn(SysBusDevice *dev)
 {
     SpinState *s;
 
-    s = FROM_SYSBUS(SpinState, sysbus_from_qdev(dev));
+    s = FROM_SYSBUS(SpinState, SYS_BUS_DEVICE(dev));
 
     memory_region_init_io(&s->iomem, &spin_rw_ops, s, "e500 spin pv device",
                           sizeof(SpinInfo) * MAX_CPUS);
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 492805f..2367c6a 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1456,7 +1456,7 @@ PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base,
     SysBusDevice *i2c_dev;
     PXA2xxI2CState *s;
 
-    i2c_dev = sysbus_from_qdev(qdev_create(NULL, "pxa2xx_i2c"));
+    i2c_dev = SYS_BUS_DEVICE(qdev_create(NULL, "pxa2xx_i2c"));
     qdev_prop_set_uint32(&i2c_dev->qdev, "size", region_size + 1);
     qdev_prop_set_uint32(&i2c_dev->qdev, "offset", base & region_size);
 
diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index 693b1c2..c0dba45 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -481,8 +481,8 @@ DeviceState *pxa27x_dma_init(hwaddr base, qemu_irq irq)
     qdev_prop_set_int32(dev, "channels", PXA27X_DMA_NUM_CHANNELS);
     qdev_init_nofail(dev);
 
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
 
     return dev;
 }
@@ -495,8 +495,8 @@ DeviceState *pxa255_dma_init(hwaddr base, qemu_irq irq)
     qdev_prop_set_int32(dev, "channels", PXA27X_DMA_NUM_CHANNELS);
     qdev_init_nofail(dev);
 
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
 
     return dev;
 }
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index eec2ea3..05d2ad2 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -260,12 +260,12 @@ DeviceState *pxa2xx_gpio_init(hwaddr base,
     qdev_prop_set_int32(dev, "ncpu", cs->cpu_index);
     qdev_init_nofail(dev);
 
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0,
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
                     qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_0));
-    sysbus_connect_irq(sysbus_from_qdev(dev), 1,
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1,
                     qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_1));
-    sysbus_connect_irq(sysbus_from_qdev(dev), 2,
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 2,
                     qdev_get_gpio_in(pic, PXA2XX_PIC_GPIO_X));
 
     return dev;
@@ -297,7 +297,7 @@ static int pxa2xx_gpio_initfn(SysBusDevice *dev)
  */
 void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler)
 {
-    PXA2xxGPIOInfo *s = FROM_SYSBUS(PXA2xxGPIOInfo, sysbus_from_qdev(dev));
+    PXA2xxGPIOInfo *s = FROM_SYSBUS(PXA2xxGPIOInfo, SYS_BUS_DEVICE(dev));
     s->read_notify = handler;
 }
 
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 138245b..90b8fef 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -261,7 +261,7 @@ DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu)
 {
     CPUARMState *env = &cpu->env;
     DeviceState *dev = qdev_create(NULL, "pxa2xx_pic");
-    PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, sysbus_from_qdev(dev));
+    PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, SYS_BUS_DEVICE(dev));
 
     s->cpu = cpu;
 
@@ -279,8 +279,8 @@ DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu)
     /* Enable IC memory-mapped registers access.  */
     memory_region_init_io(&s->iomem, &pxa2xx_pic_ops, s,
                           "pxa2xx-pic", 0x00100000);
-    sysbus_init_mmio(sysbus_from_qdev(dev), &s->iomem);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
 
     /* Enable IC coprocessor access.  */
     define_arm_cp_regs_with_opaque(arm_env_get_cpu(env), pxa_pic_cp_reginfo, s);
diff --git a/hw/r2d.c b/hw/r2d.c
index 72b593f..a2e3b6f 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -262,7 +262,7 @@ static void r2d_init(QEMUMachineInitArgs *args)
     irq = r2d_fpga_init(address_space_mem, 0x04000000, sh7750_irl(s));
 
     dev = qdev_create(NULL, "sh_pci");
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     qdev_init_nofail(dev);
     sysbus_mmio_map(busdev, 0, P4ADDR(0x1e200000));
     sysbus_mmio_map(busdev, 1, A7ADDR(0x1e200000));
diff --git a/hw/realview.c b/hw/realview.c
index cecb67e..78da767 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -140,14 +140,14 @@ static void realview_init(QEMUMachineInitArgs *args,
     qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
     qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
     qdev_init_nofail(sysctl);
-    sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000);
+    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
 
     if (is_mpcore) {
         hwaddr periphbase;
         dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore");
         qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
         qdev_init_nofail(dev);
-        busdev = sysbus_from_qdev(dev);
+        busdev = SYS_BUS_DEVICE(dev);
         if (is_pb) {
             periphbase = 0x1f000000;
         } else {
@@ -172,8 +172,8 @@ static void realview_init(QEMUMachineInitArgs *args,
     pl041 = qdev_create(NULL, "pl041");
     qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
     qdev_init_nofail(pl041);
-    sysbus_mmio_map(sysbus_from_qdev(pl041), 0, 0x10004000);
-    sysbus_connect_irq(sysbus_from_qdev(pl041), 0, pic[19]);
+    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
+    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[19]);
 
     sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]);
     sysbus_create_simple("pl050_mouse", 0x10007000, pic[21]);
@@ -215,7 +215,7 @@ static void realview_init(QEMUMachineInitArgs *args,
 
     if (!is_pb) {
         dev = qdev_create(NULL, "realview_pci");
-        busdev = sysbus_from_qdev(dev);
+        busdev = SYS_BUS_DEVICE(dev);
         qdev_init_nofail(dev);
         sysbus_mmio_map(busdev, 0, 0x61000000); /* PCI self-config */
         sysbus_mmio_map(busdev, 1, 0x62000000); /* PCI config */
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index b1b74d8..8f2a7e2 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -35,7 +35,7 @@ static int realview_gic_init(SysBusDevice *dev)
     qdev_prop_set_uint32(s->gic, "num-cpu", 1);
     qdev_prop_set_uint32(s->gic, "num-irq", numirq);
     qdev_init_nofail(s->gic);
-    busdev = sysbus_from_qdev(s->gic);
+    busdev = SYS_BUS_DEVICE(s->gic);
 
     /* Pass through outbound IRQ lines from the GIC */
     sysbus_pass_irq(dev, busdev);
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index d67c8cc..136ceeb 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -210,7 +210,7 @@ void slavio_pic_info(Monitor *mon, DeviceState *dev)
     SLAVIO_INTCTLState *s;
     int i;
 
-    sd = sysbus_from_qdev(dev);
+    sd = SYS_BUS_DEVICE(dev);
     s = FROM_SYSBUS(SLAVIO_INTCTLState, sd);
     for (i = 0; i < MAX_CPUS; i++) {
         monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i,
@@ -230,7 +230,7 @@ void slavio_irq_info(Monitor *mon, DeviceState *dev)
     int i;
     int64_t count;
 
-    sd = sysbus_from_qdev(dev);
+    sd = SYS_BUS_DEVICE(dev);
     s = FROM_SYSBUS(SLAVIO_INTCTLState, sd);
     monitor_printf(mon, "IRQ statistics:\n");
     for (i = 0; i < 32; i++) {
diff --git a/hw/sm501.c b/hw/sm501.c
index dd186aa..b7ac7f9 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -1428,9 +1428,9 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
     qdev_prop_set_uint32(dev, "num-ports", 2);
     qdev_prop_set_taddr(dev, "dma-offset", base);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0,
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0,
                     base + MMIO_BASE_OFFSET + SM501_USB_HOST);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
 
     /* bridge to serial emulation module */
     if (chr) {
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index a34698f..36cb4ed 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -254,7 +254,7 @@ static void smc91c111_queue_tx(smc91c111_state *s, int packet)
 
 static void smc91c111_reset(DeviceState *dev)
 {
-    smc91c111_state *s = FROM_SYSBUS(smc91c111_state, sysbus_from_qdev(dev));
+    smc91c111_state *s = FROM_SYSBUS(smc91c111_state, SYS_BUS_DEVICE(dev));
     s->bank = 0;
     s->tx_fifo_len = 0;
     s->tx_fifo_done_len = 0;
@@ -797,7 +797,7 @@ void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq)
     dev = qdev_create(NULL, "smc91c111");
     qdev_set_nic_properties(dev, nd);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(s, 0, base);
     sysbus_connect_irq(s, 0, irq);
 }
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 27b3ad3..bbcc9fc 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -597,7 +597,7 @@ static int spapr_phb_init(SysBusDevice *s)
 
 static void spapr_phb_reset(DeviceState *qdev)
 {
-    SysBusDevice *s = sysbus_from_qdev(qdev);
+    SysBusDevice *s = SYS_BUS_DEVICE(qdev);
     sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
 
     /* Reset the IOMMU state */
diff --git a/hw/spitz.c b/hw/spitz.c
index ab7ca80..5bc49fc 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -156,7 +156,7 @@ static void sl_flash_register(PXA2xxState *cpu, int size)
         qdev_prop_set_uint8(dev, "chip_id", 0xf1);
 
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, FLASH_BASE);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, FLASH_BASE);
 }
 
 static int sl_nand_init(SysBusDevice *dev) {
@@ -459,7 +459,7 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
     SpitzKeyboardState *s;
 
     dev = sysbus_create_simple("spitz-keyboard", -1, NULL);
-    s = FROM_SYSBUS(SpitzKeyboardState, sysbus_from_qdev(dev));
+    s = FROM_SYSBUS(SpitzKeyboardState, SYS_BUS_DEVICE(dev));
 
     for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++)
         qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(cpu->gpio, spitz_gpio_key_sense[i]));
diff --git a/hw/stellaris.c b/hw/stellaris.c
index b5e78ff..9b8f203 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -1286,8 +1286,8 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
         enet = qdev_create(NULL, "stellaris_enet");
         qdev_set_nic_properties(enet, &nd_table[0]);
         qdev_init_nofail(enet);
-        sysbus_mmio_map(sysbus_from_qdev(enet), 0, 0x40048000);
-        sysbus_connect_irq(sysbus_from_qdev(enet), 0, pic[42]);
+        sysbus_mmio_map(SYS_BUS_DEVICE(enet), 0, 0x40048000);
+        sysbus_connect_irq(SYS_BUS_DEVICE(enet), 0, pic[42]);
     }
     if (board->peripherals & BP_GAMEPAD) {
         qemu_irq gpad_irq[5];
diff --git a/hw/strongarm.c b/hw/strongarm.c
index af688ac..ab736e3 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -619,9 +619,9 @@ static DeviceState *strongarm_gpio_init(hwaddr base,
     dev = qdev_create(NULL, "strongarm-gpio");
     qdev_init_nofail(dev);
 
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
     for (i = 0; i < 12; i++)
-        sysbus_connect_irq(sysbus_from_qdev(dev), i,
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
                     qdev_get_gpio_in(pic, SA_PIC_GPIO0_EDGE + i));
 
     return dev;
@@ -1597,9 +1597,9 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem,
         DeviceState *dev = qdev_create(NULL, "strongarm-uart");
         qdev_prop_set_chr(dev, "chardev", serial_hds[i]);
         qdev_init_nofail(dev);
-        sysbus_mmio_map(sysbus_from_qdev(dev), 0,
+        sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0,
                 sa_serial[i].io_base);
-        sysbus_connect_irq(sysbus_from_qdev(dev), 0,
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
                 qdev_get_gpio_in(s->pic, sa_serial[i].irq));
     }
 
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 41730bc..035a011 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -381,7 +381,7 @@ static void *iommu_init(hwaddr addr, uint32_t version, qemu_irq irq)
     dev = qdev_create(NULL, "iommu");
     qdev_prop_set_uint32(dev, "version", version);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_connect_irq(s, 0, irq);
     sysbus_mmio_map(s, 0, addr);
 
@@ -398,7 +398,7 @@ static void *sparc32_dma_init(hwaddr daddr, qemu_irq parent_irq,
     qdev_prop_set_ptr(dev, "iommu_opaque", iommu);
     qdev_prop_set_uint32(dev, "is_ledma", is_ledma);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_connect_irq(s, 0, parent_irq);
     *dev_irq = qdev_get_gpio_in(dev, 0);
     sysbus_mmio_map(s, 0, daddr);
@@ -419,7 +419,7 @@ static void lance_init(NICInfo *nd, hwaddr leaddr,
     qdev_set_nic_properties(dev, nd);
     qdev_prop_set_ptr(dev, "dma", dma_opaque);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(s, 0, leaddr);
     sysbus_connect_irq(s, 0, irq);
     reset = qdev_get_gpio_in(dev, 0);
@@ -437,7 +437,7 @@ static DeviceState *slavio_intctl_init(hwaddr addr,
     dev = qdev_create(NULL, "slavio_intctl");
     qdev_init_nofail(dev);
 
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
 
     for (i = 0; i < MAX_CPUS; i++) {
         for (j = 0; j < MAX_PILS; j++) {
@@ -465,7 +465,7 @@ static void slavio_timer_init_all(hwaddr addr, qemu_irq master_irq,
     dev = qdev_create(NULL, "slavio_timer");
     qdev_prop_set_uint32(dev, "num_cpus", num_cpus);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_connect_irq(s, 0, master_irq);
     sysbus_mmio_map(s, 0, addr + SYS_TIMER_OFFSET);
 
@@ -502,7 +502,7 @@ static void slavio_misc_init(hwaddr base,
 
     dev = qdev_create(NULL, "slavio_misc");
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     if (base) {
         /* 8 bit registers */
         /* Slavio control */
@@ -540,7 +540,7 @@ static void ecc_init(hwaddr base, qemu_irq irq, uint32_t version)
     dev = qdev_create(NULL, "eccmemctl");
     qdev_prop_set_uint32(dev, "version", version);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_connect_irq(s, 0, irq);
     sysbus_mmio_map(s, 0, base);
     if (version == 0) { // SS-600MP only
@@ -555,7 +555,7 @@ static void apc_init(hwaddr power_base, qemu_irq cpu_halt)
 
     dev = qdev_create(NULL, "apc");
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     /* Power management (APC) XXX: not a Slavio device */
     sysbus_mmio_map(s, 0, power_base);
     sysbus_connect_irq(s, 0, cpu_halt);
@@ -574,7 +574,7 @@ static void tcx_init(hwaddr addr, int vram_size, int width,
     qdev_prop_set_uint16(dev, "height", height);
     qdev_prop_set_uint16(dev, "depth", depth);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     /* 8-bit plane */
     sysbus_mmio_map(s, 0, addr + 0x00800000ULL);
     /* DAC */
@@ -604,7 +604,7 @@ static void idreg_init(hwaddr addr)
 
     dev = qdev_create(NULL, "macio_idreg");
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
 
     sysbus_mmio_map(s, 0, addr);
     cpu_physical_memory_write_rom(addr, idreg_data, sizeof(idreg_data));
@@ -653,7 +653,7 @@ static void afx_init(hwaddr addr)
 
     dev = qdev_create(NULL, "tcx_afx");
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
 
     sysbus_mmio_map(s, 0, addr);
 }
@@ -703,7 +703,7 @@ static void prom_init(hwaddr addr, const char *bios_name)
 
     dev = qdev_create(NULL, "openprom");
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
 
     sysbus_mmio_map(s, 0, addr);
 
@@ -793,7 +793,7 @@ static void ram_init(hwaddr addr, ram_addr_t RAM_size,
         exit(1);
     }
     dev = qdev_create(NULL, "memory");
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
 
     d = FROM_SYSBUS(RamDevice, s);
     d->size = RAM_size;
@@ -1560,7 +1560,7 @@ static DeviceState *sbi_init(hwaddr addr, qemu_irq **parent_irq)
     dev = qdev_create(NULL, "sbi");
     qdev_init_nofail(dev);
 
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
 
     for (i = 0; i < MAX_CPUS; i++) {
         sysbus_connect_irq(s, i, *parent_irq[i]);
@@ -1761,7 +1761,7 @@ static DeviceState *sun4c_intctl_init(hwaddr addr,
     dev = qdev_create(NULL, "sun4c_intctl");
     qdev_init_nofail(dev);
 
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
 
     for (i = 0; i < MAX_PILS; i++) {
         sysbus_connect_irq(s, i, parent_irq[i]);
diff --git a/hw/sun4u.c b/hw/sun4u.c
index d36acde..b891b84 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -646,7 +646,7 @@ static void prom_init(hwaddr addr, const char *bios_name)
 
     dev = qdev_create(NULL, "openprom");
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
 
     sysbus_mmio_map(s, 0, addr);
 
@@ -729,7 +729,7 @@ static void ram_init(hwaddr addr, ram_addr_t RAM_size)
 
     /* allocate RAM */
     dev = qdev_create(NULL, "memory");
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
 
     d = FROM_SYSBUS(RamDevice, s);
     d->size = RAM_size;
diff --git a/hw/sysbus.c b/hw/sysbus.c
index f0ab8a8..6d9d1df 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -131,7 +131,7 @@ DeviceState *sysbus_create_varargs(const char *name,
     int n;
 
     dev = qdev_create(NULL, name);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     qdev_init_nofail(dev);
     if (addr != (hwaddr)-1) {
         sysbus_mmio_map(s, 0, addr);
@@ -163,7 +163,7 @@ DeviceState *sysbus_try_create_varargs(const char *name,
     if (!dev) {
         return NULL;
     }
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     qdev_init_nofail(dev);
     if (addr != (hwaddr)-1) {
         sysbus_mmio_map(s, 0, addr);
@@ -184,7 +184,7 @@ DeviceState *sysbus_try_create_varargs(const char *name,
 
 static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
 {
-    SysBusDevice *s = sysbus_from_qdev(dev);
+    SysBusDevice *s = SYS_BUS_DEVICE(dev);
     hwaddr size;
     int i;
 
@@ -198,7 +198,7 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
 
 static char *sysbus_get_fw_dev_path(DeviceState *dev)
 {
-    SysBusDevice *s = sysbus_from_qdev(dev);
+    SysBusDevice *s = SYS_BUS_DEVICE(dev);
     char path[40];
     int off;
 
diff --git a/hw/sysbus.h b/hw/sysbus.h
index 669cf87..a7fcded 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -44,7 +44,6 @@ struct SysBusDevice {
 };
 
 /* Macros to compensate for lack of type inheritance in C.  */
-#define sysbus_from_qdev(dev) ((SysBusDevice *)(dev))
 #define FROM_SYSBUS(type, dev) DO_UPCAST(type, busdev, dev)
 
 void *sysbus_new(void);
diff --git a/hw/tusb6010.c b/hw/tusb6010.c
index 7d05b31..2c7d033 100644
--- a/hw/tusb6010.c
+++ b/hw/tusb6010.c
@@ -740,7 +740,7 @@ static void tusb6010_irq(void *opaque, int source, int level)
 
 static void tusb6010_reset(DeviceState *dev)
 {
-    TUSBState *s = FROM_SYSBUS(TUSBState, sysbus_from_qdev(dev));
+    TUSBState *s = FROM_SYSBUS(TUSBState, SYS_BUS_DEVICE(dev));
     int i;
 
     s->test_reset = TUSB_PROD_TEST_RESET_VAL;
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 7a1b20b..e0a28f0 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -203,7 +203,7 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id)
     qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004);
     qdev_prop_set_uint32(sysctl, "proc_id", 0x02000000);
     qdev_init_nofail(sysctl);
-    sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000);
+    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
 
     cpu_pic = arm_pic_init_cpu(cpu);
     dev = sysbus_create_varargs("pl190", 0x10140000,
@@ -214,7 +214,7 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id)
     }
     dev = sysbus_create_simple("versatilepb_sic", 0x10003000, NULL);
     for (n = 0; n < 32; n++) {
-        sysbus_connect_irq(sysbus_from_qdev(dev), n, pic[n]);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), n, pic[n]);
         sic[n] = qdev_get_gpio_in(dev, n);
     }
 
@@ -222,7 +222,7 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id)
     sysbus_create_simple("pl050_mouse", 0x10007000, sic[4]);
 
     dev = qdev_create(NULL, "versatile_pci");
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     qdev_init_nofail(dev);
     sysbus_mmio_map(busdev, 0, 0x41000000); /* PCI self-config */
     sysbus_mmio_map(busdev, 1, 0x42000000); /* PCI config */
@@ -287,8 +287,8 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id)
     pl041 = qdev_create(NULL, "pl041");
     qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
     qdev_init_nofail(pl041);
-    sysbus_mmio_map(sysbus_from_qdev(pl041), 0, 0x10004000);
-    sysbus_connect_irq(sysbus_from_qdev(pl041), 0, sic[24]);
+    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000);
+    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, sic[24]);
 
     /* Memory map for Versatile/PB:  */
     /* 0x10000000 System registers.  */
diff --git a/hw/vexpress.c b/hw/vexpress.c
index 6bbe8c3..7f0897c 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -211,7 +211,7 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard,
     dev = qdev_create(NULL, "a9mpcore_priv");
     qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
     qdev_init_nofail(dev);
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(busdev, 0, 0x1e000000);
     for (n = 0; n < smp_cpus; n++) {
         sysbus_connect_irq(busdev, n, cpu_irq[n]);
@@ -307,7 +307,7 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard,
     dev = qdev_create(NULL, "a15mpcore_priv");
     qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
     qdev_init_nofail(dev);
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(busdev, 0, 0x2c000000);
     for (n = 0; n < smp_cpus; n++) {
         sysbus_connect_irq(busdev, n, cpu_irq[n]);
@@ -374,7 +374,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
     qdev_prop_set_uint32(sysctl, "sys_id", sys_id);
     qdev_prop_set_uint32(sysctl, "proc_id", proc_id);
     qdev_init_nofail(sysctl);
-    sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, map[VE_SYSREGS]);
+    sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]);
 
     /* VE_SP810: not modelled */
     /* VE_SERIALPCI: not modelled */
@@ -382,8 +382,8 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard,
     pl041 = qdev_create(NULL, "pl041");
     qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512);
     qdev_init_nofail(pl041);
-    sysbus_mmio_map(sysbus_from_qdev(pl041), 0, map[VE_PL041]);
-    sysbus_connect_irq(sysbus_from_qdev(pl041), 0, pic[11]);
+    sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, map[VE_PL041]);
+    sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[11]);
 
     dev = sysbus_create_varargs("pl181", map[VE_MMCI], pic[9], pic[10], NULL);
     /* Wire up MMC card detect and read-only signals */
diff --git a/hw/xilinx.h b/hw/xilinx.h
index a12eccb..725f2f4 100644
--- a/hw/xilinx.h
+++ b/hw/xilinx.h
@@ -14,8 +14,8 @@ xilinx_intc_create(hwaddr base, qemu_irq irq, int kind_of_intr)
     dev = qdev_create(NULL, "xlnx.xps-intc");
     qdev_prop_set_uint32(dev, "kind-of-intr", kind_of_intr);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
     return dev;
 }
 
@@ -29,8 +29,8 @@ xilinx_timer_create(hwaddr base, qemu_irq irq, int oto, int freq)
     qdev_prop_set_uint32(dev, "one-timer-only", oto);
     qdev_prop_set_uint32(dev, "clock-frequency", freq);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
     return dev;
 }
 
@@ -48,8 +48,8 @@ xilinx_ethlite_create(NICInfo *nd, hwaddr base, qemu_irq irq,
     qdev_prop_set_uint32(dev, "tx-ping-pong", txpingpong);
     qdev_prop_set_uint32(dev, "rx-ping-pong", rxpingpong);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
     return dev;
 }
 
@@ -71,8 +71,8 @@ xilinx_axiethernet_create(NICInfo *nd, StreamSlave *peer,
                              &errp);
     assert_no_error(errp);
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
 
     return dev;
 }
@@ -90,9 +90,9 @@ xilinx_axiethernetdma_init(DeviceState *dev, StreamSlave *peer,
     assert_no_error(errp);
     qdev_init_nofail(dev);
 
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
-    sysbus_connect_irq(sysbus_from_qdev(dev), 1, irq2);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
+    sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, irq2);
 }
 
 #endif
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index 8dede9f..0ac33b5 100644
--- a/hw/xilinx_zynq.c
+++ b/hw/xilinx_zynq.c
@@ -46,7 +46,7 @@ static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
     dev = qdev_create(NULL, "cadence_gem");
     qdev_set_nic_properties(dev, nd);
     qdev_init_nofail(dev);
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(s, 0, base);
     sysbus_connect_irq(s, 0, irq);
 }
@@ -67,7 +67,7 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
     qdev_prop_set_uint8(dev, "num-ss-bits", num_ss);
     qdev_prop_set_uint8(dev, "num-busses", num_busses);
     qdev_init_nofail(dev);
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(busdev, 0, base_addr);
     if (is_qspi) {
         sysbus_mmio_map(busdev, 1, 0xFC000000);
@@ -150,12 +150,12 @@ static void zynq_init(QEMUMachineInitArgs *args)
 
     dev = qdev_create(NULL, "xilinx,zynq_slcr");
     qdev_init_nofail(dev);
-    sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xF8000000);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000);
 
     dev = qdev_create(NULL, "a9mpcore_priv");
     qdev_prop_set_uint32(dev, "num-cpu", 1);
     qdev_init_nofail(dev);
-    busdev = sysbus_from_qdev(dev);
+    busdev = SYS_BUS_DEVICE(dev);
     sysbus_mmio_map(busdev, 0, 0xF8F00000);
     sysbus_connect_irq(busdev, 0, cpu_irq);
 
diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c
index a85fe9b..a810b9e 100644
--- a/hw/xtensa_lx60.c
+++ b/hw/xtensa_lx60.c
@@ -131,7 +131,7 @@ static void lx60_net_init(MemoryRegion *address_space,
     qdev_set_nic_properties(dev, nd);
     qdev_init_nofail(dev);
 
-    s = sysbus_from_qdev(dev);
+    s = SYS_BUS_DEVICE(dev);
     sysbus_connect_irq(s, 0, irq);
     memory_region_add_subregion(address_space, base,
             sysbus_mmio_get_region(s, 0));
diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c
index 4d6f8d9..27b00f0 100644
--- a/hw/zynq_slcr.c
+++ b/hw/zynq_slcr.c
@@ -160,7 +160,7 @@ static void zynq_slcr_reset(DeviceState *d)
 {
     int i;
     ZynqSLCRState *s =
-            FROM_SYSBUS(ZynqSLCRState, sysbus_from_qdev(d));
+            FROM_SYSBUS(ZynqSLCRState, SYS_BUS_DEVICE(d));
 
     DB_PRINT("RESET\n");
 
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 333745b..376d4c8 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2134,7 +2134,7 @@ static void x86_cpu_apic_init(X86CPU *cpu, Error **errp)
         /* NOTE: the APIC is directly connected to the CPU - it is not
            on the global memory bus. */
         /* XXX: what if the base changes? */
-        sysbus_mmio_map(sysbus_from_qdev(env->apic_state), 0, MSI_ADDR_BASE);
+        sysbus_mmio_map(SYS_BUS_DEVICE(env->apic_state), 0, MSI_ADDR_BASE);
         apic_mapped = 1;
     }
 }
commit 6fd8e79af031d8cfc0eb02d40d03281917fcb27b
Author: Tim Hardeck <thardeck at suse.de>
Date:   Mon Jan 21 11:04:45 2013 +0100

    vnc: fix possible uninitialized removals
    
    Some VncState values are not initialized before the Websocket handshake.
    If it fails QEMU segfaults during the cleanup. To prevent this behavior
    intialization checks are added.
    
    Signed-off-by: Tim Hardeck <thardeck at suse.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index ee08894..ff4e2ae 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1053,20 +1053,24 @@ void vnc_disconnect_finish(VncState *vs)
     audio_del(vs);
     vnc_release_modifiers(vs);
 
-    QTAILQ_REMOVE(&vs->vd->clients, vs, next);
+    if (vs->initialized) {
+        QTAILQ_REMOVE(&vs->vd->clients, vs, next);
+        qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
+    }
 
     if (QTAILQ_EMPTY(&vs->vd->clients)) {
         dcl->idle = 1;
     }
 
-    qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
     vnc_remove_timer(vs->vd);
     if (vs->vd->lock_key_sync)
         qemu_remove_led_event_handler(vs->led);
     vnc_unlock_output(vs);
 
     qemu_mutex_destroy(&vs->output_mutex);
-    qemu_bh_delete(vs->bh);
+    if (vs->bh != NULL) {
+        qemu_bh_delete(vs->bh);
+    }
     buffer_free(&vs->jobs_buffer);
 
     for (i = 0; i < VNC_STAT_ROWS; ++i) {
@@ -2749,6 +2753,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket)
 
 void vnc_init_state(VncState *vs)
 {
+    vs->initialized = true;
     VncDisplay *vd = vs->vd;
 
     vs->ds = vd->ds;
diff --git a/ui/vnc.h b/ui/vnc.h
index f93c89a..45d7686 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -306,6 +306,7 @@ struct VncState
     QEMUPutLEDEntry *led;
 
     bool abort;
+    bool initialized;
     QemuMutex output_mutex;
     QEMUBH *bh;
     Buffer jobs_buffer;
commit 7536ee4bc3da7e9b7fdadba5ba6ade63eaace430
Author: Tim Hardeck <thardeck at suse.de>
Date:   Mon Jan 21 11:04:44 2013 +0100

    vnc: added initial websocket protocol support
    
    This patch adds basic Websocket Protocol version 13 - RFC 6455 - support
    to QEMU VNC. Binary encoding support on the client side is mandatory.
    
    Because of the GnuTLS requirement the Websockets implementation is
    optional (--enable-vnc-ws).
    
    To activate Websocket support the VNC option "websocket"is used, for
    example "-vnc :0,websocket".
    The listen port for Websocket connections is (5700 + display) so if
    QEMU VNC is started with :0 the Websocket port would be 5700.
    As an alternative the Websocket port could be manually specified by
    using ",websocket=<port>" instead.
    
    Parts of the implementation base on Anthony Liguori's QEMU Websocket
    patch from 2010 and on Joel Martin's LibVNC Websocket implementation.
    
    Signed-off-by: Tim Hardeck <thardeck at suse.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 6211db9..c6172ef 100755
--- a/configure
+++ b/configure
@@ -158,6 +158,7 @@ vnc_tls=""
 vnc_sasl=""
 vnc_jpeg=""
 vnc_png=""
+vnc_ws=""
 xen=""
 xen_ctrl_version=""
 xen_pci_passthrough=""
@@ -724,6 +725,10 @@ for opt do
   ;;
   --enable-vnc-png) vnc_png="yes"
   ;;
+  --disable-vnc-ws) vnc_ws="no"
+  ;;
+  --enable-vnc-ws) vnc_ws="yes"
+  ;;
   --disable-slirp) slirp="no"
   ;;
   --disable-uuid) uuid="no"
@@ -1069,6 +1074,8 @@ echo "  --disable-vnc-jpeg       disable JPEG lossy compression for VNC server"
 echo "  --enable-vnc-jpeg        enable JPEG lossy compression for VNC server"
 echo "  --disable-vnc-png        disable PNG compression for VNC server (default)"
 echo "  --enable-vnc-png         enable PNG compression for VNC server"
+echo "  --disable-vnc-ws         disable Websockets support for VNC server"
+echo "  --enable-vnc-ws          enable Websockets support for VNC server"
 echo "  --disable-curses         disable curses output"
 echo "  --enable-curses          enable curses output"
 echo "  --disable-curl           disable curl connectivity"
@@ -1712,8 +1719,8 @@ EOF
 fi
 
 ##########################################
-# VNC TLS detection
-if test "$vnc" = "yes" -a "$vnc_tls" != "no" ; then
+# VNC TLS/WS detection
+if test "$vnc" = "yes" -a \( "$vnc_tls" != "no" -o "$vnc_ws" != "no" \) ; then
   cat > $TMPC <<EOF
 #include <gnutls/gnutls.h>
 int main(void) { gnutls_session_t s; gnutls_init(&s, GNUTLS_SERVER); return 0; }
@@ -1721,14 +1728,23 @@ EOF
   vnc_tls_cflags=`$pkg_config --cflags gnutls 2> /dev/null`
   vnc_tls_libs=`$pkg_config --libs gnutls 2> /dev/null`
   if compile_prog "$vnc_tls_cflags" "$vnc_tls_libs" ; then
-    vnc_tls=yes
+    if test "$vnc_tls" != "no" ; then
+      vnc_tls=yes
+    fi
+    if test "$vnc_ws" != "no" ; then
+      vnc_ws=yes
+    fi
     libs_softmmu="$vnc_tls_libs $libs_softmmu"
     QEMU_CFLAGS="$QEMU_CFLAGS $vnc_tls_cflags"
   else
     if test "$vnc_tls" = "yes" ; then
       feature_not_found "vnc-tls"
     fi
+    if test "$vnc_ws" = "yes" ; then
+      feature_not_found "vnc-ws"
+    fi
     vnc_tls=no
+    vnc_ws=no
   fi
 fi
 
@@ -3283,6 +3299,7 @@ if test "$vnc" = "yes" ; then
     echo "VNC SASL support  $vnc_sasl"
     echo "VNC JPEG support  $vnc_jpeg"
     echo "VNC PNG support   $vnc_png"
+    echo "VNC WS support    $vnc_ws"
 fi
 if test -n "$sparc_cpu"; then
     echo "Target Sparc Arch $sparc_cpu"
@@ -3461,6 +3478,10 @@ fi
 if test "$vnc_png" = "yes" ; then
   echo "CONFIG_VNC_PNG=y" >> $config_host_mak
 fi
+if test "$vnc_ws" = "yes" ; then
+  echo "CONFIG_VNC_WS=y" >> $config_host_mak
+  echo "VNC_WS_CFLAGS=$vnc_ws_cflags" >> $config_host_mak
+fi
 if test "$fnmatch" = "yes" ; then
   echo "CONFIG_FNMATCH=y" >> $config_host_mak
 fi
diff --git a/qemu-options.hx b/qemu-options.hx
index 40cd683..4e2b499 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1096,6 +1096,14 @@ client is specified by the @var{display}. For reverse network
 connections (@var{host}:@var{d}, at code{reverse}), the @var{d} argument
 is a TCP port number, not a display number.
 
+ at item websocket
+
+Opens an additional TCP listening port dedicated to VNC Websocket connections.
+By defintion the Websocket port is 5700+ at var{display}. If @var{host} is
+specified connections will only be allowed from this host.
+As an alternative the Websocket port could be specified by using
+ at code{websocket}=@var{port}.
+
 @item password
 
 Require that password based authentication is used for client connections.
diff --git a/ui/Makefile.objs b/ui/Makefile.objs
index 6768bb7..d9db073 100644
--- a/ui/Makefile.objs
+++ b/ui/Makefile.objs
@@ -4,6 +4,7 @@ vnc-obj-y += vnc-enc-tight.o vnc-palette.o
 vnc-obj-y += vnc-enc-zrle.o
 vnc-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
 vnc-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
+vnc-obj-$(CONFIG_VNC_WS) += vnc-ws.o
 vnc-obj-y += vnc-jobs.o
 
 common-obj-y += keymaps.o console.o cursor.o input.o qemu-pixman.o
diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c
new file mode 100644
index 0000000..9ccdc19
--- /dev/null
+++ b/ui/vnc-ws.c
@@ -0,0 +1,284 @@
+/*
+ * QEMU VNC display driver: Websockets support
+ *
+ * Copyright (C) 2010 Joel Martin
+ * Copyright (C) 2012 Tim Hardeck
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "vnc.h"
+
+void vncws_handshake_read(void *opaque)
+{
+    VncState *vs = opaque;
+    uint8_t *handshake_end;
+    long ret;
+    buffer_reserve(&vs->ws_input, 4096);
+    ret = vnc_client_read_buf(vs, buffer_end(&vs->ws_input), 4096);
+
+    if (!ret) {
+        if (vs->csock == -1) {
+            vnc_disconnect_finish(vs);
+        }
+        return;
+    }
+    vs->ws_input.offset += ret;
+
+    handshake_end = (uint8_t *)g_strstr_len((char *)vs->ws_input.buffer,
+            vs->ws_input.offset, WS_HANDSHAKE_END);
+    if (handshake_end) {
+        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
+        vncws_process_handshake(vs, vs->ws_input.buffer, vs->ws_input.offset);
+        buffer_advance(&vs->ws_input, handshake_end - vs->ws_input.buffer +
+                strlen(WS_HANDSHAKE_END));
+    }
+}
+
+
+long vnc_client_read_ws(VncState *vs)
+{
+    int ret, err;
+    uint8_t *payload;
+    size_t payload_size, frame_size;
+    VNC_DEBUG("Read websocket %p size %zd offset %zd\n", vs->ws_input.buffer,
+            vs->ws_input.capacity, vs->ws_input.offset);
+    buffer_reserve(&vs->ws_input, 4096);
+    ret = vnc_client_read_buf(vs, buffer_end(&vs->ws_input), 4096);
+    if (!ret) {
+        return 0;
+    }
+    vs->ws_input.offset += ret;
+
+    /* make sure that nothing is left in the ws_input buffer */
+    do {
+        err = vncws_decode_frame(&vs->ws_input, &payload,
+                              &payload_size, &frame_size);
+        if (err <= 0) {
+            return err;
+        }
+
+        buffer_reserve(&vs->input, payload_size);
+        buffer_append(&vs->input, payload, payload_size);
+
+        buffer_advance(&vs->ws_input, frame_size);
+    } while (vs->ws_input.offset > 0);
+
+    return ret;
+}
+
+long vnc_client_write_ws(VncState *vs)
+{
+    long ret;
+    VNC_DEBUG("Write WS: Pending output %p size %zd offset %zd\n",
+              vs->output.buffer, vs->output.capacity, vs->output.offset);
+    vncws_encode_frame(&vs->ws_output, vs->output.buffer, vs->output.offset);
+    buffer_reset(&vs->output);
+    ret = vnc_client_write_buf(vs, vs->ws_output.buffer, vs->ws_output.offset);
+    if (!ret) {
+        return 0;
+    }
+
+    buffer_advance(&vs->ws_output, ret);
+
+    if (vs->ws_output.offset == 0) {
+        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
+    }
+
+    return ret;
+}
+
+static char *vncws_extract_handshake_entry(const char *handshake,
+        size_t handshake_len, const char *name)
+{
+    char *begin, *end, *ret = NULL;
+    char *line = g_strdup_printf("%s%s: ", WS_HANDSHAKE_DELIM, name);
+    begin = g_strstr_len(handshake, handshake_len, line);
+    if (begin != NULL) {
+        begin += strlen(line);
+        end = g_strstr_len(begin, handshake_len - (begin - handshake),
+                WS_HANDSHAKE_DELIM);
+        if (end != NULL) {
+            ret = g_strndup(begin, end - begin);
+        }
+    }
+    g_free(line);
+    return ret;
+}
+
+static void vncws_send_handshake_response(VncState *vs, const char* key)
+{
+    char combined_key[WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1];
+    char hash[SHA1_DIGEST_LEN];
+    size_t hash_size = SHA1_DIGEST_LEN;
+    char *accept = NULL, *response = NULL;
+    gnutls_datum_t in;
+
+    g_strlcpy(combined_key, key, WS_CLIENT_KEY_LEN + 1);
+    g_strlcat(combined_key, WS_GUID, WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1);
+
+    /* hash and encode it */
+    in.data = (void *)combined_key;
+    in.size = WS_CLIENT_KEY_LEN + WS_GUID_LEN;
+    if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &in, hash, &hash_size)
+            == GNUTLS_E_SUCCESS) {
+        accept = g_base64_encode((guchar *)hash, SHA1_DIGEST_LEN);
+    }
+    if (accept == NULL) {
+        VNC_DEBUG("Hashing Websocket combined key failed\n");
+        vnc_client_error(vs);
+        return;
+    }
+
+    response = g_strdup_printf(WS_HANDSHAKE, accept);
+    vnc_write(vs, response, strlen(response));
+    vnc_flush(vs);
+
+    g_free(accept);
+    g_free(response);
+
+    vs->encode_ws = 1;
+    vnc_init_state(vs);
+}
+
+void vncws_process_handshake(VncState *vs, uint8_t *line, size_t size)
+{
+    char *protocols = vncws_extract_handshake_entry((const char *)line, size,
+            "Sec-WebSocket-Protocol");
+    char *version = vncws_extract_handshake_entry((const char *)line, size,
+            "Sec-WebSocket-Version");
+    char *key = vncws_extract_handshake_entry((const char *)line, size,
+            "Sec-WebSocket-Key");
+
+    if (protocols && version && key
+            && g_strrstr(protocols, "binary")
+            && !strcmp(version, WS_SUPPORTED_VERSION)
+            && strlen(key) == WS_CLIENT_KEY_LEN) {
+        vncws_send_handshake_response(vs, key);
+    } else {
+        VNC_DEBUG("Defective Websockets header or unsupported protocol\n");
+        vnc_client_error(vs);
+    }
+
+    g_free(protocols);
+    g_free(version);
+    g_free(key);
+}
+
+void vncws_encode_frame(Buffer *output, const void *payload,
+        const size_t payload_size)
+{
+    size_t header_size = 0;
+    unsigned char opcode = WS_OPCODE_BINARY_FRAME;
+    union {
+        char buf[WS_HEAD_MAX_LEN];
+        WsHeader ws;
+    } header;
+
+    if (!payload_size) {
+        return;
+    }
+
+    header.ws.b0 = 0x80 | (opcode & 0x0f);
+    if (payload_size <= 125) {
+        header.ws.b1 = (uint8_t)payload_size;
+        header_size = 2;
+    } else if (payload_size < 65536) {
+        header.ws.b1 = 0x7e;
+        header.ws.u.s16.l16 = cpu_to_be16((uint16_t)payload_size);
+        header_size = 4;
+    } else {
+        header.ws.b1 = 0x7f;
+        header.ws.u.s64.l64 = cpu_to_be64(payload_size);
+        header_size = 10;
+    }
+
+    buffer_reserve(output, header_size + payload_size);
+    buffer_append(output, header.buf, header_size);
+    buffer_append(output, payload, payload_size);
+}
+
+int vncws_decode_frame(Buffer *input, uint8_t **payload,
+                           size_t *payload_size, size_t *frame_size)
+{
+    unsigned char opcode = 0, fin = 0, has_mask = 0;
+    size_t header_size = 0;
+    uint32_t *payload32;
+    WsHeader *header = (WsHeader *)input->buffer;
+    WsMask mask;
+    int i;
+
+    if (input->offset < WS_HEAD_MIN_LEN + 4) {
+        /* header not complete */
+        return 0;
+    }
+
+    fin = (header->b0 & 0x80) >> 7;
+    opcode = header->b0 & 0x0f;
+    has_mask = (header->b1 & 0x80) >> 7;
+    *payload_size = header->b1 & 0x7f;
+
+    if (opcode == WS_OPCODE_CLOSE) {
+        /* disconnect */
+        return -1;
+    }
+
+    /* Websocket frame sanity check:
+     * * Websocket fragmentation is not supported.
+     * * All  websockets frames sent by a client have to be masked.
+     * * Only binary encoding is supported.
+     */
+    if (!fin || !has_mask || opcode != WS_OPCODE_BINARY_FRAME) {
+        VNC_DEBUG("Received faulty/unsupported Websocket frame\n");
+        return -2;
+    }
+
+    if (*payload_size < 126) {
+        header_size = 6;
+        mask = header->u.m;
+    } else if (*payload_size == 126 && input->offset >= 8) {
+        *payload_size = be16_to_cpu(header->u.s16.l16);
+        header_size = 8;
+        mask = header->u.s16.m16;
+    } else if (*payload_size == 127 && input->offset >= 14) {
+        *payload_size = be64_to_cpu(header->u.s64.l64);
+        header_size = 14;
+        mask = header->u.s64.m64;
+    } else {
+        /* header not complete */
+        return 0;
+    }
+
+    *frame_size = header_size + *payload_size;
+
+    if (input->offset < *frame_size) {
+        /* frame not complete */
+        return 0;
+    }
+
+    *payload = input->buffer + header_size;
+
+    /* unmask frame */
+    /* process 1 frame (32 bit op) */
+    payload32 = (uint32_t *)(*payload);
+    for (i = 0; i < *payload_size / 4; i++) {
+        payload32[i] ^= mask.u;
+    }
+    /* process the remaining bytes (if any) */
+    for (i *= 4; i < *payload_size; i++) {
+        (*payload)[i] ^= mask.c[i % 4];
+    }
+
+    return 1;
+}
diff --git a/ui/vnc-ws.h b/ui/vnc-ws.h
new file mode 100644
index 0000000..039a587
--- /dev/null
+++ b/ui/vnc-ws.h
@@ -0,0 +1,86 @@
+/*
+ * QEMU VNC display driver: Websockets support
+ *
+ * Copyright (C) 2010 Joel Martin
+ * Copyright (C) 2012 Tim Hardeck
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __QEMU_UI_VNC_WS_H
+#define __QEMU_UI_VNC_WS_H
+
+#include <gnutls/gnutls.h>
+
+#define B64LEN(__x) (((__x + 2) / 3) * 12 / 3)
+#define SHA1_DIGEST_LEN 20
+
+#define WS_ACCEPT_LEN (B64LEN(SHA1_DIGEST_LEN) + 1)
+#define WS_CLIENT_KEY_LEN 24
+#define WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
+#define WS_GUID_LEN strlen(WS_GUID)
+
+#define WS_HANDSHAKE "HTTP/1.1 101 Switching Protocols\r\n\
+Upgrade: websocket\r\n\
+Connection: Upgrade\r\n\
+Sec-WebSocket-Accept: %s\r\n\
+Sec-WebSocket-Protocol: binary\r\n\
+\r\n"
+#define WS_HANDSHAKE_DELIM "\r\n"
+#define WS_HANDSHAKE_END "\r\n\r\n"
+#define WS_SUPPORTED_VERSION "13"
+
+#define WS_HEAD_MIN_LEN sizeof(uint16_t)
+#define WS_HEAD_MAX_LEN (WS_HEAD_MIN_LEN + sizeof(uint64_t) + sizeof(uint32_t))
+
+typedef union WsMask {
+    char c[4];
+    uint32_t u;
+} WsMask;
+
+typedef struct QEMU_PACKED WsHeader {
+    unsigned char b0;
+    unsigned char b1;
+    union {
+        struct QEMU_PACKED {
+            uint16_t l16;
+            WsMask m16;
+        } s16;
+        struct QEMU_PACKED {
+            uint64_t l64;
+            WsMask m64;
+        } s64;
+        WsMask m;
+    } u;
+} WsHeader;
+
+enum {
+    WS_OPCODE_CONTINUATION = 0x0,
+    WS_OPCODE_TEXT_FRAME = 0x1,
+    WS_OPCODE_BINARY_FRAME = 0x2,
+    WS_OPCODE_CLOSE = 0x8,
+    WS_OPCODE_PING = 0x9,
+    WS_OPCODE_PONG = 0xA
+};
+
+void vncws_handshake_read(void *opaque);
+long vnc_client_write_ws(VncState *vs);
+long vnc_client_read_ws(VncState *vs);
+void vncws_process_handshake(VncState *vs, uint8_t *line, size_t size);
+void vncws_encode_frame(Buffer *output, const void *payload,
+            const size_t payload_size);
+int vncws_decode_frame(Buffer *input, uint8_t **payload,
+                               size_t *payload_size, size_t *frame_size);
+
+#endif /* __QEMU_UI_VNC_WS_H */
diff --git a/ui/vnc.c b/ui/vnc.c
index ddf01f1..ee08894 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -420,7 +420,6 @@ out_error:
 static int vnc_update_client(VncState *vs, int has_dirty);
 static int vnc_update_client_sync(VncState *vs, int has_dirty);
 static void vnc_disconnect_start(VncState *vs);
-static void vnc_disconnect_finish(VncState *vs);
 static void vnc_init_timer(VncDisplay *vd);
 static void vnc_remove_timer(VncDisplay *vd);
 
@@ -486,7 +485,7 @@ static int buffer_empty(Buffer *buffer)
     return buffer->offset == 0;
 }
 
-static uint8_t *buffer_end(Buffer *buffer)
+uint8_t *buffer_end(Buffer *buffer)
 {
     return buffer->buffer + buffer->offset;
 }
@@ -1023,7 +1022,7 @@ static void vnc_disconnect_start(VncState *vs)
     vs->csock = -1;
 }
 
-static void vnc_disconnect_finish(VncState *vs)
+void vnc_disconnect_finish(VncState *vs)
 {
     int i;
 
@@ -1034,6 +1033,10 @@ static void vnc_disconnect_finish(VncState *vs)
 
     buffer_free(&vs->input);
     buffer_free(&vs->output);
+#ifdef CONFIG_VNC_WS
+    buffer_free(&vs->ws_input);
+    buffer_free(&vs->ws_output);
+#endif /* CONFIG_VNC_WS */
 
     qobject_decref(vs->info);
 
@@ -1199,7 +1202,16 @@ static void vnc_client_write_locked(void *opaque)
         vnc_client_write_sasl(vs);
     } else
 #endif /* CONFIG_VNC_SASL */
-        vnc_client_write_plain(vs);
+    {
+#ifdef CONFIG_VNC_WS
+        if (vs->encode_ws) {
+            vnc_client_write_ws(vs);
+        } else
+#endif /* CONFIG_VNC_WS */
+        {
+            vnc_client_write_plain(vs);
+        }
+    }
 }
 
 void vnc_client_write(void *opaque)
@@ -1207,7 +1219,11 @@ void vnc_client_write(void *opaque)
     VncState *vs = opaque;
 
     vnc_lock_output(vs);
-    if (vs->output.offset) {
+    if (vs->output.offset
+#ifdef CONFIG_VNC_WS
+            || vs->ws_output.offset
+#endif
+            ) {
         vnc_client_write_locked(opaque);
     } else if (vs->csock != -1) {
         qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
@@ -1301,7 +1317,21 @@ void vnc_client_read(void *opaque)
         ret = vnc_client_read_sasl(vs);
     else
 #endif /* CONFIG_VNC_SASL */
+#ifdef CONFIG_VNC_WS
+        if (vs->encode_ws) {
+            ret = vnc_client_read_ws(vs);
+            if (ret == -1) {
+                vnc_disconnect_start(vs);
+                return;
+            } else if (ret == -2) {
+                vnc_client_error(vs);
+                return;
+            }
+        } else
+#endif /* CONFIG_VNC_WS */
+        {
         ret = vnc_client_read_plain(vs);
+        }
     if (!ret) {
         if (vs->csock == -1)
             vnc_disconnect_finish(vs);
@@ -1372,7 +1402,11 @@ void vnc_write_u8(VncState *vs, uint8_t value)
 void vnc_flush(VncState *vs)
 {
     vnc_lock_output(vs);
-    if (vs->csock != -1 && vs->output.offset) {
+    if (vs->csock != -1 && (vs->output.offset
+#ifdef CONFIG_VNC_WS
+                || vs->ws_output.offset
+#endif
+                )) {
         vnc_client_write_locked(vs);
     }
     vnc_unlock_output(vs);
@@ -2662,7 +2696,7 @@ static void vnc_remove_timer(VncDisplay *vd)
     }
 }
 
-static void vnc_connect(VncDisplay *vd, int csock, int skipauth)
+static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket)
 {
     VncState *vs = g_malloc0(sizeof(VncState));
     int i;
@@ -2689,13 +2723,34 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth)
     VNC_DEBUG("New client on socket %d\n", csock);
     dcl->idle = 0;
     socket_set_nonblock(vs->csock);
-    qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
+#ifdef CONFIG_VNC_WS
+    if (websocket) {
+        vs->websocket = 1;
+        qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read, NULL, vs);
+    } else
+#endif /* CONFIG_VNC_WS */
+    {
+        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
+    }
 
     vnc_client_cache_addr(vs);
     vnc_qmp_event(vs, QEVENT_VNC_CONNECTED);
     vnc_set_share_mode(vs, VNC_SHARE_MODE_CONNECTING);
 
     vs->vd = vd;
+
+#ifdef CONFIG_VNC_WS
+    if (!vs->websocket)
+#endif
+    {
+        vnc_init_state(vs);
+    }
+}
+
+void vnc_init_state(VncState *vs)
+{
+    VncDisplay *vd = vs->vd;
+
     vs->ds = vd->ds;
     vs->last_x = -1;
     vs->last_y = -1;
@@ -2727,21 +2782,41 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth)
     /* vs might be free()ed here */
 }
 
-static void vnc_listen_read(void *opaque)
+static void vnc_listen_read(void *opaque, bool websocket)
 {
     VncDisplay *vs = opaque;
     struct sockaddr_in addr;
     socklen_t addrlen = sizeof(addr);
+    int csock;
 
     /* Catch-up */
     vga_hw_update();
+#ifdef CONFIG_VNC_WS
+    if (websocket) {
+        csock = qemu_accept(vs->lwebsock, (struct sockaddr *)&addr, &addrlen);
+    } else
+#endif /* CONFIG_VNC_WS */
+    {
+        csock = qemu_accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
+    }
 
-    int csock = qemu_accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
     if (csock != -1) {
-        vnc_connect(vs, csock, 0);
+        vnc_connect(vs, csock, 0, websocket);
     }
 }
 
+static void vnc_listen_regular_read(void *opaque)
+{
+    vnc_listen_read(opaque, 0);
+}
+
+#ifdef CONFIG_VNC_WS
+static void vnc_listen_websocket_read(void *opaque)
+{
+    vnc_listen_read(opaque, 1);
+}
+#endif /* CONFIG_VNC_WS */
+
 void vnc_display_init(DisplayState *ds)
 {
     VncDisplay *vs = g_malloc0(sizeof(*vs));
@@ -2753,6 +2828,9 @@ void vnc_display_init(DisplayState *ds)
     vnc_display = vs;
 
     vs->lsock = -1;
+#ifdef CONFIG_VNC_WS
+    vs->lwebsock = -1;
+#endif
 
     vs->ds = ds;
     QTAILQ_INIT(&vs->clients);
@@ -2794,6 +2872,15 @@ static void vnc_display_close(DisplayState *ds)
         close(vs->lsock);
         vs->lsock = -1;
     }
+#ifdef CONFIG_VNC_WS
+    g_free(vs->ws_display);
+    vs->ws_display = NULL;
+    if (vs->lwebsock != -1) {
+        qemu_set_fd_handler2(vs->lwebsock, NULL, NULL, NULL, NULL);
+        close(vs->lwebsock);
+        vs->lwebsock = -1;
+    }
+#endif /* CONFIG_VNC_WS */
     vs->auth = VNC_AUTH_INVALID;
 #ifdef CONFIG_VNC_TLS
     vs->subauth = VNC_AUTH_INVALID;
@@ -2915,6 +3002,36 @@ void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
         } else if (strncmp(options, "sasl", 4) == 0) {
             sasl = 1; /* Require SASL auth */
 #endif
+#ifdef CONFIG_VNC_WS
+        } else if (strncmp(options, "websocket", 9) == 0) {
+            char *start, *end;
+            vs->websocket = 1;
+
+            /* Check for 'websocket=<port>' */
+            start = strchr(options, '=');
+            end = strchr(options, ',');
+            if (start && (!end || (start < end))) {
+                int len = end ? end-(start+1) : strlen(start+1);
+                if (len < 6) {
+                    /* extract the host specification from display */
+                    char  *host = NULL, *port = NULL, *host_end = NULL;
+                    port = g_strndup(start + 1, len);
+
+                    /* ipv6 hosts have colons */
+                    end = strchr(display, ',');
+                    host_end = g_strrstr_len(display, end - display, ":");
+
+                    if (host_end) {
+                        host = g_strndup(display, host_end - display + 1);
+                    } else {
+                        host = g_strndup(":", 1);
+                    }
+                    vs->ws_display = g_strconcat(host, port, NULL);
+                    g_free(host);
+                    g_free(port);
+                }
+            }
+#endif /* CONFIG_VNC_WS */
 #ifdef CONFIG_VNC_TLS
         } else if (strncmp(options, "tls", 3) == 0) {
             tls = 1; /* Require TLS */
@@ -3073,6 +3190,9 @@ void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
         /* connect to viewer */
         int csock;
         vs->lsock = -1;
+#ifdef CONFIG_VNC_WS
+        vs->lwebsock = -1;
+#endif
         if (strncmp(display, "unix:", 5) == 0) {
             csock = unix_connect(display+5, errp);
         } else {
@@ -3081,7 +3201,7 @@ void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
         if (csock < 0) {
             goto fail;
         }
-        vnc_connect(vs, csock, 0);
+        vnc_connect(vs, csock, 0, 0);
     } else {
         /* listen for connects */
         char *dpy;
@@ -3092,25 +3212,56 @@ void vnc_display_open(DisplayState *ds, const char *display, Error **errp)
         } else {
             vs->lsock = inet_listen(display, dpy, 256,
                                     SOCK_STREAM, 5900, errp);
-        }
-        if (vs->lsock < 0) {
-            g_free(dpy);
-            goto fail;
+            if (vs->lsock < 0) {
+                g_free(dpy);
+                goto fail;
+            }
+#ifdef CONFIG_VNC_WS
+            if (vs->websocket) {
+                if (vs->ws_display) {
+                    vs->lwebsock = inet_listen(vs->ws_display, NULL, 256,
+                        SOCK_STREAM, 0, errp);
+                } else {
+                    vs->lwebsock = inet_listen(vs->display, NULL, 256,
+                        SOCK_STREAM, 5700, errp);
+                }
+
+                if (vs->lwebsock < 0) {
+                    if (vs->lsock) {
+                        close(vs->lsock);
+                        vs->lsock = -1;
+                    }
+                    g_free(dpy);
+                    goto fail;
+                }
+            }
+#endif /* CONFIG_VNC_WS */
         }
         g_free(vs->display);
         vs->display = dpy;
-        qemu_set_fd_handler2(vs->lsock, NULL, vnc_listen_read, NULL, vs);
+        qemu_set_fd_handler2(vs->lsock, NULL,
+                vnc_listen_regular_read, NULL, vs);
+#ifdef CONFIG_VNC_WS
+        if (vs->websocket) {
+            qemu_set_fd_handler2(vs->lwebsock, NULL,
+                    vnc_listen_websocket_read, NULL, vs);
+        }
+#endif /* CONFIG_VNC_WS */
     }
     return;
 
 fail:
     g_free(vs->display);
     vs->display = NULL;
+#ifdef CONFIG_VNC_WS
+    g_free(vs->ws_display);
+    vs->ws_display = NULL;
+#endif /* CONFIG_VNC_WS */
 }
 
 void vnc_display_add_client(DisplayState *ds, int csock, int skipauth)
 {
     VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
 
-    vnc_connect(vs, csock, skipauth);
+    vnc_connect(vs, csock, skipauth, 0);
 }
diff --git a/ui/vnc.h b/ui/vnc.h
index 5059cbe..f93c89a 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -99,6 +99,9 @@ typedef struct VncDisplay VncDisplay;
 #ifdef CONFIG_VNC_SASL
 #include "vnc-auth-sasl.h"
 #endif
+#ifdef CONFIG_VNC_WS
+#include "vnc-ws.h"
+#endif
 
 struct VncRectStat
 {
@@ -142,6 +145,11 @@ struct VncDisplay
     QEMUTimer *timer;
     int timer_interval;
     int lsock;
+#ifdef CONFIG_VNC_WS
+    int lwebsock;
+    bool websocket;
+    char *ws_display;
+#endif
     DisplayState *ds;
     kbd_layout_t *kbd_layout;
     int lock_key_sync;
@@ -269,11 +277,19 @@ struct VncState
 #ifdef CONFIG_VNC_SASL
     VncStateSASL sasl;
 #endif
+#ifdef CONFIG_VNC_WS
+    bool encode_ws;
+    bool websocket;
+#endif
 
     QObject *info;
 
     Buffer output;
     Buffer input;
+#ifdef CONFIG_VNC_WS
+    Buffer ws_input;
+    Buffer ws_output;
+#endif
     /* current output mode information */
     VncWritePixels *write_pixels;
     PixelFormat client_pf;
@@ -493,6 +509,8 @@ void vnc_write_u16(VncState *vs, uint16_t value);
 void vnc_write_u8(VncState *vs, uint8_t value);
 void vnc_flush(VncState *vs);
 void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting);
+void vnc_disconnect_finish(VncState *vs);
+void vnc_init_state(VncState *vs);
 
 
 /* Buffer I/O functions */
@@ -511,6 +529,7 @@ void buffer_reset(Buffer *buffer);
 void buffer_free(Buffer *buffer);
 void buffer_append(Buffer *buffer, const void *data, size_t len);
 void buffer_advance(Buffer *buf, size_t len);
+uint8_t *buffer_end(Buffer *buffer);
 
 
 /* Misc helpers */
commit 32ed26808d4e59efb4a03290a4a85f5f8335f268
Author: Tim Hardeck <thardeck at suse.de>
Date:   Mon Jan 21 11:04:43 2013 +0100

    vnc: added buffer_advance function
    
    Following Anthony Liguori's Websocket implementation I have added the
    buffer_advance function to VNC and replaced all related buffer memmove
    operations with it.
    
    Signed-off-by: Tim Hardeck <thardeck at suse.de>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 8912b78..ddf01f1 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -510,6 +510,13 @@ void buffer_append(Buffer *buffer, const void *data, size_t len)
     buffer->offset += len;
 }
 
+void buffer_advance(Buffer *buf, size_t len)
+{
+    memmove(buf->buffer, buf->buffer + len,
+            (buf->offset - len));
+    buf->offset -= len;
+}
+
 static void vnc_desktop_resize(VncState *vs)
 {
     DisplayState *ds = vs->ds;
@@ -1166,8 +1173,7 @@ static long vnc_client_write_plain(VncState *vs)
     if (!ret)
         return 0;
 
-    memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret));
-    vs->output.offset -= ret;
+    buffer_advance(&vs->output, ret);
 
     if (vs->output.offset == 0) {
         qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
@@ -1313,8 +1319,7 @@ void vnc_client_read(void *opaque)
         }
 
         if (!ret) {
-            memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
-            vs->input.offset -= len;
+            buffer_advance(&vs->input, len);
         } else {
             vs->read_handler_expect = ret;
         }
diff --git a/ui/vnc.h b/ui/vnc.h
index 8b40f09..5059cbe 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -510,6 +510,7 @@ void buffer_reserve(Buffer *buffer, size_t len);
 void buffer_reset(Buffer *buffer);
 void buffer_free(Buffer *buffer);
 void buffer_append(Buffer *buffer, const void *data, size_t len);
+void buffer_advance(Buffer *buf, size_t len);
 
 
 /* Misc helpers */
commit 11e9235b1a88a98124fe005c93ade019d6a09c0b
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Tue Jan 15 00:08:06 2013 +0100

    virtio-s390-device: create a virtio-s390-bus during init.
    
    A virtio-s390-bus is created during the init. So one VirtIODevice can be
    connected on the virtio-s390-device through this bus.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index f78725f..b5d1f2b 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -503,6 +503,8 @@ static int s390_virtio_busdev_init(DeviceState *dev)
     VirtIOS390Device *_dev = (VirtIOS390Device *)dev;
     VirtIOS390DeviceClass *_info = VIRTIO_S390_DEVICE_GET_CLASS(dev);
 
+    virtio_s390_bus_new(&_dev->bus, _dev);
+
     return _info->init(_dev);
 }
 
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index ffc6f88..438b37f 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -96,6 +96,7 @@ struct VirtIOS390Device {
     virtio_net_conf net;
     VirtIOSCSIConf scsi;
     VirtIORNGConf rng;
+    VirtioBusState bus;
 };
 
 typedef struct VirtIOS390Bus {
commit ea35d4f1e9781a4b489d550e4bbc4568704f34bf
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Tue Jan 15 00:08:05 2013 +0100

    virtio-s390-bus: add virtio-s390-bus.
    
    This add the virtio-s390-bus which extends virtio-bus. So one VirtIODevice can
    be connected on this bus.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index bcb09f2..f78725f 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -32,6 +32,7 @@
 #include "sysemu/kvm.h"
 
 #include "hw/s390-virtio-bus.h"
+#include "hw/virtio-bus.h"
 
 /* #define DEBUG_S390 */
 
@@ -569,8 +570,36 @@ static const TypeInfo s390_virtio_bridge_info = {
     .class_init    = s390_virtio_bridge_class_init,
 };
 
+/* virtio-s390-bus */
+
+void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev)
+{
+    DeviceState *qdev = DEVICE(dev);
+    BusState *qbus;
+    qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_S390_BUS, qdev, NULL);
+    qbus = BUS(bus);
+    qbus->allow_hotplug = 0;
+}
+
+static void virtio_s390_bus_class_init(ObjectClass *klass, void *data)
+{
+    VirtioBusClass *k = VIRTIO_BUS_CLASS(klass);
+    BusClass *bus_class = BUS_CLASS(klass);
+    bus_class->max_dev = 1;
+    k->notify = virtio_s390_notify;
+    k->get_features = virtio_s390_get_features;
+}
+
+static const TypeInfo virtio_s390_bus_info = {
+    .name          = TYPE_VIRTIO_S390_BUS,
+    .parent        = TYPE_VIRTIO_BUS,
+    .instance_size = sizeof(VirtioS390BusState),
+    .class_init    = virtio_s390_bus_class_init,
+};
+
 static void s390_virtio_register_types(void)
 {
+    type_register_static(&virtio_s390_bus_info);
     type_register_static(&s390_virtio_bus_info);
     type_register_static(&virtio_s390_device_info);
     type_register_static(&s390_virtio_serial);
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index 23fedd5..ffc6f88 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -24,6 +24,7 @@
 #include "virtio-rng.h"
 #include "virtio-serial.h"
 #include "virtio-scsi.h"
+#include "virtio-bus.h"
 
 #define VIRTIO_DEV_OFFS_TYPE		0	/* 8 bits */
 #define VIRTIO_DEV_OFFS_NUM_VQ		1	/* 8 bits */
@@ -59,8 +60,24 @@
 #define S390_VIRTIO_BUS(obj) \
      OBJECT_CHECK(VirtIOS390Bus, (obj), TYPE_S390_VIRTIO_BUS)
 
+/* virtio-s390-bus */
+
+typedef struct VirtioBusState VirtioS390BusState;
+typedef struct VirtioBusClass VirtioS390BusClass;
+
+#define TYPE_VIRTIO_S390_BUS "virtio-s390-bus"
+#define VIRTIO_S390_BUS(obj) \
+        OBJECT_CHECK(VirtioS390BusState, (obj), TYPE_VIRTIO_S390_BUS)
+#define VIRTIO_S390_BUS_GET_CLASS(obj) \
+        OBJECT_GET_CLASS(VirtioS390BusClass, obj, TYPE_VIRTIO_S390_BUS)
+#define VIRTIO_S390_BUS_CLASS(klass) \
+        OBJECT_CLASS_CHECK(VirtioS390BusClass, klass, TYPE_VIRTIO_S390_BUS)
+
+
 typedef struct VirtIOS390Device VirtIOS390Device;
 
+void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev);
+
 typedef struct VirtIOS390DeviceClass {
     DeviceClass qdev;
     int (*init)(VirtIOS390Device *dev);
commit 085bccb72c280f36f651556ef5169f5faca31d87
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Tue Jan 15 00:08:04 2013 +0100

    virtio-pci: refactor virtio-pci device.
    
    Create the virtio-pci device which is abstract. This transport device will
    create a virtio-pci-bus, so one VirtIODevice can be connected.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 904a7e1..9abbcdf 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -1312,6 +1312,121 @@ static const TypeInfo virtio_scsi_info = {
     .class_init    = virtio_scsi_class_init,
 };
 
+/*
+ * virtio-pci: This is the PCIDevice which has a virtio-pci-bus.
+ */
+
+/* This is called by virtio-bus just after the device is plugged. */
+static void virtio_pci_device_plugged(DeviceState *d)
+{
+    VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
+    VirtioBusState *bus = &proxy->bus;
+    uint8_t *config;
+    uint32_t size;
+
+    proxy->vdev = bus->vdev;
+
+    config = proxy->pci_dev.config;
+    if (proxy->class_code) {
+        pci_config_set_class(config, proxy->class_code);
+    }
+    pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID,
+                 pci_get_word(config + PCI_VENDOR_ID));
+    pci_set_word(config + PCI_SUBSYSTEM_ID, virtio_bus_get_vdev_id(bus));
+    config[PCI_INTERRUPT_PIN] = 1;
+
+    if (proxy->nvectors &&
+        msix_init_exclusive_bar(&proxy->pci_dev, proxy->nvectors, 1)) {
+        proxy->nvectors = 0;
+    }
+
+    proxy->pci_dev.config_write = virtio_write_config;
+
+    size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev)
+         + virtio_bus_get_vdev_config_len(bus);
+    if (size & (size - 1)) {
+        size = 1 << qemu_fls(size);
+    }
+
+    memory_region_init_io(&proxy->bar, &virtio_pci_config_ops, proxy,
+                          "virtio-pci", size);
+    pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO,
+                     &proxy->bar);
+
+    if (!kvm_has_many_ioeventfds()) {
+        proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
+    }
+
+    proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
+    proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
+    proxy->host_features = virtio_bus_get_vdev_features(bus,
+                                                      proxy->host_features);
+}
+
+/* This is called by virtio-bus just before the device is unplugged. */
+static void virtio_pci_device_unplug(DeviceState *d)
+{
+    VirtIOPCIProxy *dev = VIRTIO_PCI(d);
+    virtio_pci_stop_ioeventfd(dev);
+}
+
+static int virtio_pci_init(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *dev = VIRTIO_PCI(pci_dev);
+    VirtioPCIClass *k = VIRTIO_PCI_GET_CLASS(pci_dev);
+    virtio_pci_bus_new(&dev->bus, dev);
+    if (k->init != NULL) {
+        return k->init(dev);
+    }
+    return 0;
+}
+
+static void virtio_pci_exit(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
+    VirtioBusState *bus = VIRTIO_BUS(&proxy->bus);
+    BusState *qbus = BUS(&proxy->bus);
+    virtio_bus_destroy_device(bus);
+    qbus_free(qbus);
+    virtio_exit_pci(pci_dev);
+}
+
+/*
+ * This will be renamed virtio_pci_reset at the end of the series.
+ * virtio_pci_reset is still in use at this moment.
+ */
+static void virtio_pci_rst(DeviceState *qdev)
+{
+    VirtIOPCIProxy *proxy = VIRTIO_PCI(qdev);
+    VirtioBusState *bus = VIRTIO_BUS(&proxy->bus);
+    virtio_pci_stop_ioeventfd(proxy);
+    virtio_bus_reset(bus);
+    msix_unuse_all_vectors(&proxy->pci_dev);
+    proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
+}
+
+static void virtio_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = virtio_pci_init;
+    k->exit = virtio_pci_exit;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->revision = VIRTIO_PCI_ABI_VERSION;
+    k->class_id = PCI_CLASS_OTHERS;
+    dc->reset = virtio_pci_rst;
+}
+
+static const TypeInfo virtio_pci_info = {
+    .name          = TYPE_VIRTIO_PCI,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(VirtIOPCIProxy),
+    .class_init    = virtio_pci_class_init,
+    .class_size    = sizeof(VirtioPCIClass),
+    .abstract      = true,
+};
+
 /* virtio-pci-bus */
 
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
@@ -1338,6 +1453,8 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
     k->set_host_notifier = virtio_pci_set_host_notifier;
     k->set_guest_notifiers = virtio_pci_set_guest_notifiers;
     k->vmstate_change = virtio_pci_vmstate_change;
+    k->device_plugged = virtio_pci_device_plugged;
+    k->device_unplug = virtio_pci_device_unplug;
 }
 
 static const TypeInfo virtio_pci_bus_info = {
@@ -1356,6 +1473,7 @@ static void virtio_pci_register_types(void)
     type_register_static(&virtio_scsi_info);
     type_register_static(&virtio_rng_info);
     type_register_static(&virtio_pci_bus_info);
+    type_register_static(&virtio_pci_info);
 }
 
 type_init(virtio_pci_register_types)
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index d11e622..d24957c 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -23,6 +23,8 @@
 #include "virtio-scsi.h"
 #include "virtio-bus.h"
 
+typedef struct VirtIOPCIProxy VirtIOPCIProxy;
+
 /* virtio-pci-bus */
 
 typedef struct VirtioBusState VirtioPCIBusState;
@@ -47,7 +49,23 @@ typedef struct {
     unsigned int users;
 } VirtIOIRQFD;
 
-typedef struct {
+/*
+ * virtio-pci: This is the PCIDevice which has a virtio-pci-bus.
+ */
+#define TYPE_VIRTIO_PCI "virtio-pci"
+#define VIRTIO_PCI_GET_CLASS(obj) \
+        OBJECT_GET_CLASS(VirtioPCIClass, obj, TYPE_VIRTIO_PCI)
+#define VIRTIO_PCI_CLASS(klass) \
+        OBJECT_CLASS_CHECK(VirtioPCIClass, klass, TYPE_VIRTIO_PCI)
+#define VIRTIO_PCI(obj) \
+        OBJECT_CHECK(VirtIOPCIProxy, (obj), TYPE_VIRTIO_PCI)
+
+typedef struct VirtioPCIClass {
+    PCIDeviceClass parent_class;
+    int (*init)(VirtIOPCIProxy *vpci_dev);
+} VirtioPCIClass;
+
+struct VirtIOPCIProxy {
     PCIDevice pci_dev;
     VirtIODevice *vdev;
     MemoryRegion bar;
@@ -68,7 +86,8 @@ typedef struct {
     bool ioeventfd_started;
     VirtIOIRQFD *vector_irqfd;
     int nvqs_with_notifiers;
-} VirtIOPCIProxy;
+    VirtioBusState bus;
+};
 
 void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
 void virtio_pci_reset(DeviceState *d);
commit 0a2acf5eb3237350e84693b9b37eced5080a1fef
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Tue Jan 15 00:08:03 2013 +0100

    virtio-pci-bus: introduce virtio-pci-bus.
    
    Introduce virtio-pci-bus, which extends virtio-bus. It is used with virtio-pci
    transport device.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 212acd8..904a7e1 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -31,6 +31,7 @@
 #include "sysemu/blockdev.h"
 #include "virtio-pci.h"
 #include "qemu/range.h"
+#include "virtio-bus.h"
 
 /* from Linux's linux/virtio_pci.h */
 
@@ -1311,6 +1312,41 @@ static const TypeInfo virtio_scsi_info = {
     .class_init    = virtio_scsi_class_init,
 };
 
+/* virtio-pci-bus */
+
+void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
+{
+    DeviceState *qdev = DEVICE(dev);
+    BusState *qbus;
+    qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_PCI_BUS, qdev, NULL);
+    qbus = BUS(bus);
+    qbus->allow_hotplug = 0;
+}
+
+static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
+{
+    BusClass *bus_class = BUS_CLASS(klass);
+    VirtioBusClass *k = VIRTIO_BUS_CLASS(klass);
+    bus_class->max_dev = 1;
+    k->notify = virtio_pci_notify;
+    k->save_config = virtio_pci_save_config;
+    k->load_config = virtio_pci_load_config;
+    k->save_queue = virtio_pci_save_queue;
+    k->load_queue = virtio_pci_load_queue;
+    k->get_features = virtio_pci_get_features;
+    k->query_guest_notifiers = virtio_pci_query_guest_notifiers;
+    k->set_host_notifier = virtio_pci_set_host_notifier;
+    k->set_guest_notifiers = virtio_pci_set_guest_notifiers;
+    k->vmstate_change = virtio_pci_vmstate_change;
+}
+
+static const TypeInfo virtio_pci_bus_info = {
+    .name          = TYPE_VIRTIO_PCI_BUS,
+    .parent        = TYPE_VIRTIO_BUS,
+    .instance_size = sizeof(VirtioPCIBusState),
+    .class_init    = virtio_pci_bus_class_init,
+};
+
 static void virtio_pci_register_types(void)
 {
     type_register_static(&virtio_blk_info);
@@ -1319,6 +1355,7 @@ static void virtio_pci_register_types(void)
     type_register_static(&virtio_balloon_info);
     type_register_static(&virtio_scsi_info);
     type_register_static(&virtio_rng_info);
+    type_register_static(&virtio_pci_bus_info);
 }
 
 type_init(virtio_pci_register_types)
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index 917b465..d11e622 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -21,6 +21,20 @@
 #include "virtio-rng.h"
 #include "virtio-serial.h"
 #include "virtio-scsi.h"
+#include "virtio-bus.h"
+
+/* virtio-pci-bus */
+
+typedef struct VirtioBusState VirtioPCIBusState;
+typedef struct VirtioBusClass VirtioPCIBusClass;
+
+#define TYPE_VIRTIO_PCI_BUS "virtio-pci-bus"
+#define VIRTIO_PCI_BUS(obj) \
+        OBJECT_CHECK(VirtioPCIBusState, (obj), TYPE_VIRTIO_PCI_BUS)
+#define VIRTIO_PCI_BUS_GET_CLASS(obj) \
+        OBJECT_GET_CLASS(VirtioPCIBusClass, obj, TYPE_VIRTIO_PCI_BUS)
+#define VIRTIO_PCI_BUS_CLASS(klass) \
+        OBJECT_CLASS_CHECK(VirtioPCIBusClass, klass, TYPE_VIRTIO_PCI_BUS)
 
 /* Performance improves when virtqueue kick processing is decoupled from the
  * vcpu thread using ioeventfd for some devices. */
@@ -58,6 +72,7 @@ typedef struct {
 
 void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
 void virtio_pci_reset(DeviceState *d);
+void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev);
 
 /* Virtio ABI version, if we increment this, we break the guest driver. */
 #define VIRTIO_PCI_ABI_VERSION          0
commit 8e05db9234050cb3f0ffb765608dd8b176334ae1
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Tue Jan 15 00:08:02 2013 +0100

    virtio-device: refactor virtio-device.
    
    Create the virtio-device which is abstract. All the virtio-device can extend
    this class. It also add some functions to virtio-bus.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-bus.c b/hw/virtio-bus.c
index b8f656e..6045d8a 100644
--- a/hw/virtio-bus.c
+++ b/hw/virtio-bus.c
@@ -113,6 +113,41 @@ size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus)
     return bus->vdev->config_len;
 }
 
+/* Get the features of the plugged device. */
+uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus,
+                                    uint32_t requested_features)
+{
+    VirtioDeviceClass *k;
+    assert(bus->vdev != NULL);
+    k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+    assert(k->get_features != NULL);
+    return k->get_features(bus->vdev, requested_features);
+}
+
+/* Get bad features of the plugged device. */
+uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus)
+{
+    VirtioDeviceClass *k;
+    assert(bus->vdev != NULL);
+    k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+    if (k->bad_features != NULL) {
+        return k->bad_features(bus->vdev);
+    } else {
+        return 0;
+    }
+}
+
+/* Get config of the plugged device. */
+void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config)
+{
+    VirtioDeviceClass *k;
+    assert(bus->vdev != NULL);
+    k = VIRTIO_DEVICE_GET_CLASS(bus->vdev);
+    if (k->get_config != NULL) {
+        k->get_config(bus->vdev, config);
+    }
+}
+
 static const TypeInfo virtio_bus_info = {
     .name = TYPE_VIRTIO_BUS,
     .parent = TYPE_BUS,
diff --git a/hw/virtio-bus.h b/hw/virtio-bus.h
index f378897..7584a0e 100644
--- a/hw/virtio-bus.h
+++ b/hw/virtio-bus.h
@@ -83,5 +83,12 @@ void virtio_bus_destroy_device(VirtioBusState *bus);
 uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus);
 /* Get the config_len field of the plugged device. */
 size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus);
+/* Get the features of the plugged device. */
+uint32_t virtio_bus_get_vdev_features(VirtioBusState *bus,
+                                    uint32_t requested_features);
+/* Get bad features of the plugged device. */
+uint32_t virtio_bus_get_vdev_bad_features(VirtioBusState *bus);
+/* Get config of the plugged device. */
+void virtio_bus_get_vdev_config(VirtioBusState *bus, uint8_t *config);
 
 #endif /* VIRTIO_BUS_H */
diff --git a/hw/virtio.c b/hw/virtio.c
index 77b53a9..ca170c3 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -17,6 +17,7 @@
 #include "qemu/error-report.h"
 #include "virtio.h"
 #include "qemu/atomic.h"
+#include "virtio-bus.h"
 
 /* The alignment to use between consumer and producer parts of vring.
  * x86 pagesize again. */
@@ -875,11 +876,16 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
     return 0;
 }
 
-void virtio_cleanup(VirtIODevice *vdev)
+void virtio_common_cleanup(VirtIODevice *vdev)
 {
     qemu_del_vm_change_state_handler(vdev->vmstate);
     g_free(vdev->config);
     g_free(vdev->vq);
+}
+
+void virtio_cleanup(VirtIODevice *vdev)
+{
+    virtio_common_cleanup(vdev);
     g_free(vdev);
 }
 
@@ -902,14 +908,10 @@ static void virtio_vmstate_change(void *opaque, int running, RunState state)
     }
 }
 
-VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
-                                 size_t config_size, size_t struct_size)
+void virtio_init(VirtIODevice *vdev, const char *name,
+                 uint16_t device_id, size_t config_size)
 {
-    VirtIODevice *vdev;
     int i;
-
-    vdev = g_malloc0(struct_size);
-
     vdev->device_id = device_id;
     vdev->status = 0;
     vdev->isr = 0;
@@ -917,20 +919,28 @@ VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
     vdev->config_vector = VIRTIO_NO_VECTOR;
     vdev->vq = g_malloc0(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX);
     vdev->vm_running = runstate_is_running();
-    for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
+    for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
         vdev->vq[i].vector = VIRTIO_NO_VECTOR;
         vdev->vq[i].vdev = vdev;
     }
 
     vdev->name = name;
     vdev->config_len = config_size;
-    if (vdev->config_len)
+    if (vdev->config_len) {
         vdev->config = g_malloc0(config_size);
-    else
+    } else {
         vdev->config = NULL;
+    }
+    vdev->vmstate = qemu_add_vm_change_state_handler(virtio_vmstate_change,
+                                                     vdev);
+}
 
-    vdev->vmstate = qemu_add_vm_change_state_handler(virtio_vmstate_change, vdev);
-
+VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
+                                 size_t config_size, size_t struct_size)
+{
+    VirtIODevice *vdev;
+    vdev = g_malloc0(struct_size);
+    virtio_init(vdev, name, device_id, config_size);
     return vdev;
 }
 
@@ -1056,3 +1066,39 @@ EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq)
 {
     return &vq->host_notifier;
 }
+
+static int virtio_device_init(DeviceState *qdev)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+    VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(qdev);
+    assert(k->init != NULL);
+    if (k->init(vdev) < 0) {
+        return -1;
+    }
+    virtio_bus_plug_device(vdev);
+    return 0;
+}
+
+static void virtio_device_class_init(ObjectClass *klass, void *data)
+{
+    /* Set the default value here. */
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    dc->init = virtio_device_init;
+    dc->bus_type = TYPE_VIRTIO_BUS;
+}
+
+static const TypeInfo virtio_device_info = {
+    .name = TYPE_VIRTIO_DEVICE,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(VirtIODevice),
+    .class_init = virtio_device_class_init,
+    .abstract = true,
+    .class_size = sizeof(VirtioDeviceClass),
+};
+
+static void virtio_register_types(void)
+{
+    type_register_static(&virtio_device_info);
+}
+
+type_init(virtio_register_types)
diff --git a/hw/virtio.h b/hw/virtio.h
index b9f1873..9cc7b85 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -108,8 +108,17 @@ typedef struct {
 
 #define VIRTIO_NO_VECTOR 0xffff
 
+#define TYPE_VIRTIO_DEVICE "virtio-device"
+#define VIRTIO_DEVICE_GET_CLASS(obj) \
+        OBJECT_GET_CLASS(VirtioDeviceClass, obj, TYPE_VIRTIO_DEVICE)
+#define VIRTIO_DEVICE_CLASS(klass) \
+        OBJECT_CLASS_CHECK(VirtioDeviceClass, klass, TYPE_VIRTIO_DEVICE)
+#define VIRTIO_DEVICE(obj) \
+        OBJECT_CHECK(VirtIODevice, (obj), TYPE_VIRTIO_DEVICE)
+
 struct VirtIODevice
 {
+    DeviceState parent_obj;
     const char *name;
     uint8_t status;
     uint8_t isr;
@@ -119,6 +128,10 @@ struct VirtIODevice
     void *config;
     uint16_t config_vector;
     int nvectors;
+    /*
+     * Function pointers will be removed at the end of the series as they are in
+     * VirtioDeviceClass.
+     */
     uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features);
     uint32_t (*bad_features)(VirtIODevice *vdev);
     void (*set_features)(VirtIODevice *vdev, uint32_t val);
@@ -147,6 +160,23 @@ struct VirtIODevice
     VMChangeStateEntry *vmstate;
 };
 
+typedef struct VirtioDeviceClass {
+    /* This is what a VirtioDevice must implement */
+    DeviceClass parent;
+    int (*init)(VirtIODevice *vdev);
+    uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features);
+    uint32_t (*bad_features)(VirtIODevice *vdev);
+    void (*set_features)(VirtIODevice *vdev, uint32_t val);
+    void (*get_config)(VirtIODevice *vdev, uint8_t *config);
+    void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
+    void (*reset)(VirtIODevice *vdev);
+    void (*set_status)(VirtIODevice *vdev, uint8_t val);
+} VirtioDeviceClass;
+
+void virtio_init(VirtIODevice *vdev, const char *name,
+                         uint16_t device_id, size_t config_size);
+void virtio_common_cleanup(VirtIODevice *vdev);
+
 VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
                             void (*handle_output)(VirtIODevice *,
                                                   VirtQueue *));
commit ff8eca5536edd3f84bc87277e158e4db11dadf82
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Tue Jan 15 00:08:01 2013 +0100

    virtio-bus: introduce virtio-bus
    
    Introduce virtio-bus. Refactored transport device will create a bus which
    extends virtio-bus.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 74b07a7..23ac249 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -8,6 +8,7 @@ common-obj-y += loader.o
 common-obj-$(CONFIG_VIRTIO) += virtio-console.o
 common-obj-$(CONFIG_VIRTIO) += virtio-rng.o
 common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
+common-obj-$(CONFIG_VIRTIO) += virtio-bus.o
 common-obj-y += fw_cfg.o
 common-obj-$(CONFIG_PCI) += pci_bridge_dev.o
 common-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
diff --git a/hw/virtio-bus.c b/hw/virtio-bus.c
new file mode 100644
index 0000000..b8f656e
--- /dev/null
+++ b/hw/virtio-bus.c
@@ -0,0 +1,129 @@
+/*
+ * VirtioBus
+ *
+ *  Copyright (C) 2012 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info at greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad at greensocs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "hw.h"
+#include "qemu/error-report.h"
+#include "qdev.h"
+#include "virtio-bus.h"
+#include "virtio.h"
+
+/* #define DEBUG_VIRTIO_BUS */
+
+#ifdef DEBUG_VIRTIO_BUS
+#define DPRINTF(fmt, ...) \
+do { printf("virtio_bus: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do { } while (0)
+#endif
+
+/* Plug the VirtIODevice */
+int virtio_bus_plug_device(VirtIODevice *vdev)
+{
+    DeviceState *qdev = DEVICE(vdev);
+    BusState *qbus = BUS(qdev_get_parent_bus(qdev));
+    VirtioBusState *bus = VIRTIO_BUS(qbus);
+    VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
+    DPRINTF("%s: plug device.\n", qbus->name);
+
+    bus->vdev = vdev;
+
+    /*
+     * The lines below will disappear when we drop VirtIOBindings, at the end
+     * of the series.
+     */
+    bus->bindings.notify = klass->notify;
+    bus->bindings.save_config = klass->save_config;
+    bus->bindings.save_queue = klass->save_queue;
+    bus->bindings.load_config = klass->load_config;
+    bus->bindings.load_queue = klass->load_queue;
+    bus->bindings.load_done = klass->load_done;
+    bus->bindings.get_features = klass->get_features;
+    bus->bindings.query_guest_notifiers = klass->query_guest_notifiers;
+    bus->bindings.set_guest_notifiers = klass->set_guest_notifiers;
+    bus->bindings.set_host_notifier = klass->set_host_notifier;
+    bus->bindings.vmstate_change = klass->vmstate_change;
+    virtio_bind_device(bus->vdev, &bus->bindings, qbus->parent);
+
+    if (klass->device_plugged != NULL) {
+        klass->device_plugged(qbus->parent);
+    }
+
+    return 0;
+}
+
+/* Reset the virtio_bus */
+void virtio_bus_reset(VirtioBusState *bus)
+{
+    DPRINTF("%s: reset device.\n", qbus->name);
+    if (bus->vdev != NULL) {
+        virtio_reset(bus->vdev);
+    }
+}
+
+/* Destroy the VirtIODevice */
+void virtio_bus_destroy_device(VirtioBusState *bus)
+{
+    DeviceState *qdev;
+    BusState *qbus = BUS(bus);
+    VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
+    DPRINTF("%s: remove device.\n", qbus->name);
+
+    if (bus->vdev != NULL) {
+        if (klass->device_unplug != NULL) {
+            klass->device_unplug(qbus->parent);
+        }
+        qdev = DEVICE(bus->vdev);
+        qdev_free(qdev);
+        bus->vdev = NULL;
+    }
+}
+
+/* Get the device id of the plugged device. */
+uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus)
+{
+    assert(bus->vdev != NULL);
+    return bus->vdev->device_id;
+}
+
+/* Get the config_len field of the plugged device. */
+size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus)
+{
+    assert(bus->vdev != NULL);
+    return bus->vdev->config_len;
+}
+
+static const TypeInfo virtio_bus_info = {
+    .name = TYPE_VIRTIO_BUS,
+    .parent = TYPE_BUS,
+    .instance_size = sizeof(VirtioBusState),
+    .abstract = true,
+    .class_size = sizeof(VirtioBusClass),
+};
+
+static void virtio_register_types(void)
+{
+    type_register_static(&virtio_bus_info);
+}
+
+type_init(virtio_register_types)
diff --git a/hw/virtio-bus.h b/hw/virtio-bus.h
new file mode 100644
index 0000000..f378897
--- /dev/null
+++ b/hw/virtio-bus.h
@@ -0,0 +1,87 @@
+/*
+ * VirtioBus
+ *
+ *  Copyright (C) 2012 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info at greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad at greensocs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef VIRTIO_BUS_H
+#define VIRTIO_BUS_H
+
+#include "qdev.h"
+#include "sysemu/sysemu.h"
+#include "virtio.h"
+
+#define TYPE_VIRTIO_BUS "virtio-bus"
+#define VIRTIO_BUS_GET_CLASS(obj) \
+        OBJECT_GET_CLASS(VirtioBusClass, obj, TYPE_VIRTIO_BUS)
+#define VIRTIO_BUS_CLASS(klass) \
+        OBJECT_CLASS_CHECK(VirtioBusClass, klass, TYPE_VIRTIO_BUS)
+#define VIRTIO_BUS(obj) OBJECT_CHECK(VirtioBusState, (obj), TYPE_VIRTIO_BUS)
+
+typedef struct VirtioBusState VirtioBusState;
+
+typedef struct VirtioBusClass {
+    /* This is what a VirtioBus must implement */
+    BusClass parent;
+    void (*notify)(DeviceState *d, uint16_t vector);
+    void (*save_config)(DeviceState *d, QEMUFile *f);
+    void (*save_queue)(DeviceState *d, int n, QEMUFile *f);
+    int (*load_config)(DeviceState *d, QEMUFile *f);
+    int (*load_queue)(DeviceState *d, int n, QEMUFile *f);
+    int (*load_done)(DeviceState *d, QEMUFile *f);
+    unsigned (*get_features)(DeviceState *d);
+    bool (*query_guest_notifiers)(DeviceState *d);
+    int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assign);
+    int (*set_host_notifier)(DeviceState *d, int n, bool assigned);
+    void (*vmstate_change)(DeviceState *d, bool running);
+    /*
+     * transport independent init function.
+     * This is called by virtio-bus just after the device is plugged.
+     */
+    void (*device_plugged)(DeviceState *d);
+    /*
+     * transport independent exit function.
+     * This is called by virtio-bus just before the device is unplugged.
+     */
+    void (*device_unplug)(DeviceState *d);
+} VirtioBusClass;
+
+struct VirtioBusState {
+    BusState parent_obj;
+    /*
+     * Only one VirtIODevice can be plugged on the bus.
+     */
+    VirtIODevice *vdev;
+    /*
+     * This will be removed at the end of the series.
+     */
+    VirtIOBindings bindings;
+};
+
+int virtio_bus_plug_device(VirtIODevice *vdev);
+void virtio_bus_reset(VirtioBusState *bus);
+void virtio_bus_destroy_device(VirtioBusState *bus);
+/* Get the device id of the plugged device. */
+uint16_t virtio_bus_get_vdev_id(VirtioBusState *bus);
+/* Get the config_len field of the plugged device. */
+size_t virtio_bus_get_vdev_config_len(VirtioBusState *bus);
+
+#endif /* VIRTIO_BUS_H */
commit 1395af6f76e9f0e145a235a71e3578385d82ece5
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Tue Jan 15 00:08:00 2013 +0100

    qdev: add a maximum device allowed field for the bus.
    
    Add a max_dev field to BusClass to specify the maximum amount of devices allowed
    on the bus (has no effect if max_dev=0)
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev-core.h b/hw/qdev-core.h
index 731aadd..d1b8e37 100644
--- a/hw/qdev-core.h
+++ b/hw/qdev-core.h
@@ -145,6 +145,8 @@ struct BusClass {
      */
     char *(*get_fw_dev_path)(DeviceState *dev);
     int (*reset)(BusState *bus);
+    /* maximum devices allowed on the bus, 0: no limit. */
+    int max_dev;
 };
 
 typedef struct BusChild {
diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
index 1db5ee0..4e2a92b 100644
--- a/hw/qdev-monitor.c
+++ b/hw/qdev-monitor.c
@@ -283,6 +283,7 @@ static DeviceState *qbus_find_dev(BusState *bus, char *elem)
 static BusState *qbus_find_recursive(BusState *bus, const char *name,
                                      const char *bus_typename)
 {
+    BusClass *bus_class = BUS_GET_CLASS(bus);
     BusChild *kid;
     BusState *child, *ret;
     int match = 1;
@@ -293,6 +294,17 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
     if (bus_typename && !object_dynamic_cast(OBJECT(bus), bus_typename)) {
         match = 0;
     }
+    if ((bus_class->max_dev != 0) && (bus_class->max_dev <= bus->max_index)) {
+        if (name != NULL) {
+            /* bus was explicitly specified: return an error. */
+            qerror_report(ERROR_CLASS_GENERIC_ERROR, "Bus '%s' is full",
+                          bus->name);
+            return NULL;
+        } else {
+            /* bus was not specified: try to find another one. */
+            match = 0;
+        }
+    }
     if (match) {
         return bus;
     }
commit 016c7182315b1f842ac351fae86041d2c8fe4596
Merge: e0f0183 6522773
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jan 21 13:22:43 2013 -0600

    Merge remote-tracking branch 'quintela/thread.next' into staging
    
    # By Juan Quintela (7) and Paolo Bonzini (6)
    # Via Juan Quintela
    * quintela/thread.next:
      migration: remove argument to qemu_savevm_state_cancel
      migration: Only go to the iterate stage if there is anything to send
      migration: unfold rest of migrate_fd_put_ready() into thread
      migration: move exit condition to migration thread
      migration: Add buffered_flush error handling
      migration: move beginning stage to the migration thread
      qemu-file: Only set last_error if it is not already set
      migration: fix off-by-one in buffered_rate_limit
      migration: remove double call to migrate_fd_close
      migration: make function static
      use XFER_LIMIT_RATIO consistently
      Protect migration_bitmap_sync() with the ramlist lock
      Unlock ramlist lock also in error case

commit e0f01837e104517c7c511c79bb93c8792b7263e5
Merge: f2bdbd5 09a021f
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jan 21 07:32:22 2013 -0600

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    # By Stefan Weil (2) and others
    # Via Stefan Hajnoczi
    * stefanha/trivial-patches:
      hw/tpci200: Fix compiler warning (redefined symbol with MinGW)
      configure: silence pkg-config's check for curses
      acpitable: open the data file in binary mode
      hw: Spelling fix in log message

commit f2bdbd5bb4b7869ea48845d5a92979290df6f195
Merge: 56a8810 3588185
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jan 21 07:32:14 2013 -0600

    Merge remote-tracking branch 'kraxel/seabios-1.7.2' into staging
    
    # By Gerd Hoffmann
    # Via Gerd Hoffmann
    * kraxel/seabios-1.7.2:
      seabios: update to 1.7.2 release

commit 56a8810dd6686a999e47afa5c1870c66485ef1c6
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Jan 20 03:26:12 2013 +0100

    target-microblaze: Drop unused cpu_mb_close() prototype
    
    Such a function never existed.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 4de2226..5621068 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -274,7 +274,6 @@ struct CPUMBState {
 
 MicroBlazeCPU *cpu_mb_init(const char *cpu_model);
 int cpu_mb_exec(CPUMBState *s);
-void cpu_mb_close(CPUMBState *s);
 void do_interrupt(CPUMBState *env);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
commit a42a56c5deeedebe650469640ebe77d80e1eefb5
Author: Andreas Färber <afaerber at suse.de>
Date:   Sun Jan 20 03:20:58 2013 +0100

    target-cris: Drop unused cpu_cris_close() prototype
    
    Such a function never existed.
    
    Signed-off-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 63e6234..257cb52 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -175,7 +175,6 @@ typedef struct CPUCRISState {
 
 CRISCPU *cpu_cris_init(const char *cpu_model);
 int cpu_cris_exec(CPUCRISState *s);
-void cpu_cris_close(CPUCRISState *s);
 void do_interrupt(CPUCRISState *env);
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
commit 09a021fb7ceb7255ab106999d7b38ffd92c3bdd6
Author: Stefan Weil <sw at weilnetz.de>
Date:   Mon Jan 21 07:49:51 2013 +0100

    hw/tpci200: Fix compiler warning (redefined symbol with MinGW)
    
    STATUS_TIMEOUT is defined in winnt.h:
    
      CC    hw/tpci200.o
    hw/tpci200.c:34:0:
     warning: "STATUS_TIMEOUT" redefined [enabled by default]
    /usr/lib/gcc/x86_64-w64-mingw32/4.6/../../../../x86_64-w64-mingw32/include/winnt.h:1036:0:
     note: this is the location of the previous definition
    
    Use STATUS_TIME instead of STATUS_TIMEOUT as suggested by Alberto Garcia.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/tpci200.c b/hw/tpci200.c
index e082bca..a4823fb 100644
--- a/hw/tpci200.c
+++ b/hw/tpci200.c
@@ -31,7 +31,7 @@
 #define IP_INT_SPACE_ADDR_MASK 0x3F
 
 #define STATUS_INT(IP, INTNO) BIT((IP) * 2 + (INTNO))
-#define STATUS_TIMEOUT(IP)    BIT((IP) + 12)
+#define STATUS_TIME(IP)       BIT((IP) + 12)
 #define STATUS_ERR_ANY        0xF00
 
 #define CTRL_CLKRATE          BIT(0)
@@ -279,9 +279,9 @@ static void tpci200_write_las0(void *opaque, hwaddr addr, uint64_t val,
                     }
                 }
 
-                if (val & STATUS_TIMEOUT(i)) {
+                if (val & STATUS_TIME(i)) {
                     DPRINTF("Clear IP %c timeout\n", 'A' + i);
-                    s->status &= ~STATUS_TIMEOUT(i);
+                    s->status &= ~STATUS_TIME(i);
                 }
             }
 
commit acf15c8949f125a4d4f958a5134f8eeece1f99f5
Author: Vadim Evard <v.e.evard at gmail.com>
Date:   Fri Jan 18 17:48:04 2013 +0400

    configure: silence pkg-config's check for curses
    
    Signed-off-by: Vadim Evard <v.e.evard at gmail.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/configure b/configure
index 4ebb60d..6211db9 100755
--- a/configure
+++ b/configure
@@ -2039,7 +2039,7 @@ fi
 if test "$mingw32" = "yes" ; then
     curses_list="-lpdcurses"
 else
-    curses_list="-lncurses:-lcurses:$($pkg_config --libs ncurses)"
+    curses_list="-lncurses:-lcurses:$($pkg_config --libs ncurses 2>/dev/null)"
 fi
 
 if test "$curses" != "no" ; then
commit 5facfb4934221cac2c267e529d7ebab165103bc9
Author: Michael Tokarev <mjt at tls.msk.ru>
Date:   Thu Jan 17 14:53:52 2013 +0400

    acpitable: open the data file in binary mode
    
    -acpitable {file|data}=file reads the content of file, but it is
    in binary form, so the file should be opened usin O_BINARY flag.
    On *nix it is a no-op, but on windows and other weird platform
    it is really needed.
    
    Signed-off-by: Michael Tokarev <mjt at tls.msk.ru>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/acpi.c b/hw/acpi.c
index 97617c4..8c9dcc5 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -104,7 +104,7 @@ int acpi_table_add(const char *t)
     /* now read in the data files, reallocating buffer as needed */
 
     for (f = strtok(buf, ":"); f; f = strtok(NULL, ":")) {
-        int fd = open(f, O_RDONLY);
+        int fd = open(f, O_RDONLY | O_BINARY);
 
         if (fd < 0) {
             fprintf(stderr, "can't open file %s: %s\n", f, strerror(errno));
commit d0f54533eb484028f54d3f9810d504cb63f323ee
Author: Stefan Weil <sw at weilnetz.de>
Date:   Wed Jan 16 18:40:29 2013 +0100

    hw: Spelling fix in log message
    
    defineition -> definition
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Reviewed-by: Andreas F=E4rber <afaerber at suse.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c
index fb47cdc..6c443ba 100644
--- a/hw/openrisc_sim.c
+++ b/hw/openrisc_sim.c
@@ -107,7 +107,7 @@ static void openrisc_sim_init(QEMUMachineInitArgs *args)
     for (n = 0; n < smp_cpus; n++) {
         cpu = cpu_openrisc_init(cpu_model);
         if (cpu == NULL) {
-            qemu_log("Unable to find CPU defineition!\n");
+            qemu_log("Unable to find CPU definition!\n");
             exit(1);
         }
         qemu_register_reset(main_cpu_reset, cpu);
commit 3588185b8396eb97fd9efd41c2b97775465f67c4
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Jan 21 09:17:16 2013 +0100

    seabios: update to 1.7.2 release
    
    Not that many changes as we have a pretty recent git snapshot in master
    already:
    
    Hannes Reinecke (1):
          megasas: Invert PCI device selection
    
    Kevin O'Connor (2):
          Minor: Separate UUID display from F12 boot prompt.
          boot: Support "halt" in the boot order to prevent default boot attempts.
    
    Laszlo Ersek (1):
          display_uuid(): fix incomplete check after the loop
    
    Paolo Bonzini (1):
          vgabios: implement AX=1120H..1124H functions

diff --git a/pc-bios/acpi-dsdt.aml b/pc-bios/acpi-dsdt.aml
index 00224ea..75dfd1e 100644
Binary files a/pc-bios/acpi-dsdt.aml and b/pc-bios/acpi-dsdt.aml differ
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index 3910875..924bee3 100644
Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ
diff --git a/pc-bios/q35-acpi-dsdt.aml b/pc-bios/q35-acpi-dsdt.aml
index e50641c..cf7b085 100644
Binary files a/pc-bios/q35-acpi-dsdt.aml and b/pc-bios/q35-acpi-dsdt.aml differ
diff --git a/roms/seabios b/roms/seabios
index a810e4e..4bd8aeb 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit a810e4e72a0d42c7bc04eda57382f8e019add901
+Subproject commit 4bd8aebf3534e10d9aa21e820903f2cf9120708c
commit 6522773f88a2e37800f0bf7dc3632a14649f53c6
Author: Juan Quintela <quintela at redhat.com>
Date:   Mon Jan 14 14:14:42 2013 +0100

    migration: remove argument to qemu_savevm_state_cancel
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    
    Reviewed-by: Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index c07d4ee..d65a9f1 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -77,7 +77,7 @@ int qemu_savevm_state_begin(QEMUFile *f,
                             const MigrationParams *params);
 int qemu_savevm_state_iterate(QEMUFile *f);
 int qemu_savevm_state_complete(QEMUFile *f);
-void qemu_savevm_state_cancel(QEMUFile *f);
+void qemu_savevm_state_cancel(void);
 uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size);
 int qemu_loadvm_state(QEMUFile *f);
 
diff --git a/migration.c b/migration.c
index fe1a103..77c1971 100644
--- a/migration.c
+++ b/migration.c
@@ -330,7 +330,7 @@ static void migrate_fd_cancel(MigrationState *s)
 
     s->state = MIG_STATE_CANCELLED;
     notifier_list_notify(&migration_state_notifiers, s);
-    qemu_savevm_state_cancel(s->file);
+    qemu_savevm_state_cancel();
 
     migrate_fd_cleanup(s);
 }
diff --git a/savevm.c b/savevm.c
index 611e997..913a623 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1590,13 +1590,13 @@ int qemu_savevm_state_begin(QEMUFile *f,
 
         ret = se->ops->save_live_setup(f, se->opaque);
         if (ret < 0) {
-            qemu_savevm_state_cancel(f);
+            qemu_savevm_state_cancel();
             return ret;
         }
     }
     ret = qemu_file_get_error(f);
     if (ret != 0) {
-        qemu_savevm_state_cancel(f);
+        qemu_savevm_state_cancel();
     }
 
     return ret;
@@ -1647,7 +1647,7 @@ int qemu_savevm_state_iterate(QEMUFile *f)
     }
     ret = qemu_file_get_error(f);
     if (ret != 0) {
-        qemu_savevm_state_cancel(f);
+        qemu_savevm_state_cancel();
     }
     return ret;
 }
@@ -1727,7 +1727,7 @@ uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size)
     return ret;
 }
 
-void qemu_savevm_state_cancel(QEMUFile *f)
+void qemu_savevm_state_cancel(void)
 {
     SaveStateEntry *se;
 
commit b22ff1fbed9d7f1f677804cbaa9ee03ca17d0013
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 17 21:06:31 2012 +0200

    migration: Only go to the iterate stage if there is anything to send
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    
    Reviewed-by: Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/migration.c b/migration.c
index 6d3aeed..fe1a103 100644
--- a/migration.c
+++ b/migration.c
@@ -698,7 +698,7 @@ static void *buffered_file_thread(void *opaque)
             DPRINTF("iterate\n");
             pending_size = qemu_savevm_state_pending(s->file, max_size);
             DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
-            if (pending_size >= max_size) {
+            if (pending_size && pending_size >= max_size) {
                 ret = qemu_savevm_state_iterate(s->file);
                 if (ret < 0) {
                     qemu_mutex_unlock_iothread();
commit c369f40d2cb39f4eaaf6589c1113b528256d3a09
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 3 20:33:34 2012 +0200

    migration: unfold rest of migrate_fd_put_ready() into thread
    
    This will allow us finer control in next patches.
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    
    Reviewed-by: Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/migration.c b/migration.c
index 651edd5..6d3aeed 100644
--- a/migration.c
+++ b/migration.c
@@ -662,54 +662,6 @@ static int64_t buffered_get_rate_limit(void *opaque)
     return s->xfer_limit;
 }
 
-static bool migrate_fd_put_ready(MigrationState *s, uint64_t max_size)
-{
-    int ret;
-    uint64_t pending_size;
-    bool last_round = false;
-
-    qemu_mutex_lock_iothread();
-    DPRINTF("iterate\n");
-    pending_size = qemu_savevm_state_pending(s->file, max_size);
-    DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
-    if (pending_size >= max_size) {
-        ret = qemu_savevm_state_iterate(s->file);
-        if (ret < 0) {
-            migrate_fd_error(s);
-        }
-    } else {
-        int old_vm_running = runstate_is_running();
-        int64_t start_time, end_time;
-
-        DPRINTF("done iterating\n");
-        start_time = qemu_get_clock_ms(rt_clock);
-        qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
-        if (old_vm_running) {
-            vm_stop(RUN_STATE_FINISH_MIGRATE);
-        } else {
-            vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
-        }
-
-        if (qemu_savevm_state_complete(s->file) < 0) {
-            migrate_fd_error(s);
-        } else {
-            migrate_fd_completed(s);
-        }
-        end_time = qemu_get_clock_ms(rt_clock);
-        s->total_time = end_time - s->total_time;
-        s->downtime = end_time - start_time;
-        if (s->state != MIG_STATE_COMPLETED) {
-            if (old_vm_running) {
-                vm_start();
-            }
-        }
-        last_round = true;
-    }
-    qemu_mutex_unlock_iothread();
-
-    return last_round;
-}
-
 static void *buffered_file_thread(void *opaque)
 {
     MigrationState *s = opaque;
@@ -730,6 +682,7 @@ static void *buffered_file_thread(void *opaque)
 
     while (true) {
         int64_t current_time = qemu_get_clock_ms(rt_clock);
+        uint64_t pending_size;
 
         qemu_mutex_lock_iothread();
         if (s->state != MIG_STATE_ACTIVE) {
@@ -741,6 +694,46 @@ static void *buffered_file_thread(void *opaque)
             qemu_mutex_unlock_iothread();
             break;
         }
+        if (s->bytes_xfer < s->xfer_limit) {
+            DPRINTF("iterate\n");
+            pending_size = qemu_savevm_state_pending(s->file, max_size);
+            DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
+            if (pending_size >= max_size) {
+                ret = qemu_savevm_state_iterate(s->file);
+                if (ret < 0) {
+                    qemu_mutex_unlock_iothread();
+                    break;
+                }
+            } else {
+                int old_vm_running = runstate_is_running();
+                int64_t start_time, end_time;
+
+                DPRINTF("done iterating\n");
+                start_time = qemu_get_clock_ms(rt_clock);
+                qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
+                if (old_vm_running) {
+                    vm_stop(RUN_STATE_FINISH_MIGRATE);
+                } else {
+                    vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
+                }
+                ret = qemu_savevm_state_complete(s->file);
+                if (ret < 0) {
+                    qemu_mutex_unlock_iothread();
+                    break;
+                } else {
+                    migrate_fd_completed(s);
+                }
+                end_time = qemu_get_clock_ms(rt_clock);
+                s->total_time = end_time - s->total_time;
+                s->downtime = end_time - start_time;
+                if (s->state != MIG_STATE_COMPLETED) {
+                    if (old_vm_running) {
+                        vm_start();
+                    }
+                }
+                last_round = true;
+            }
+        }
         qemu_mutex_unlock_iothread();
         if (current_time >= initial_time + BUFFER_DELAY) {
             uint64_t transferred_bytes = s->bytes_xfer;
@@ -763,12 +756,6 @@ static void *buffered_file_thread(void *opaque)
         if (ret < 0) {
             break;
         }
-
-        DPRINTF("file is ready\n");
-        if (s->bytes_xfer < s->xfer_limit) {
-            DPRINTF("notifying client\n");
-            last_round = migrate_fd_put_ready(s, max_size);
-        }
     }
 
 out:
commit 7de6a690e73967eb5bc5e72b2942a6be1fee2c20
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 3 20:23:43 2012 +0200

    migration: move exit condition to migration thread
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    
    Reviewed-by: Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/migration.c b/migration.c
index 17eb27d..651edd5 100644
--- a/migration.c
+++ b/migration.c
@@ -669,12 +669,6 @@ static bool migrate_fd_put_ready(MigrationState *s, uint64_t max_size)
     bool last_round = false;
 
     qemu_mutex_lock_iothread();
-    if (s->state != MIG_STATE_ACTIVE) {
-        DPRINTF("put_ready returning because of non-active state\n");
-        qemu_mutex_unlock_iothread();
-        return false;
-    }
-
     DPRINTF("iterate\n");
     pending_size = qemu_savevm_state_pending(s->file, max_size);
     DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
@@ -737,9 +731,17 @@ static void *buffered_file_thread(void *opaque)
     while (true) {
         int64_t current_time = qemu_get_clock_ms(rt_clock);
 
+        qemu_mutex_lock_iothread();
+        if (s->state != MIG_STATE_ACTIVE) {
+            DPRINTF("put_ready returning because of non-active state\n");
+            qemu_mutex_unlock_iothread();
+            break;
+        }
         if (s->complete) {
+            qemu_mutex_unlock_iothread();
             break;
         }
+        qemu_mutex_unlock_iothread();
         if (current_time >= initial_time + BUFFER_DELAY) {
             uint64_t transferred_bytes = s->bytes_xfer;
             uint64_t time_spent = current_time - initial_time;
commit f7b67be36d01f8f506dc93213855b31dad17708c
Author: Juan Quintela <quintela at redhat.com>
Date:   Mon Dec 10 22:29:14 2012 +0100

    migration: Add buffered_flush error handling
    
    Now that we have error handling we can do proper handling of
    buffered_flush().
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    
    Reviewed-by: Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/migration.c b/migration.c
index 7ae1d93..17eb27d 100644
--- a/migration.c
+++ b/migration.c
@@ -757,7 +757,8 @@ static void *buffered_file_thread(void *opaque)
             /* usleep expects microseconds */
             g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
         }
-        if (buffered_flush(s) < 0) {
+        ret = buffered_flush(s);
+        if (ret < 0) {
             break;
         }
 
commit 76f5933aea281a52149b39a1a78a43565dc9715c
Author: Juan Quintela <quintela at redhat.com>
Date:   Wed Oct 3 20:16:24 2012 +0200

    migration: move beginning stage to the migration thread
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    
    Reviewed-by: Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/include/migration/migration.h b/include/migration/migration.h
index 95261c1..a8c9639 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -54,7 +54,6 @@ struct MigrationState
     bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
     int64_t xbzrle_cache_size;
     bool complete;
-    bool first_time;
 };
 
 void process_incoming_migration(QEMUFile *f);
diff --git a/migration.c b/migration.c
index 380f3cb..7ae1d93 100644
--- a/migration.c
+++ b/migration.c
@@ -674,17 +674,6 @@ static bool migrate_fd_put_ready(MigrationState *s, uint64_t max_size)
         qemu_mutex_unlock_iothread();
         return false;
     }
-    if (s->first_time) {
-        s->first_time = false;
-        DPRINTF("beginning savevm\n");
-        ret = qemu_savevm_state_begin(s->file, &s->params);
-        if (ret < 0) {
-            DPRINTF("failed, %d\n", ret);
-            migrate_fd_error(s);
-            qemu_mutex_unlock_iothread();
-            return false;
-        }
-    }
 
     DPRINTF("iterate\n");
     pending_size = qemu_savevm_state_pending(s->file, max_size);
@@ -733,6 +722,17 @@ static void *buffered_file_thread(void *opaque)
     int64_t initial_time = qemu_get_clock_ms(rt_clock);
     int64_t max_size = 0;
     bool last_round = false;
+    int ret;
+
+    qemu_mutex_lock_iothread();
+    DPRINTF("beginning savevm\n");
+    ret = qemu_savevm_state_begin(s->file, &s->params);
+    if (ret < 0) {
+        DPRINTF("failed, %d\n", ret);
+        qemu_mutex_unlock_iothread();
+        goto out;
+    }
+    qemu_mutex_unlock_iothread();
 
     while (true) {
         int64_t current_time = qemu_get_clock_ms(rt_clock);
@@ -768,6 +768,10 @@ static void *buffered_file_thread(void *opaque)
         }
     }
 
+out:
+    if (ret < 0) {
+        migrate_fd_error(s);
+    }
     g_free(s->buffer);
     return NULL;
 }
@@ -789,8 +793,6 @@ void migrate_fd_connect(MigrationState *s)
     s->buffer_size = 0;
     s->buffer_capacity = 0;
 
-    s->first_time = true;
-
     s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
     s->complete = false;
 
commit afe419319de1e5e98b131368ba14f85f98ab3a76
Author: Juan Quintela <quintela at redhat.com>
Date:   Mon Jan 14 13:36:28 2013 +0100

    qemu-file: Only set last_error if it is not already set
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    
    Reviewed-by: Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/savevm.c b/savevm.c
index 4e970ca..611e997 100644
--- a/savevm.c
+++ b/savevm.c
@@ -419,7 +419,9 @@ int qemu_file_get_error(QEMUFile *f)
 
 static void qemu_file_set_error(QEMUFile *f, int ret)
 {
-    f->last_error = ret;
+    if (f->last_error == 0) {
+        f->last_error = ret;
+    }
 }
 
 /** Flushes QEMUFile buffer
commit 1e973051b96bac5eef46393eec15b68796e7c7d3
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 20 11:30:39 2012 +0100

    migration: fix off-by-one in buffered_rate_limit
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    
    Reviewed-by: Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/migration.c b/migration.c
index 5513dde..380f3cb 100644
--- a/migration.c
+++ b/migration.c
@@ -632,7 +632,7 @@ static int buffered_rate_limit(void *opaque)
         return ret;
     }
 
-    if (s->bytes_xfer > s->xfer_limit) {
+    if (s->bytes_xfer >= s->xfer_limit) {
         return 1;
     }
 
commit 25242635acb0b803392ad5669b5624815af3fd07
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Sat Nov 10 18:58:40 2012 +0100

    migration: remove double call to migrate_fd_close
    
    The call in buffered_close is enough, because buffered_close is called
    already by migrate_fd_cleanup.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    
    Reviewed-by: Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/migration.c b/migration.c
index 1f4c6ee..5513dde 100644
--- a/migration.c
+++ b/migration.c
@@ -605,7 +605,6 @@ static int buffered_close(void *opaque)
     if (ret >= 0) {
         ret = ret2;
     }
-    ret = migrate_fd_close(s);
     s->complete = true;
     return ret;
 }
commit b9c961a8ff3973b97964431491bc3f4f427cd66a
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 20 11:29:03 2012 +0100

    migration: make function static
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    
    Reviewed-by: Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/include/migration/migration.h b/include/migration/migration.h
index 2d5b630..95261c1 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -87,8 +87,6 @@ void migrate_fd_error(MigrationState *s);
 
 void migrate_fd_connect(MigrationState *s);
 
-ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
-                              size_t size);
 int migrate_fd_close(MigrationState *s);
 
 void add_migration_state_change_notifier(Notifier *notify);
diff --git a/migration.c b/migration.c
index d6ec3e8..1f4c6ee 100644
--- a/migration.c
+++ b/migration.c
@@ -302,8 +302,8 @@ static void migrate_fd_completed(MigrationState *s)
     notifier_list_notify(&migration_state_notifiers, s);
 }
 
-ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
-                              size_t size)
+static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
+                                     size_t size)
 {
     ssize_t ret;
 
commit f65a874756bb3e4b57571a33a51d8887bbee7981
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 20 11:31:03 2012 +0100

    use XFER_LIMIT_RATIO consistently
    
    commit 5b4e1eb769eee892b44d3f6b2369b05196442f59
    
    missed this use.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    
    Reviewed-by: Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/migration.c b/migration.c
index c69e864..d6ec3e8 100644
--- a/migration.c
+++ b/migration.c
@@ -650,7 +650,7 @@ static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate)
         new_rate = SIZE_MAX;
     }
 
-    s->xfer_limit = new_rate / 10;
+    s->xfer_limit = new_rate / XFER_LIMIT_RATIO;
 
 out:
     return s->xfer_limit;
commit 9c339485f0abb96595f4d91880b177726463300c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 20 11:26:04 2012 +0100

    Protect migration_bitmap_sync() with the ramlist lock
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    
    Reviewed-by: Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 8c833b6..dada6de 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -658,9 +658,8 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
 
 static int ram_save_complete(QEMUFile *f, void *opaque)
 {
-    migration_bitmap_sync();
-
     qemu_mutex_lock_ramlist();
+    migration_bitmap_sync();
 
     /* try transferring iterative blocks of memory */
 
commit fb3409de22c7c167dced51175500bc4b1a78dcc2
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 20 11:25:45 2012 +0100

    Unlock ramlist lock also in error case
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    
    Reviewed-by: Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 86f8544..8c833b6 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -642,12 +642,13 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
         i++;
     }
 
+    qemu_mutex_unlock_ramlist();
+
     if (ret < 0) {
         bytes_transferred += total_sent;
         return ret;
     }
 
-    qemu_mutex_unlock_ramlist();
     qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
     total_sent += 8;
     bytes_transferred += total_sent;


More information about the Spice-commits mailing list