[Spice-commits] 799 commits - .gitignore MAINTAINERS Makefile Makefile.objs Makefile.target QMP/qmp-events.txt QMP/qmp-shell arch_init.c async.c backends/Makefile.objs backends/baum.c backends/msmouse.c backends/rng-egd.c backends/rng-random.c backends/tpm.c block-migration.c block.c block/blkdebug.c block/blkverify.c block/bochs.c block/cloop.c block/cow.c block/curl.c block/dmg.c block/gluster.c block/iscsi.c block/nbd.c block/parallels.c block/qcow.c block/qcow2-cluster.c block/qcow2-refcount.c block/qcow2-snapshot.c block/qcow2.c block/qcow2.h block/qed.c block/raw-posix.c block/raw-win32.c block/raw.c block/rbd.c block/sheepdog.c block/vdi.c block/vmdk.c block/vpc.c block/vvfat.c blockdev.c bt-host.c configure cpu-exec.c cpus.c default-configs/arm-softmmu.mak default-configs/i386-softmmu.mak default-configs/moxie-softmmu.mak default-configs/pci.mak default-configs/ppc-softmmu.mak default-configs/ppc64-softmmu.mak default-configs/ppcemb-softmmu.mak default-configs/x86_64-softmmu .mak device-hotplug.c disas.c disas/Makefile.objs disas/lm32.c disas/moxie.c docs/migration.txt docs/tracing.txt docs/usb-storage.txt exec.c gdbstub.c hmp-commands.hx hmp.c hmp.h hw/9p.h hw/9pfs hw/Makefile.objs hw/a15mpcore.c hw/a9mpcore.c hw/a9scu.c hw/ac97.c hw/acpi.c hw/acpi.h hw/acpi_ich9.c hw/acpi_ich9.h hw/acpi_piix4.c hw/adb.c hw/adb.h hw/adlib.c hw/ads7846.c hw/alpha hw/alpha_dp264.c hw/alpha_pci.c hw/alpha_sys.h hw/alpha_typhoon.c hw/an5206.c hw/apb_pci.c hw/apic.c hw/apic_common.c hw/apic_internal.h hw/apm.c hw/apm.h hw/applesmc.c hw/arm hw/arm-misc.h hw/arm11mpcore.c hw/arm_boot.c hw/arm_gic.c hw/arm_gic_common.c hw/arm_gic_internal.h hw/arm_l2x0.c hw/arm_mptimer.c hw/arm_pic.c hw/arm_sysctl.c hw/arm_timer.c hw/armv7m.c hw/armv7m_nvic.c hw/axis_dev88.c hw/baum.c hw/baum.h hw/bitbang_i2c.c hw/bitbang_i2c.h hw/blizzard.c hw/boards.h hw/bonito.c hw/bt-hci-csr.c hw/bt-hci.c hw/bt-hid.c hw/bt-l2cap.c hw/bt-sdp.c hw/bt.c hw/cadence_gem.c hw/cadence_ttc.c hw/cadence_uar t.c hw/cbus.c hw/ccid.h hw/cdrom.c hw/cirrus_vga.c hw/cirrus_vga_rop.h hw/collie.c hw/cris hw/cris-boot.c hw/cris_pic_cpu.c hw/cs4231.c hw/cs4231a.c hw/cuda.c hw/dataplane hw/debugcon.c hw/debugexit.c hw/dec_pci.c hw/device-hotplug.c hw/dma.c hw/dp8393x.c hw/ds1225y.c hw/ds1338.c hw/dummy_m68k.c hw/e1000.c hw/ecc.c hw/eccmemctl.c hw/eepro100.c hw/eeprom93xx.c hw/elf_ops.h hw/empty_slot.c hw/es1370.c hw/escc.c hw/esp-pci.c hw/esp.c hw/esp.h hw/etraxfs.h hw/etraxfs_dma.c hw/etraxfs_eth.c hw/etraxfs_pic.c hw/etraxfs_ser.c hw/etraxfs_timer.c hw/exynos4210.c hw/exynos4210_combiner.c hw/exynos4210_fimd.c hw/exynos4210_gic.c hw/exynos4210_i2c.c hw/exynos4210_mct.c hw/exynos4210_pmu.c hw/exynos4210_pwm.c hw/exynos4210_rtc.c hw/exynos4210_uart.c hw/exynos4_boards.c hw/fdc.c hw/fifo.c hw/fifo.h hw/fmopl.c hw/framebuffer.c hw/framebuffer.h hw/fw_cfg.c hw/g364fb.c hw/grackle_pci.c hw/grlib.h hw/grlib_apbuart.c hw/grlib_gptimer.c hw/grlib_irqmp.c hw/gt64xxx.c hw/gumstix.c hw/gus.c hw/gus emu_hal.c hw/gusemu_mixer.c hw/hda-audio.c hw/heathrow_pic.c hw/hid.c hw/highbank.c hw/hpet.c hw/hw.h hw/i2c.c hw/i2c.h hw/i386 hw/i82374.c hw/i82378.c hw/i8254.c hw/i8254.h hw/i8254_common.c hw/i8254_internal.h hw/i8259.c hw/i8259_common.c hw/i8259_internal.h hw/i82801b11.c hw/ich9.h hw/ide.h hw/imx_avic.c hw/imx_ccm.c hw/imx_serial.c hw/imx_timer.c hw/integratorcp.c hw/intel-hda.c hw/intel-hda.h hw/ioapic.c hw/ioapic_common.c hw/ioapic_internal.h hw/ioh3420.c hw/ioh3420.h hw/ipack.c hw/ipack.h hw/ipoctal232.c hw/irq.c hw/isa-bus.c hw/isa.h hw/isa_mmio.c hw/ivshmem.c hw/jazz_led.c hw/kvm hw/kvmvapic.c hw/kzm.c hw/lan9118.c hw/lance.c hw/leon3.c hw/lm32 hw/lm32_boards.c hw/lm32_hwsetup.h hw/lm32_juart.c hw/lm32_pic.c hw/lm32_sys.c hw/lm32_timer.c hw/lm32_uart.c hw/lm4549.c hw/lm832x.c hw/loader.c hw/loader.h hw/lpc_ich9.c hw/lsi53c895a.c hw/m25p80.c hw/m48t59.c hw/m68k hw/mac_dbdma.c hw/mac_nvram.c hw/macio.c hw/mainstone.c hw/marvell_88w8618_audio.c hw/max111x.c hw/max7310. c hw/mc146818rtc.c hw/mc146818rtc.h hw/mcf5206.c hw/mcf5208.c hw/mcf_fec.c hw/mcf_intc.c hw/mcf_uart.c hw/megasas.c hw/microblaze hw/microblaze_boot.c hw/microblaze_boot.h hw/microblaze_pic_cpu.c hw/milkymist-ac97.c hw/milkymist-hpdmc.c hw/milkymist-hw.h hw/milkymist-memcard.c hw/milkymist-minimac2.c hw/milkymist-pfpu.c hw/milkymist-softusb.c hw/milkymist-sysctl.c hw/milkymist-tmu2.c hw/milkymist-uart.c hw/milkymist-vgafb.c hw/milkymist.c hw/mips hw/mips_addr.c hw/mips_fulong2e.c hw/mips_int.c hw/mips_jazz.c hw/mips_malta.c hw/mips_mipssim.c hw/mips_r4k.c hw/mips_timer.c hw/mipsnet.c hw/moxie hw/mpc8544_guts.c hw/msmouse.c hw/msmouse.h hw/mst_fpga.c hw/multiboot.c hw/musicpal.c hw/nand.c hw/ne2000-isa.c hw/ne2000.c hw/nseries.c hw/omap1.c hw/omap2.c hw/omap_clk.c hw/omap_dma.c hw/omap_dss.c hw/omap_gpio.c hw/omap_gpmc.c hw/omap_gptimer.c hw/omap_i2c.c hw/omap_intc.c hw/omap_l4.c hw/omap_lcdc.c hw/omap_mmc.c hw/omap_sdrc.c hw/omap_spi.c hw/omap_sx1.c hw/omap_synctimer.c hw/om ap_tap.c hw/omap_uart.c hw/onenand.c hw/opencores_eth.c hw/openpic.c hw/openrisc hw/openrisc_pic.c hw/openrisc_sim.c hw/openrisc_timer.c hw/palm.c hw/pam.c hw/parallel.c hw/pc-testdev.c hw/pc.c hw/pc.h hw/pc87312.c hw/pc87312.h hw/pc_piix.c hw/pc_q35.c hw/pc_sysfw.c hw/pci hw/pci_bridge_dev.c hw/pckbd.c hw/pcnet-pci.c hw/pcnet.c hw/pcspk.c hw/pcspk.h hw/petalogix_ml605_mmu.c hw/petalogix_s3adsp1800_mmu.c hw/pflash_cfi01.c hw/pflash_cfi02.c hw/piix4.c hw/piix_pci.c hw/pl011.c hw/pl022.c hw/pl031.c hw/pl041.c hw/pl050.c hw/pl061.c hw/pl080.c hw/pl110.c hw/pl110_template.h hw/pl181.c hw/pl190.c hw/pl330.c hw/pm_smbus.c hw/ppc hw/ppc.c hw/ppc405.h hw/ppc405_boards.c hw/ppc405_uc.c hw/ppc440_bamboo.c hw/ppc4xx.h hw/ppc4xx_devs.c hw/ppc4xx_pci.c hw/ppc_booke.c hw/ppce500_pci.c hw/ppce500_spin.c hw/prep_pci.c hw/ps2.c hw/ptimer.c hw/puv3.c hw/puv3_dma.c hw/puv3_gpio.c hw/puv3_intc.c hw/puv3_ost.c hw/puv3_pm.c hw/pxa2xx.c hw/pxa2xx_dma.c hw/pxa2xx_gpio.c hw/pxa2xx_keypad.c hw/pxa2xx _lcd.c hw/pxa2xx_mmci.c hw/pxa2xx_pcmcia.c hw/pxa2xx_pic.c hw/pxa2xx_timer.c hw/q35.c hw/q35.h hw/qdev-addr.c hw/qdev-core.h hw/qdev-monitor.c hw/qdev-monitor.h hw/qdev-properties-system.c hw/qdev-properties.c hw/qdev-properties.h hw/qdev.c hw/qdev.h hw/qxl-logger.c hw/qxl-render.c hw/qxl.c hw/qxl.h hw/r2d.c hw/rc4030.c hw/realview.c hw/realview_gic.c hw/rtl8139.c hw/s390x hw/sb16.c hw/sbi.c hw/scsi-bus.c hw/scsi-disk.c hw/scsi-generic.c hw/scsi.h hw/sd.c hw/sdhci.c hw/sdhci.h hw/serial-isa.c hw/serial-pci.c hw/serial.c hw/serial.h hw/sga.c hw/sh.h hw/sh4 hw/sh7750.c hw/sh7750_regnames.c hw/sh_intc.c hw/sh_intc.h hw/sh_pci.c hw/sh_serial.c hw/sh_timer.c hw/shix.c hw/slavio_intctl.c hw/slavio_misc.c hw/slavio_timer.c hw/sm501.c hw/smbios.c hw/smbus.c hw/smbus.h hw/smbus_eeprom.c hw/smbus_ich9.c hw/smc91c111.c hw/soc_dma.c hw/spapr.c hw/spapr_events.c hw/spapr_hcall.c hw/spapr_iommu.c hw/spapr_llan.c hw/spapr_pci.c hw/spapr_pci.h hw/spapr_rtas.c hw/spapr_vio.c hw/spapr_vscsi.c hw/spapr_vty.c hw/sparc hw/sparc32_dma.c hw/sparc64 hw/spitz.c hw/ssd0303.c hw/ssd0323.c hw/ssi-sd.c hw/ssi.c hw/ssi.h hw/stellaris.c hw/stellaris_enet.c hw/stellaris_input.c hw/stream.c hw/strongarm.c hw/sun4c_intctl.c hw/sun4m.c hw/sun4m.h hw/sun4m_iommu.c hw/sun4u.c hw/sysbus.c hw/sysbus.h hw/tc58128.c hw/tc6393xb.c hw/tc6393xb_template.h hw/tcx.c hw/tmp105.c hw/tmp105.h hw/tosa.c hw/tpci200.c hw/tsc2005.c hw/tsc210x.c hw/tusb6010.c hw/twl92230.c hw/unicore32 hw/unin_pci.c hw/usb hw/usb.h hw/versatile_i2c.c hw/versatile_pci.c hw/versatilepb.c hw/vexpress.c hw/vfio_pci.c hw/vga-isa-mm.c hw/vga-isa.c hw/vga-pci.c hw/vga.c hw/vga_int.h hw/vhost.c hw/vhost_net.c hw/virtex_ml507.c hw/virtio-balloon.c hw/virtio-balloon.h hw/virtio-blk.c hw/virtio-blk.h hw/virtio-bus.c hw/virtio-bus.h hw/virtio-console.c hw/virtio-net.c hw/virtio-net.h hw/virtio-pci.c hw/virtio-pci.h hw/virtio-rng.c hw/virtio-rng.h hw/virtio-scsi.c hw/virtio-scsi.h hw/virtio-serial-bus.c hw/virtio-serial.h hw/v irtio.c hw/virtio.h hw/vmmouse.c hw/vmport.c hw/vmware_utils.h hw/vmware_vga.c hw/vmxnet3.c hw/vmxnet3.h hw/vmxnet_debug.h hw/vmxnet_rx_pkt.c hw/vmxnet_rx_pkt.h hw/vmxnet_tx_pkt.c hw/vmxnet_tx_pkt.h hw/vt82c686.c hw/wdt_i6300esb.c hw/wdt_ib700.c hw/wm8750.c hw/xen-host-pci-device.c hw/xen-host-pci-device.h hw/xen_apic.c hw/xen_backend.c hw/xen_backend.h hw/xen_common.h hw/xen_console.c hw/xen_devconfig.c hw/xen_disk.c hw/xen_domainbuild.c hw/xen_domainbuild.h hw/xen_machine_pv.c hw/xen_nic.c hw/xen_platform.c hw/xen_pt.c hw/xen_pt.h hw/xen_pt_config_init.c hw/xen_pt_msi.c hw/xenfb.c hw/xgmac.c hw/xics.c hw/xics.h hw/xilinx.h hw/xilinx_axidma.c hw/xilinx_axienet.c hw/xilinx_ethlite.c hw/xilinx_intc.c hw/xilinx_spi.c hw/xilinx_spips.c hw/xilinx_timer.c hw/xilinx_uartlite.c hw/xilinx_zynq.c hw/xio3130_downstream.c hw/xio3130_downstream.h hw/xio3130_upstream.c hw/xio3130_upstream.h hw/xtensa hw/xtensa_lx60.c hw/xtensa_pic.c hw/xtensa_sim.c hw/z2.c hw/zaurus.c hw/zynq_slcr.c incl ude/backends include/block include/char include/disas include/exec include/glib-compat.h include/migration include/monitor include/net include/qapi include/qemu include/qemu-common.h include/qom include/sysemu include/tpm include/ui kvm-all.c linux-headers/asm-arm linux-headers/asm-generic linux-headers/linux linux-user/main.c linux-user/mips64 linux-user/mipsn32 linux-user/signal.c linux-user/socket.h linux-user/sparc linux-user/strace.c linux-user/syscall.c main-loop.c memory.c migration-exec.c migration-fd.c migration-tcp.c migration-unix.c migration.c monitor.c nbd.c net/Makefile.objs net/checksum.c net/eth.c net/hub.c net/hub.h net/net.c net/queue.c net/slirp.c net/socket.c net/tap-linux.c net/tap-linux.h net/tap.c net/vde.c page_cache.c pc-bios/bios.bin pc-bios/efi-e1000.rom pc-bios/efi-eepro100.rom pc-bios/efi-ne2k_pci.rom pc-bios/efi-pcnet.rom pc-bios/efi-rtl8139.rom pc-bios/efi-virtio.rom po/Makefile po/de_DE.po po/fr_FR.po po/it.po po/messages.po qapi-schema.json q dev-monitor.c qemu-bridge-helper.c qemu-char.c qemu-coroutine-lock.c qemu-doc.texi qemu-img.c qemu-io.c qemu-nbd.c qemu-options.hx qga/channel-win32.c qga/commands-posix.c qga/commands-win32.c qga/guest-agent-core.h qga/main.c qga/qapi-schema.json qga/service-win32.c qmp-commands.hx qobject/qdict.c qobject/qstring.c qom/cpu.c qom/object.c qtest.c roms/Makefile roms/config.ipxe.general.h roms/configure-seabios.sh roms/ipxe roms/seabios savevm.c scripts/make_device_config.sh scripts/tracetool scripts/tracetool.py slirp/misc.c slirp/socket.c slirp/tcp_subr.c slirp/udp.c spice-qemu-char.c stubs/Makefile.objs stubs/pci-drive-hot-add.c stubs/vmstate.c target-alpha/cpu-qom.h target-alpha/cpu.c target-alpha/cpu.h target-alpha/helper.c target-alpha/translate.c target-arm/Makefile.objs target-arm/cpu-qom.h target-arm/cpu.c target-arm/cpu.h target-arm/helper.c target-arm/kvm.c target-arm/kvm_arm.h target-arm/op_helper.c target-arm/translate.c target-cris/cpu-qom.h target-cris/cpu.c tar get-cris/cpu.h target-cris/helper.c target-cris/translate.c target-i386/cpu-qom.h target-i386/cpu.c target-i386/cpu.h target-i386/fpu_helper.c target-i386/helper.c target-i386/kvm.c target-i386/machine.c target-i386/misc_helper.c target-i386/ops_sse.h target-i386/seg_helper.c target-i386/svm_helper.c target-i386/translate.c target-lm32/cpu-qom.h target-lm32/cpu.c target-lm32/cpu.h target-lm32/helper.c target-lm32/machine.c target-lm32/op_helper.c target-lm32/translate.c target-m68k/cpu-qom.h target-m68k/cpu.c target-m68k/cpu.h target-m68k/helper.c target-m68k/op_helper.c target-m68k/qregs.def target-m68k/translate.c target-microblaze/cpu-qom.h target-microblaze/cpu.c target-microblaze/cpu.h target-microblaze/helper.c target-microblaze/op_helper.c target-microblaze/translate.c target-mips/cpu-qom.h target-mips/cpu.c target-mips/cpu.h target-mips/dsp_helper.c target-mips/helper.c target-mips/op_helper.c target-mips/translate.c target-moxie/Makefile.objs target-moxie/cpu.c targ et-moxie/cpu.h target-moxie/helper.c target-moxie/helper.h target-moxie/machine.c target-moxie/machine.h target-moxie/mmu.c target-moxie/mmu.h target-moxie/translate.c target-openrisc/cpu.c target-openrisc/cpu.h target-openrisc/interrupt.c target-openrisc/interrupt_helper.c target-openrisc/sys_helper.c target-openrisc/translate.c target-ppc/Makefile.objs target-ppc/cpu-models.c target-ppc/cpu-models.h target-ppc/cpu-qom.h target-ppc/cpu.h target-ppc/excp_helper.c target-ppc/fpu_helper.c target-ppc/helper.h target-ppc/helper_regs.h target-ppc/kvm.c target-ppc/machine.c target-ppc/mem_helper.c target-ppc/misc_helper.c target-ppc/mmu-hash32.c target-ppc/mmu-hash32.h target-ppc/mmu-hash64.c target-ppc/mmu-hash64.h target-ppc/mmu_helper.c target-ppc/translate.c target-ppc/translate_init.c target-ppc/user_only_helper.c target-s390x/cpu-qom.h target-s390x/cpu.c target-s390x/cpu.h target-s390x/helper.c target-s390x/ioinst.c target-s390x/kvm.c target-s390x/translate.c target-sh4/cpu- qom.h target-sh4/cpu.c target-sh4/cpu.h target-sh4/helper.c target-sh4/op_helper.c target-sh4/translate.c target-sparc/cpu-qom.h target-sparc/cpu.c target-sparc/cpu.h target-sparc/helper.c target-sparc/int32_helper.c target-sparc/int64_helper.c target-sparc/translate.c target-unicore32/cpu-qom.h target-unicore32/cpu.c target-unicore32/cpu.h target-unicore32/helper.c target-unicore32/softmmu.c target-unicore32/translate.c target-xtensa/cpu-qom.h target-xtensa/cpu.c target-xtensa/cpu.h target-xtensa/helper.c target-xtensa/op_helper.c target-xtensa/translate.c tcg/README tcg/mips tcg/optimize.c tcg/sparc tcg/tcg.h tests/qemu-iotests tests/rtc-test.c tests/tcg tests/test-thread-pool.c tests/test-visitor-serialization.c thread-pool.c tpm/Makefile.objs tpm/tpm.c tpm/tpm_backend.c tpm/tpm_backend.h tpm/tpm_int.h tpm/tpm_passthrough.c tpm/tpm_tis.c tpm/tpm_tis.h trace-events trace/Makefile.objs trace/control-internal.h trace/control.c trace/control.h trace/default.c trace/event-inte rnal.h trace/simple.c trace/simple.h trace/stderr.c trace/stderr.h translate-all.c ui/cocoa.m ui/console.c ui/curses.c ui/gtk.c ui/sdl.c ui/spice-display.c ui/vnc-enc-tight.c ui/vnc-jobs.c ui/vnc.c ui/vnc.h util/Makefile.objs util/bitops.c util/cutils.c util/fifo8.c util/hexdump.c util/iov.c util/osdep.c util/oslib-posix.c util/oslib-win32.c util/qemu-config.c util/qemu-option.c util/qemu-sockets.c util/qemu-timer-common.c vl.c xen-all.c xen-mapcache.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Mon Apr 15 01:47:17 PDT 2013


 .gitignore                               |    7 
 MAINTAINERS                              |   24 
 Makefile                                 |   11 
 Makefile.objs                            |    2 
 Makefile.target                          |    1 
 QMP/qmp-events.txt                       |   18 
 QMP/qmp-shell                            |    7 
 arch_init.c                              |  108 
 async.c                                  |   11 
 backends/Makefile.objs                   |    6 
 backends/baum.c                          |  633 +++
 backends/msmouse.c                       |   84 
 backends/rng-egd.c                       |    6 
 backends/rng-random.c                    |    4 
 backends/tpm.c                           |  154 
 block-migration.c                        |  167 
 block.c                                  |  307 +
 block/blkdebug.c                         |    5 
 block/blkverify.c                        |    7 
 block/bochs.c                            |    2 
 block/cloop.c                            |    2 
 block/cow.c                              |    4 
 block/curl.c                             |    3 
 block/dmg.c                              |   15 
 block/gluster.c                          |    2 
 block/iscsi.c                            |  431 +-
 block/nbd.c                              |  137 
 block/parallels.c                        |    2 
 block/qcow.c                             |    4 
 block/qcow2-cluster.c                    |  514 ++
 block/qcow2-refcount.c                   |   53 
 block/qcow2-snapshot.c                   |   10 
 block/qcow2.c                            |   75 
 block/qcow2.h                            |   33 
 block/qed.c                              |    6 
 block/raw-posix.c                        |   23 
 block/raw-win32.c                        |   10 
 block/raw.c                              |    2 
 block/rbd.c                              |    3 
 block/sheepdog.c                         |  341 +
 block/vdi.c                              |    2 
 block/vmdk.c                             |    6 
 block/vpc.c                              |    2 
 block/vvfat.c                            |    5 
 blockdev.c                               |  119 
 bt-host.c                                |    2 
 configure                                |  111 
 cpu-exec.c                               |  134 
 cpus.c                                   |   17 
 default-configs/arm-softmmu.mak          |    3 
 default-configs/i386-softmmu.mak         |    2 
 default-configs/moxie-softmmu.mak        |    1 
 default-configs/pci.mak                  |    1 
 default-configs/ppc-softmmu.mak          |    1 
 default-configs/ppc64-softmmu.mak        |    2 
 default-configs/ppcemb-softmmu.mak       |    1 
 default-configs/x86_64-softmmu.mak       |    2 
 device-hotplug.c                         |   79 
 disas.c                                  |    6 
 disas/Makefile.objs                      |    1 
 disas/lm32.c                             |    8 
 disas/moxie.c                            |  360 ++
 docs/migration.txt                       |   20 
 docs/tracing.txt                         |   44 
 docs/usb-storage.txt                     |    4 
 exec.c                                   |   47 
 gdbstub.c                                |   13 
 hmp-commands.hx                          |   69 
 hmp.c                                    |   54 
 hmp.h                                    |    2 
 hw/9p.h                                  |   24 
 hw/9pfs/virtio-9p-device.c               |   53 
 hw/9pfs/virtio-9p-device.h               |   24 
 hw/9pfs/virtio-9p-proxy.c                |    1 
 hw/9pfs/virtio-9p.c                      |    3 
 hw/9pfs/virtio-9p.h                      |    1 
 hw/Makefile.objs                         |   12 
 hw/a15mpcore.c                           |   10 
 hw/a9mpcore.c                            |  159 
 hw/a9scu.c                               |  164 
 hw/ac97.c                                |    6 
 hw/acpi.c                                |  365 +-
 hw/acpi.h                                |    2 
 hw/acpi_ich9.c                           |   12 
 hw/acpi_ich9.h                           |    2 
 hw/acpi_piix4.c                          |   16 
 hw/adb.c                                 |    4 
 hw/adb.h                                 |    2 
 hw/adlib.c                               |    8 
 hw/ads7846.c                             |    2 
 hw/alpha/Makefile.objs                   |    4 
 hw/alpha/dp264.c                         |  182 +
 hw/alpha/pci.c                           |  109 
 hw/alpha_dp264.c                         |  182 -
 hw/alpha_pci.c                           |  109 
 hw/alpha_sys.h                           |   10 
 hw/alpha_typhoon.c                       |   26 
 hw/an5206.c                              |  100 
 hw/apb_pci.c                             |   16 
 hw/apic.c                                |   37 
 hw/apic_common.c                         |    6 
 hw/apic_internal.h                       |    2 
 hw/apm.c                                 |    6 
 hw/apm.h                                 |    2 
 hw/applesmc.c                            |    4 
 hw/arm-misc.h                            |    2 
 hw/arm/Makefile.objs                     |   45 
 hw/arm/armv7m.c                          |  284 +
 hw/arm/boot.c                            |  480 ++
 hw/arm/collie.c                          |   73 
 hw/arm/exynos4210.c                      |  349 +
 hw/arm/exynos4_boards.c                  |  170 
 hw/arm/gumstix.c                         |  141 
 hw/arm/highbank.c                        |  342 +
 hw/arm/integratorcp.c                    |  566 +++
 hw/arm/kzm.c                             |  157 
 hw/arm/mainstone.c                       |  190 +
 hw/arm/musicpal.c                        | 1717 +++++++++
 hw/arm/nseries.c                         | 1415 +++++++
 hw/arm/omap1.c                           | 4059 ++++++++++++++++++++++
 hw/arm/omap2.c                           | 2684 ++++++++++++++
 hw/arm/omap_sx1.c                        |  238 +
 hw/arm/palm.c                            |  284 +
 hw/arm/pic_cpu.c                         |   68 
 hw/arm/pxa2xx.c                          | 2294 ++++++++++++
 hw/arm/pxa2xx_gpio.c                     |  351 +
 hw/arm/pxa2xx_pic.c                      |  335 +
 hw/arm/realview.c                        |  404 ++
 hw/arm/spitz.c                           | 1138 ++++++
 hw/arm/stellaris.c                       | 1401 +++++++
 hw/arm/tosa.c                            |  302 +
 hw/arm/versatilepb.c                     |  403 ++
 hw/arm/vexpress.c                        |  559 +++
 hw/arm/xilinx_zynq.c                     |  247 +
 hw/arm/z2.c                              |  384 ++
 hw/arm11mpcore.c                         |   43 
 hw/arm_boot.c                            |  480 --
 hw/arm_gic.c                             |   27 
 hw/arm_gic_common.c                      |  140 
 hw/arm_gic_internal.h                    |   46 
 hw/arm_l2x0.c                            |    2 
 hw/arm_mptimer.c                         |  119 
 hw/arm_pic.c                             |   40 
 hw/arm_sysctl.c                          |  267 +
 hw/arm_timer.c                           |    6 
 hw/armv7m.c                              |  284 -
 hw/armv7m_nvic.c                         |   25 
 hw/axis_dev88.c                          |  366 --
 hw/baum.c                                |  627 ---
 hw/baum.h                                |   30 
 hw/bitbang_i2c.c                         |    6 
 hw/bitbang_i2c.h                         |    2 
 hw/blizzard.c                            |   51 
 hw/boards.h                              |    2 
 hw/bonito.c                              |   12 
 hw/bt-hci-csr.c                          |    5 
 hw/bt-hci.c                              |    4 
 hw/bt-hid.c                              |    4 
 hw/bt-l2cap.c                            |    2 
 hw/bt-sdp.c                              |    2 
 hw/bt.c                                  |    2 
 hw/cadence_gem.c                         |   38 
 hw/cadence_ttc.c                         |    2 
 hw/cadence_uart.c                        |    3 
 hw/cbus.c                                |    4 
 hw/ccid.h                                |    2 
 hw/cdrom.c                               |    2 
 hw/cirrus_vga.c                          |   66 
 hw/cirrus_vga_rop.h                      |    8 
 hw/collie.c                              |   73 
 hw/cris-boot.c                           |   98 
 hw/cris/Makefile.objs                    |   10 
 hw/cris/axis_dev88.c                     |  366 ++
 hw/cris/boot.c                           |   98 
 hw/cris/pic_cpu.c                        |   47 
 hw/cris_pic_cpu.c                        |   45 
 hw/cs4231.c                              |    2 
 hw/cs4231a.c                             |    8 
 hw/cuda.c                                |    6 
 hw/dataplane/Makefile.objs               |    2 
 hw/dataplane/event-poll.c                |  100 
 hw/dataplane/event-poll.h                |   40 
 hw/dataplane/ioq.c                       |    2 
 hw/dataplane/virtio-blk.c                |   63 
 hw/dataplane/vring.c                     |    3 
 hw/dataplane/vring.h                     |    2 
 hw/debugcon.c                            |    6 
 hw/debugexit.c                           |    4 
 hw/dec_pci.c                             |   19 
 hw/device-hotplug.c                      |   88 
 hw/dma.c                                 |    4 
 hw/dp8393x.c                             |    4 
 hw/ds1225y.c                             |    2 
 hw/ds1338.c                              |   10 
 hw/dummy_m68k.c                          |   84 
 hw/e1000.c                               |   35 
 hw/ecc.c                                 |    4 
 hw/eccmemctl.c                           |    2 
 hw/eepro100.c                            |    6 
 hw/eeprom93xx.c                          |    4 
 hw/elf_ops.h                             |   19 
 hw/empty_slot.c                          |    6 
 hw/es1370.c                              |    6 
 hw/escc.c                                |    6 
 hw/esp-pci.c                             |    6 
 hw/esp.c                                 |    4 
 hw/esp.h                                 |    2 
 hw/etraxfs.h                             |    2 
 hw/etraxfs_dma.c                         |    4 
 hw/etraxfs_eth.c                         |    4 
 hw/etraxfs_pic.c                         |    4 
 hw/etraxfs_ser.c                         |    2 
 hw/etraxfs_timer.c                       |    4 
 hw/exynos4210.c                          |  349 -
 hw/exynos4210_combiner.c                 |    4 
 hw/exynos4210_fimd.c                     |   19 
 hw/exynos4210_gic.c                      |    6 
 hw/exynos4210_i2c.c                      |    4 
 hw/exynos4210_mct.c                      |    6 
 hw/exynos4210_pmu.c                      |    2 
 hw/exynos4210_pwm.c                      |    6 
 hw/exynos4210_rtc.c                      |    8 
 hw/exynos4210_uart.c                     |    4 
 hw/exynos4_boards.c                      |  170 
 hw/fdc.c                                 |   10 
 hw/fifo.c                                |   78 
 hw/fifo.h                                |   99 
 hw/fmopl.c                               |    2 
 hw/framebuffer.c                         |    8 
 hw/framebuffer.h                         |    2 
 hw/fw_cfg.c                              |    8 
 hw/g364fb.c                              |   47 
 hw/grackle_pci.c                         |    8 
 hw/grlib.h                               |    4 
 hw/grlib_apbuart.c                       |    2 
 hw/grlib_gptimer.c                       |    4 
 hw/grlib_irqmp.c                         |    4 
 hw/gt64xxx.c                             |   12 
 hw/gumstix.c                             |  141 
 hw/gus.c                                 |   10 
 hw/gusemu_hal.c                          |    4 
 hw/gusemu_mixer.c                        |    4 
 hw/hda-audio.c                           |    8 
 hw/heathrow_pic.c                        |    4 
 hw/hid.c                                 |    4 
 hw/highbank.c                            |  342 -
 hw/hpet.c                                |   12 
 hw/hw.h                                  |    8 
 hw/i2c.c                                 |    2 
 hw/i2c.h                                 |    2 
 hw/i386/Makefile.objs                    |   17 
 hw/i386/kvmvapic.c                       |  820 ++++
 hw/i386/multiboot.c                      |  349 +
 hw/i386/pc.c                             | 1180 ++++++
 hw/i386/pc_piix.c                        |  718 +++
 hw/i386/pc_q35.c                         |  239 +
 hw/i386/smbios.c                         |  241 +
 hw/i386/xen_domainbuild.c                |  299 +
 hw/i386/xen_machine_pv.c                 |  126 
 hw/i82374.c                              |    2 
 hw/i82378.c                              |    8 
 hw/i8254.c                               |   10 
 hw/i8254.h                               |    4 
 hw/i8254_common.c                        |   10 
 hw/i8254_internal.h                      |    6 
 hw/i8259.c                               |    8 
 hw/i8259_common.c                        |    4 
 hw/i8259_internal.h                      |    6 
 hw/i82801b11.c                           |    6 
 hw/ich9.h                                |   37 
 hw/ide.h                                 |    4 
 hw/imx_avic.c                            |    4 
 hw/imx_ccm.c                             |    6 
 hw/imx_serial.c                          |    6 
 hw/imx_timer.c                           |    8 
 hw/integratorcp.c                        |  566 ---
 hw/intel-hda.c                           |   12 
 hw/intel-hda.h                           |    2 
 hw/ioapic.c                              |   10 
 hw/ioapic_common.c                       |    6 
 hw/ioapic_internal.h                     |    4 
 hw/ioh3420.c                             |   10 
 hw/ioh3420.h                             |    2 
 hw/ipack.c                               |    2 
 hw/ipack.h                               |    2 
 hw/ipoctal232.c                          |   44 
 hw/irq.c                                 |    2 
 hw/isa-bus.c                             |    6 
 hw/isa.h                                 |    2 
 hw/isa_mmio.c                            |    4 
 hw/ivshmem.c                             |    9 
 hw/jazz_led.c                            |   90 
 hw/kvm/arm_gic.c                         |  167 
 hw/kvmvapic.c                            |  822 ----
 hw/kzm.c                                 |  157 
 hw/lan9118.c                             |    6 
 hw/lance.c                               |    6 
 hw/leon3.c                               |  223 -
 hw/lm32/Makefile.objs                    |   10 
 hw/lm32/lm32_boards.c                    |  309 +
 hw/lm32/milkymist.c                      |  219 +
 hw/lm32_boards.c                         |  308 -
 hw/lm32_hwsetup.h                        |    2 
 hw/lm32_juart.c                          |    6 
 hw/lm32_pic.c                            |    8 
 hw/lm32_sys.c                            |    4 
 hw/lm32_timer.c                          |    6 
 hw/lm32_uart.c                           |    5 
 hw/lm4549.c                              |    4 
 hw/lm832x.c                              |    4 
 hw/loader.c                              |   87 
 hw/loader.h                              |    2 
 hw/lpc_ich9.c                            |   87 
 hw/lsi53c895a.c                          |    6 
 hw/m25p80.c                              |   64 
 hw/m48t59.c                              |    8 
 hw/m68k/Makefile.objs                    |    8 
 hw/m68k/an5206.c                         |  100 
 hw/m68k/dummy_m68k.c                     |   84 
 hw/m68k/mcf5206.c                        |  548 +++
 hw/m68k/mcf5208.c                        |  306 +
 hw/m68k/mcf_intc.c                       |  154 
 hw/mac_dbdma.c                           |   10 
 hw/mac_nvram.c                           |    6 
 hw/macio.c                               |   12 
 hw/mainstone.c                           |  190 -
 hw/marvell_88w8618_audio.c               |    8 
 hw/max111x.c                             |    2 
 hw/max7310.c                             |    2 
 hw/mc146818rtc.c                         |    6 
 hw/mc146818rtc.h                         |    4 
 hw/mcf5206.c                             |  548 ---
 hw/mcf5208.c                             |  306 -
 hw/mcf_fec.c                             |    4 
 hw/mcf_intc.c                            |  154 
 hw/mcf_uart.c                            |    5 
 hw/megasas.c                             |   12 
 hw/microblaze/Makefile.objs              |   11 
 hw/microblaze/boot.c                     |  177 
 hw/microblaze/petalogix_ml605_mmu.c      |  185 +
 hw/microblaze/petalogix_s3adsp1800_mmu.c |  127 
 hw/microblaze/pic_cpu.c                  |   47 
 hw/microblaze_boot.c                     |  177 
 hw/microblaze_boot.h                     |    2 
 hw/microblaze_pic_cpu.c                  |   44 
 hw/milkymist-ac97.c                      |    4 
 hw/milkymist-hpdmc.c                     |    4 
 hw/milkymist-hw.h                        |   30 
 hw/milkymist-memcard.c                   |    6 
 hw/milkymist-minimac2.c                  |   11 
 hw/milkymist-pfpu.c                      |    4 
 hw/milkymist-softusb.c                   |   29 
 hw/milkymist-sysctl.c                    |    6 
 hw/milkymist-tmu2.c                      |    4 
 hw/milkymist-uart.c                      |    5 
 hw/milkymist-vgafb.c                     |   33 
 hw/milkymist.c                           |  218 -
 hw/mips/Makefile.objs                    |    8 
 hw/mips/addr.c                           |   34 
 hw/mips/cputimer.c                       |  147 
 hw/mips/mips_fulong2e.c                  |  411 ++
 hw/mips/mips_int.c                       |   67 
 hw/mips/mips_jazz.c                      |  345 +
 hw/mips/mips_malta.c                     | 1037 +++++
 hw/mips/mips_mipssim.c                   |  240 +
 hw/mips/mips_r4k.c                       |  313 +
 hw/mips_addr.c                           |   34 
 hw/mips_fulong2e.c                       |  411 --
 hw/mips_int.c                            |   65 
 hw/mips_jazz.c                           |  345 -
 hw/mips_malta.c                          | 1037 -----
 hw/mips_mipssim.c                        |  240 -
 hw/mips_r4k.c                            |  313 -
 hw/mips_timer.c                          |  147 
 hw/mipsnet.c                             |    4 
 hw/moxie/Makefile.objs                   |    5 
 hw/moxie/moxiesim.c                      |  174 
 hw/mpc8544_guts.c                        |  143 
 hw/msmouse.c                             |   78 
 hw/msmouse.h                             |    7 
 hw/mst_fpga.c                            |    4 
 hw/multiboot.c                           |  349 -
 hw/musicpal.c                            | 1697 ---------
 hw/nand.c                                |   10 
 hw/ne2000-isa.c                          |   10 
 hw/ne2000.c                              |   10 
 hw/nseries.c                             | 1430 -------
 hw/omap1.c                               | 4056 ----------------------
 hw/omap2.c                               | 2684 --------------
 hw/omap_clk.c                            |    4 
 hw/omap_dma.c                            |    6 
 hw/omap_dss.c                            |    4 
 hw/omap_gpio.c                           |    6 
 hw/omap_gpmc.c                           |    6 
 hw/omap_gptimer.c                        |    4 
 hw/omap_i2c.c                            |    8 
 hw/omap_intc.c                           |    6 
 hw/omap_l4.c                             |    4 
 hw/omap_lcdc.c                           |   61 
 hw/omap_mmc.c                            |    6 
 hw/omap_sdrc.c                           |    4 
 hw/omap_spi.c                            |    4 
 hw/omap_sx1.c                            |  238 -
 hw/omap_synctimer.c                      |    4 
 hw/omap_tap.c                            |    4 
 hw/omap_uart.c                           |    6 
 hw/onenand.c                             |   11 
 hw/opencores_eth.c                       |    4 
 hw/openpic.c                             |   14 
 hw/openrisc/Makefile.objs                |    5 
 hw/openrisc/cputimer.c                   |  103 
 hw/openrisc/openrisc_sim.c               |  150 
 hw/openrisc/pic_cpu.c                    |   61 
 hw/openrisc_pic.c                        |   60 
 hw/openrisc_sim.c                        |  150 
 hw/openrisc_timer.c                      |  101 
 hw/palm.c                                |  291 -
 hw/pam.c                                 |    2 
 hw/parallel.c                            |    6 
 hw/pc-testdev.c                          |    6 
 hw/pc.c                                  | 1161 ------
 hw/pc.h                                  |   39 
 hw/pc87312.c                             |    3 
 hw/pc87312.h                             |    2 
 hw/pc_piix.c                             |  713 ---
 hw/pc_q35.c                              |  239 -
 hw/pc_sysfw.c                            |   11 
 hw/pci/pci-hotplug.c                     |    2 
 hw/pci/pci.c                             |  121 
 hw/pci/pci.h                             |   35 
 hw/pci/pci_bridge.c                      |   51 
 hw/pci/pci_bridge.h                      |   17 
 hw/pci/pci_bus.h                         |   10 
 hw/pci/pci_host.c                        |    2 
 hw/pci/pci_host.h                        |    1 
 hw/pci/pcie.c                            |   16 
 hw/pci/pcie.h                            |    1 
 hw/pci/pcie_port.c                       |   18 
 hw/pci/shpc.c                            |    3 
 hw/pci/slotid_cap.c                      |    1 
 hw/pci_bridge_dev.c                      |   23 
 hw/pckbd.c                               |    8 
 hw/pcnet-pci.c                           |    8 
 hw/pcnet.c                               |    4 
 hw/pcspk.c                               |   10 
 hw/pcspk.h                               |    4 
 hw/petalogix_ml605_mmu.c                 |  187 -
 hw/petalogix_s3adsp1800_mmu.c            |  127 
 hw/pflash_cfi01.c                        |   50 
 hw/pflash_cfi02.c                        |    6 
 hw/piix4.c                               |   10 
 hw/piix_pci.c                            |   49 
 hw/pl011.c                               |    2 
 hw/pl022.c                               |    4 
 hw/pl031.c                               |    2 
 hw/pl041.c                               |    6 
 hw/pl050.c                               |    9 
 hw/pl061.c                               |    2 
 hw/pl080.c                               |    2 
 hw/pl110.c                               |   38 
 hw/pl110_template.h                      |   12 
 hw/pl181.c                               |    4 
 hw/pl190.c                               |    2 
 hw/pl330.c                               | 1653 +++++++++
 hw/pm_smbus.c                            |    8 
 hw/ppc.c                                 | 1356 -------
 hw/ppc/Makefile.objs                     |   29 
 hw/ppc/e500-ccsr.h                       |    2 
 hw/ppc/e500.c                            |   10 
 hw/ppc/e500plat.c                        |    2 
 hw/ppc/mac_newworld.c                    |    2 
 hw/ppc/mpc8544_guts.c                    |  143 
 hw/ppc/mpc8544ds.c                       |    2 
 hw/ppc/ppc.c                             | 1364 +++++++
 hw/ppc/ppc405_boards.c                   |  662 +++
 hw/ppc/ppc405_uc.c                       | 2548 ++++++++++++++
 hw/ppc/ppc440_bamboo.c                   |  306 +
 hw/ppc/ppc4xx_devs.c                     |  721 ++++
 hw/ppc/ppc_booke.c                       |  273 +
 hw/ppc/ppce500_spin.c                    |  222 +
 hw/ppc/prep.c                            |    1 
 hw/ppc/spapr.c                           |  970 +++++
 hw/ppc/spapr_events.c                    |  321 +
 hw/ppc/spapr_hcall.c                     |  740 ++++
 hw/ppc/spapr_iommu.c                     |  293 +
 hw/ppc/spapr_rtas.c                      |  334 +
 hw/ppc/spapr_vio.c                       |  649 +++
 hw/ppc/virtex_ml507.c                    |  274 +
 hw/ppc/xics.c                            |  581 +++
 hw/ppc405.h                              |    2 
 hw/ppc405_boards.c                       |  662 ---
 hw/ppc405_uc.c                           | 2548 --------------
 hw/ppc440_bamboo.c                       |  306 -
 hw/ppc4xx.h                              |    2 
 hw/ppc4xx_devs.c                         |  721 ----
 hw/ppc4xx_pci.c                          |   12 
 hw/ppc_booke.c                           |  273 -
 hw/ppce500_pci.c                         |   10 
 hw/ppce500_spin.c                        |  222 -
 hw/prep_pci.c                            |   12 
 hw/ps2.c                                 |    4 
 hw/ptimer.c                              |    4 
 hw/puv3.c                                |  135 
 hw/puv3_dma.c                            |    6 
 hw/puv3_gpio.c                           |    6 
 hw/puv3_intc.c                           |    4 
 hw/puv3_ost.c                            |    6 
 hw/puv3_pm.c                             |    6 
 hw/pxa2xx.c                              | 2291 ------------
 hw/pxa2xx_dma.c                          |    6 
 hw/pxa2xx_gpio.c                         |  350 -
 hw/pxa2xx_keypad.c                       |    4 
 hw/pxa2xx_lcd.c                          |   55 
 hw/pxa2xx_mmci.c                         |    8 
 hw/pxa2xx_pcmcia.c                       |    6 
 hw/pxa2xx_pic.c                          |  334 -
 hw/pxa2xx_timer.c                        |    6 
 hw/q35.c                                 |    7 
 hw/q35.h                                 |   22 
 hw/qdev-addr.c                           |    7 
 hw/qdev-core.h                           |    3 
 hw/qdev-monitor.c                        |  683 ---
 hw/qdev-monitor.h                        |   16 
 hw/qdev-properties-system.c              |   15 
 hw/qdev-properties.c                     |  144 
 hw/qdev-properties.h                     |   53 
 hw/qdev.c                                |   37 
 hw/qdev.h                                |    5 
 hw/qxl-logger.c                          |    2 
 hw/qxl-render.c                          |   23 
 hw/qxl.c                                 |   63 
 hw/qxl.h                                 |    6 
 hw/r2d.c                                 |  364 --
 hw/rc4030.c                              |    4 
 hw/realview.c                            |  404 --
 hw/realview_gic.c                        |    2 
 hw/rtl8139.c                             |    8 
 hw/s390x/css.c                           |   11 
 hw/s390x/event-facility.c                |    4 
 hw/s390x/s390-virtio-bus.c               |   58 
 hw/s390x/s390-virtio-bus.h               |   24 
 hw/s390x/s390-virtio-ccw.c               |    5 
 hw/s390x/s390-virtio.c                   |   14 
 hw/s390x/sclp.c                          |    2 
 hw/s390x/sclpconsole.c                   |    5 
 hw/s390x/sclpquiesce.c                   |    4 
 hw/s390x/virtio-ccw.c                    |  144 
 hw/s390x/virtio-ccw.h                    |   39 
 hw/sb16.c                                |    8 
 hw/sbi.c                                 |    2 
 hw/scsi-bus.c                            |   20 
 hw/scsi-disk.c                           |   40 
 hw/scsi-generic.c                        |    4 
 hw/scsi.h                                |    5 
 hw/sd.c                                  |    6 
 hw/sdhci.c                               | 1300 +++++++
 hw/sdhci.h                               |  312 +
 hw/serial-isa.c                          |    4 
 hw/serial-pci.c                          |    4 
 hw/serial.c                              |   34 
 hw/serial.h                              |    4 
 hw/sga.c                                 |    6 
 hw/sh.h                                  |    2 
 hw/sh4/Makefile.objs                     |    6 
 hw/sh4/r2d.c                             |  364 ++
 hw/sh4/sh7750.c                          |  842 ++++
 hw/sh4/sh7750_regnames.c                 |   97 
 hw/sh4/shix.c                            |  103 
 hw/sh7750.c                              |  838 ----
 hw/sh7750_regnames.c                     |   97 
 hw/sh_intc.c                             |   20 
 hw/sh_intc.h                             |    2 
 hw/sh_pci.c                              |   10 
 hw/sh_serial.c                           |    8 
 hw/sh_timer.c                            |    6 
 hw/shix.c                                |  103 
 hw/slavio_intctl.c                       |    4 
 hw/slavio_misc.c                         |    2 
 hw/slavio_timer.c                        |    6 
 hw/sm501.c                               |   58 
 hw/smbios.c                              |  241 -
 hw/smbus.c                               |    6 
 hw/smbus.h                               |    2 
 hw/smbus_eeprom.c                        |    6 
 hw/smbus_ich9.c                          |   14 
 hw/smc91c111.c                           |    4 
 hw/soc_dma.c                             |    2 
 hw/spapr.c                               |  963 -----
 hw/spapr_events.c                        |  321 -
 hw/spapr_hcall.c                         |  741 ----
 hw/spapr_iommu.c                         |  293 -
 hw/spapr_llan.c                          |   10 
 hw/spapr_pci.c                           |   42 
 hw/spapr_pci.h                           |    4 
 hw/spapr_rtas.c                          |  334 -
 hw/spapr_vio.c                           |  649 ---
 hw/spapr_vscsi.c                         |    8 
 hw/spapr_vty.c                           |    2 
 hw/sparc/Makefile.objs                   |    6 
 hw/sparc/leon3.c                         |  227 +
 hw/sparc/sun4m.c                         | 1944 ++++++++++
 hw/sparc32_dma.c                         |    8 
 hw/sparc64/Makefile.objs                 |    4 
 hw/sparc64/sun4u.c                       | 1020 +++++
 hw/spitz.c                               | 1138 ------
 hw/ssd0303.c                             |   19 
 hw/ssd0323.c                             |   21 
 hw/ssi-sd.c                              |    4 
 hw/ssi.c                                 |    2 
 hw/ssi.h                                 |    2 
 hw/stellaris.c                           | 1401 -------
 hw/stellaris_enet.c                      |    2 
 hw/stellaris_input.c                     |    4 
 hw/stream.c                              |    2 
 hw/strongarm.c                           |    8 
 hw/sun4c_intctl.c                        |    6 
 hw/sun4m.c                               | 1936 ----------
 hw/sun4m.h                               |    2 
 hw/sun4m_iommu.c                         |    4 
 hw/sun4u.c                               | 1014 -----
 hw/sysbus.c                              |   50 
 hw/sysbus.h                              |    9 
 hw/tc58128.c                             |    6 
 hw/tc6393xb.c                            |   44 
 hw/tc6393xb_template.h                   |    5 
 hw/tcx.c                                 |   68 
 hw/tmp105.c                              |    6 
 hw/tmp105.h                              |    4 
 hw/tosa.c                                |  302 -
 hw/tpci200.c                             |    4 
 hw/tsc2005.c                             |    4 
 hw/tsc210x.c                             |    6 
 hw/tusb6010.c                            |   10 
 hw/twl92230.c                            |    4 
 hw/unicore32/Makefile.objs               |    2 
 hw/unicore32/puv3.c                      |  137 
 hw/unin_pci.c                            |   12 
 hw/usb.h                                 |    2 
 hw/usb/dev-network.c                     |    1 
 hw/usb/dev-serial.c                      |    2 
 hw/usb/dev-storage.c                     |    2 
 hw/usb/hcd-xhci.c                        |    2 
 hw/usb/redirect.c                        |    4 
 hw/versatile_i2c.c                       |    4 
 hw/versatile_pci.c                       |    8 
 hw/versatilepb.c                         |  403 --
 hw/vexpress.c                            |  500 --
 hw/vfio_pci.c                            | 1180 ++++++
 hw/vga-isa-mm.c                          |   11 
 hw/vga-isa.c                             |   12 
 hw/vga-pci.c                             |   12 
 hw/vga.c                                 |  135 
 hw/vga_int.h                             |    2 
 hw/vhost.c                               |   51 
 hw/vhost_net.c                           |    6 
 hw/virtex_ml507.c                        |  274 -
 hw/virtio-balloon.c                      |  131 
 hw/virtio-balloon.h                      |   21 
 hw/virtio-blk.c                          |  157 
 hw/virtio-blk.h                          |   41 
 hw/virtio-bus.c                          |    8 
 hw/virtio-bus.h                          |    4 
 hw/virtio-console.c                      |   54 
 hw/virtio-net.c                          |   83 
 hw/virtio-net.h                          |   54 
 hw/virtio-pci.c                          |  474 +-
 hw/virtio-pci.h                          |   60 
 hw/virtio-rng.c                          |   26 
 hw/virtio-rng.h                          |   19 
 hw/virtio-scsi.c                         |  140 
 hw/virtio-scsi.h                         |   42 
 hw/virtio-serial-bus.c                   |   84 
 hw/virtio-serial.h                       |   51 
 hw/virtio.c                              |    4 
 hw/virtio.h                              |   12 
 hw/vmmouse.c                             |    8 
 hw/vmport.c                              |    8 
 hw/vmware_utils.h                        |  143 
 hw/vmware_vga.c                          |  115 
 hw/vmxnet3.c                             | 2461 +++++++++++++
 hw/vmxnet3.h                             |  760 ++++
 hw/vmxnet_debug.h                        |  115 
 hw/vmxnet_rx_pkt.c                       |  187 +
 hw/vmxnet_rx_pkt.h                       |  174 
 hw/vmxnet_tx_pkt.c                       |  567 +++
 hw/vmxnet_tx_pkt.h                       |  148 
 hw/vt82c686.c                            |   28 
 hw/wdt_i6300esb.c                        |    6 
 hw/wdt_ib700.c                           |    8 
 hw/wm8750.c                              |    4 
 hw/xen-host-pci-device.c                 |    2 
 hw/xen-host-pci-device.h                 |    2 
 hw/xen_apic.c                            |    2 
 hw/xen_backend.c                         |   19 
 hw/xen_backend.h                         |    4 
 hw/xen_common.h                          |    4 
 hw/xen_console.c                         |   22 
 hw/xen_devconfig.c                       |    2 
 hw/xen_disk.c                            |   84 
 hw/xen_domainbuild.c                     |  299 -
 hw/xen_domainbuild.h                     |    2 
 hw/xen_machine_pv.c                      |  126 
 hw/xen_nic.c                             |    4 
 hw/xen_platform.c                        |   12 
 hw/xen_pt.c                              |    8 
 hw/xen_pt.h                              |    6 
 hw/xen_pt_config_init.c                  |    4 
 hw/xen_pt_msi.c                          |    6 
 hw/xenfb.c                               |   61 
 hw/xgmac.c                               |    2 
 hw/xics.c                                |  588 ---
 hw/xics.h                                |    3 
 hw/xilinx.h                              |    3 
 hw/xilinx_axidma.c                       |    8 
 hw/xilinx_axienet.c                      |    7 
 hw/xilinx_ethlite.c                      |    4 
 hw/xilinx_intc.c                         |    4 
 hw/xilinx_spi.c                          |    6 
 hw/xilinx_spips.c                        |   72 
 hw/xilinx_timer.c                        |    4 
 hw/xilinx_uartlite.c                     |    2 
 hw/xilinx_zynq.c                         |  215 -
 hw/xio3130_downstream.c                  |   10 
 hw/xio3130_downstream.h                  |    2 
 hw/xio3130_upstream.c                    |   10 
 hw/xio3130_upstream.h                    |    2 
 hw/xtensa/Makefile.objs                  |    4 
 hw/xtensa/pic_cpu.c                      |  166 
 hw/xtensa/xtensa_lx60.c                  |  315 +
 hw/xtensa/xtensa_sim.c                   |  117 
 hw/xtensa_lx60.c                         |  315 -
 hw/xtensa_pic.c                          |  164 
 hw/xtensa_sim.c                          |  117 
 hw/z2.c                                  |  384 --
 hw/zaurus.c                              |    6 
 hw/zynq_slcr.c                           |    4 
 include/backends/tpm.h                   |  170 
 include/block/aio.h                      |    6 
 include/block/block.h                    |    7 
 include/block/block_int.h                |   20 
 include/block/coroutine.h                |    1 
 include/block/nbd.h                      |    4 
 include/block/thread-pool.h              |   15 
 include/char/char.h                      |   86 
 include/disas/bfd.h                      |    2 
 include/exec/cpu-all.h                   |   15 
 include/exec/cpu-defs.h                  |    2 
 include/exec/gen-icount.h                |   18 
 include/glib-compat.h                    |   27 
 include/migration/migration.h            |   14 
 include/migration/page_cache.h           |    3 
 include/migration/qemu-file.h            |   29 
 include/migration/vmstate.h              |  118 
 include/monitor/monitor.h                |    1 
 include/monitor/qdev.h                   |   15 
 include/net/checksum.h                   |   26 
 include/net/eth.h                        |  347 +
 include/net/net.h                        |    7 
 include/qapi/qmp/qdict.h                 |    2 
 include/qapi/qmp/qstring.h               |    1 
 include/qemu-common.h                    |   39 
 include/qemu/atomic.h                    |    1 
 include/qemu/compiler.h                  |    2 
 include/qemu/fifo8.h                     |   99 
 include/qemu/main-loop.h                 |    5 
 include/qemu/option.h                    |    1 
 include/qemu/osdep.h                     |    7 
 include/qemu/sockets.h                   |   10 
 include/qemu/timer.h                     |    3 
 include/qom/cpu.h                        |   66 
 include/qom/object.h                     |    2 
 include/sysemu/arch_init.h               |    4 
 include/sysemu/blockdev.h                |    2 
 include/sysemu/sysemu.h                  |    6 
 include/tpm/tpm.h                        |   25 
 include/ui/console.h                     |  278 -
 include/ui/qemu-spice.h                  |    7 
 include/ui/spice-display.h               |    9 
 kvm-all.c                                |    6 
 linux-headers/asm-arm/kvm.h              |  180 +
 linux-headers/asm-arm/kvm_para.h         |    1 
 linux-headers/asm-generic/kvm_para.h     |    4 
 linux-headers/linux/kvm.h                |   17 
 linux-headers/linux/vfio.h               |    9 
 linux-user/main.c                        |  125 
 linux-user/mips64/syscall.h              |   18 
 linux-user/mips64/syscall_nr.h           |  920 +++--
 linux-user/mipsn32/syscall.h             |  224 -
 linux-user/mipsn32/syscall_nr.h          |  311 -
 linux-user/mipsn32/target_signal.h       |   29 
 linux-user/mipsn32/termbits.h            |  245 -
 linux-user/signal.c                      |  245 -
 linux-user/socket.h                      |   69 
 linux-user/sparc/syscall_nr.h            |    2 
 linux-user/strace.c                      |  105 
 linux-user/syscall.c                     |  134 
 main-loop.c                              |   30 
 memory.c                                 |    2 
 migration-exec.c                         |   39 
 migration-fd.c                           |   47 
 migration-tcp.c                          |   33 
 migration-unix.c                         |   33 
 migration.c                              |  362 --
 monitor.c                                |  129 
 nbd.c                                    |   21 
 net/Makefile.objs                        |    1 
 net/checksum.c                           |   42 
 net/eth.c                                |  217 +
 net/hub.c                                |   14 
 net/hub.h                                |    1 
 net/net.c                                |   27 
 net/queue.c                              |   15 
 net/slirp.c                              |    1 
 net/socket.c                             |   41 
 net/tap-linux.c                          |   10 
 net/tap-linux.h                          |    9 
 net/tap.c                                |   14 
 net/vde.c                                |    2 
 page_cache.c                             |   25 
 pc-bios/bios.bin                         |binary
 pc-bios/efi-e1000.rom                    |binary
 pc-bios/efi-eepro100.rom                 |binary
 pc-bios/efi-ne2k_pci.rom                 |binary
 pc-bios/efi-pcnet.rom                    |binary
 pc-bios/efi-rtl8139.rom                  |binary
 pc-bios/efi-virtio.rom                   |binary
 po/Makefile                              |   16 
 po/de_DE.po                              |   41 
 po/fr_FR.po                              |   62 
 po/it.po                                 |   41 
 po/messages.po                           |   36 
 qapi-schema.json                         |  293 +
 qdev-monitor.c                           |  684 +++
 qemu-bridge-helper.c                     |   18 
 qemu-char.c                              | 1296 ++++---
 qemu-coroutine-lock.c                    |   55 
 qemu-doc.texi                            |   22 
 qemu-img.c                               |    6 
 qemu-io.c                                |    4 
 qemu-nbd.c                               |    2 
 qemu-options.hx                          |  119 
 qga/channel-win32.c                      |    2 
 qga/commands-posix.c                     |  270 +
 qga/commands-win32.c                     |   23 
 qga/guest-agent-core.h                   |    1 
 qga/main.c                               |  185 +
 qga/qapi-schema.json                     |  111 
 qga/service-win32.c                      |    2 
 qmp-commands.hx                          |  155 
 qobject/qdict.c                          |   22 
 qobject/qstring.c                        |    8 
 qom/cpu.c                                |    7 
 qom/object.c                             |   19 
 qtest.c                                  |    2 
 roms/Makefile                            |   49 
 roms/config.ipxe.general.h               |    2 
 roms/configure-seabios.sh                |    2 
 roms/ipxe                                |    2 
 roms/seabios                             |    2 
 savevm.c                                 |  351 +
 scripts/make_device_config.sh            |    4 
 scripts/tracetool.py                     |    4 
 scripts/tracetool/backend/__init__.py    |   16 
 scripts/tracetool/backend/dtrace.py      |    3 
 scripts/tracetool/backend/events.py      |   23 
 scripts/tracetool/backend/simple.py      |   22 
 scripts/tracetool/backend/stderr.py      |   28 
 scripts/tracetool/backend/ust.py         |    3 
 scripts/tracetool/format/events_c.py     |   39 
 scripts/tracetool/format/events_h.py     |   50 
 scripts/tracetool/format/h.py            |    9 
 slirp/misc.c                             |    6 
 slirp/socket.c                           |    4 
 slirp/tcp_subr.c                         |  145 
 slirp/udp.c                              |    2 
 spice-qemu-char.c                        |  112 
 stubs/Makefile.objs                      |    1 
 stubs/pci-drive-hot-add.c                |   10 
 stubs/vmstate.c                          |    2 
 target-alpha/cpu-qom.h                   |    3 
 target-alpha/cpu.c                       |    1 
 target-alpha/cpu.h                       |    5 
 target-alpha/helper.c                    |    4 
 target-alpha/translate.c                 |    7 
 target-arm/Makefile.objs                 |    1 
 target-arm/cpu-qom.h                     |    5 
 target-arm/cpu.c                         |   15 
 target-arm/cpu.h                         |    6 
 target-arm/helper.c                      |   36 
 target-arm/kvm.c                         |  493 ++
 target-arm/kvm_arm.h                     |   32 
 target-arm/op_helper.c                   |    4 
 target-arm/translate.c                   |  145 
 target-cris/cpu-qom.h                    |    3 
 target-cris/cpu.c                        |    1 
 target-cris/cpu.h                        |    5 
 target-cris/helper.c                     |  402 +-
 target-cris/translate.c                  |    7 
 target-i386/cpu-qom.h                    |   11 
 target-i386/cpu.c                        |   29 
 target-i386/cpu.h                        |   29 
 target-i386/fpu_helper.c                 |    1 
 target-i386/helper.c                     |   20 
 target-i386/kvm.c                        |   50 
 target-i386/machine.c                    |  215 -
 target-i386/misc_helper.c                |   21 
 target-i386/ops_sse.h                    |   64 
 target-i386/seg_helper.c                 |    5 
 target-i386/svm_helper.c                 |    9 
 target-i386/translate.c                  |   12 
 target-lm32/cpu-qom.h                    |    7 
 target-lm32/cpu.c                        |    7 
 target-lm32/cpu.h                        |   17 
 target-lm32/helper.c                     |   12 
 target-lm32/machine.c                    |   25 
 target-lm32/op_helper.c                  |   24 
 target-lm32/translate.c                  |   27 
 target-m68k/cpu-qom.h                    |    3 
 target-m68k/cpu.c                        |    1 
 target-m68k/cpu.h                        |    5 
 target-m68k/helper.c                     |   10 
 target-m68k/op_helper.c                  |   14 
 target-m68k/qregs.def                    |    1 
 target-m68k/translate.c                  |   12 
 target-microblaze/cpu-qom.h              |    3 
 target-microblaze/cpu.c                  |    1 
 target-microblaze/cpu.h                  |    5 
 target-microblaze/helper.c               |    9 
 target-microblaze/op_helper.c            |    2 
 target-microblaze/translate.c            |   21 
 target-mips/cpu-qom.h                    |    3 
 target-mips/cpu.c                        |    2 
 target-mips/cpu.h                        |    8 
 target-mips/dsp_helper.c                 |  129 
 target-mips/helper.c                     |    5 
 target-mips/op_helper.c                  |   23 
 target-mips/translate.c                  |  168 
 target-moxie/Makefile.objs               |    2 
 target-moxie/cpu.c                       |  173 
 target-moxie/cpu.h                       |  167 
 target-moxie/helper.c                    |  174 
 target-moxie/helper.h                    |    9 
 target-moxie/machine.c                   |   28 
 target-moxie/machine.h                   |    1 
 target-moxie/mmu.c                       |   36 
 target-moxie/mmu.h                       |   19 
 target-moxie/translate.c                 |  926 +++++
 target-openrisc/cpu.c                    |    1 
 target-openrisc/cpu.h                    |    8 
 target-openrisc/interrupt.c              |    4 
 target-openrisc/interrupt_helper.c       |    3 
 target-openrisc/sys_helper.c             |    3 
 target-openrisc/translate.c              |    4 
 target-ppc/Makefile.objs                 |    8 
 target-ppc/cpu-models.c                  | 1419 +++++++
 target-ppc/cpu-models.h                  |  741 ++++
 target-ppc/cpu-qom.h                     |   24 
 target-ppc/cpu.h                         |  123 
 target-ppc/excp_helper.c                 |   34 
 target-ppc/fpu_helper.c                  |    5 
 target-ppc/helper.h                      |    1 
 target-ppc/helper_regs.h                 |   11 
 target-ppc/kvm.c                         |  330 +
 target-ppc/machine.c                     |    4 
 target-ppc/mem_helper.c                  |   38 
 target-ppc/misc_helper.c                 |    6 
 target-ppc/mmu-hash32.c                  |  560 +++
 target-ppc/mmu-hash32.h                  |  102 
 target-ppc/mmu-hash64.c                  |  546 +++
 target-ppc/mmu-hash64.h                  |  124 
 target-ppc/mmu_helper.c                  |  835 ----
 target-ppc/translate.c                   |  233 -
 target-ppc/translate_init.c              | 5578 +++++++++----------------------
 target-ppc/user_only_helper.c            |   44 
 target-s390x/cpu-qom.h                   |    3 
 target-s390x/cpu.c                       |    9 
 target-s390x/cpu.h                       |   14 
 target-s390x/helper.c                    |   19 
 target-s390x/ioinst.c                    |    2 
 target-s390x/kvm.c                       |   12 
 target-s390x/translate.c                 |    7 
 target-sh4/cpu-qom.h                     |   16 
 target-sh4/cpu.c                         |  181 +
 target-sh4/cpu.h                         |    8 
 target-sh4/helper.c                      |   13 
 target-sh4/op_helper.c                   |    4 
 target-sh4/translate.c                   |   88 
 target-sparc/cpu-qom.h                   |    3 
 target-sparc/cpu.c                       |    2 
 target-sparc/cpu.h                       |    6 
 target-sparc/helper.c                    |    4 
 target-sparc/int32_helper.c              |    4 
 target-sparc/int64_helper.c              |    4 
 target-sparc/translate.c                 |    4 
 target-unicore32/cpu-qom.h               |    3 
 target-unicore32/cpu.c                   |    1 
 target-unicore32/cpu.h                   |    5 
 target-unicore32/helper.c                |    5 
 target-unicore32/softmmu.c               |    6 
 target-unicore32/translate.c             |    4 
 target-xtensa/cpu-qom.h                  |    3 
 target-xtensa/cpu.c                      |    1 
 target-xtensa/cpu.h                      |    1 
 target-xtensa/helper.c                   |    5 
 target-xtensa/op_helper.c                |    5 
 target-xtensa/translate.c                |    4 
 tcg/README                               |   14 
 tcg/mips/tcg-target.c                    |    6 
 tcg/mips/tcg-target.h                    |    2 
 tcg/optimize.c                           |   34 
 tcg/sparc/tcg-target.c                   |    2 
 tcg/tcg.h                                |   49 
 tests/qemu-iotests/007                   |    7 
 tests/qemu-iotests/038.out               |   10 
 tests/qemu-iotests/044.out               |    4 
 tests/qemu-iotests/046                   |   49 
 tests/qemu-iotests/046.out               |   76 
 tests/qemu-iotests/050                   |   75 
 tests/qemu-iotests/050.out               |   17 
 tests/qemu-iotests/052                   |   61 
 tests/qemu-iotests/052.out               |   13 
 tests/qemu-iotests/group                 |    2 
 tests/rtc-test.c                         |    4 
 tests/tcg/lm32/test_cmpgei.S             |   15 
 tests/tcg/lm32/test_cmpgeui.S            |   15 
 tests/tcg/lm32/test_cmpgi.S              |   15 
 tests/tcg/lm32/test_cmpgui.S             |   17 
 tests/tcg/mips/mips32-dsp/extr_r_w.c     |   23 
 tests/tcg/mips/mips32-dsp/extr_rs_w.c    |   46 
 tests/tcg/mips/mips32-dsp/extr_w.c       |   23 
 tests/tcg/mips/mips32-dsp/subq_s_ph.c    |   22 
 tests/tcg/mips/mips32-dsp/subq_s_w.c     |   36 
 tests/test-thread-pool.c                 |   44 
 tests/test-visitor-serialization.c       |   12 
 thread-pool.c                            |  243 -
 tpm/Makefile.objs                        |    6 
 tpm/tpm.c                                |  365 ++
 tpm/tpm_backend.c                        |   58 
 tpm/tpm_backend.h                        |   45 
 tpm/tpm_int.h                            |   95 
 tpm/tpm_passthrough.c                    |  560 +++
 tpm/tpm_tis.c                            |  930 +++++
 tpm/tpm_tis.h                            |   80 
 trace-events                             |   19 
 trace/Makefile.objs                      |   24 
 trace/control-internal.h                 |   67 
 trace/control.c                          |  106 
 trace/control.h                          |  190 -
 trace/default.c                          |    5 
 trace/event-internal.h                   |   33 
 trace/simple.c                           |   35 
 trace/simple.h                           |    6 
 trace/stderr.c                           |   34 
 trace/stderr.h                           |   11 
 translate-all.c                          |   95 
 ui/cocoa.m                               |   60 
 ui/console.c                             |  538 +-
 ui/curses.c                              |   28 
 ui/gtk.c                                 |  234 -
 ui/sdl.c                                 |  118 
 ui/spice-display.c                       |   81 
 ui/vnc-enc-tight.c                       |    7 
 ui/vnc-jobs.c                            |    1 
 ui/vnc.c                                 |  145 
 ui/vnc.h                                 |    4 
 util/Makefile.objs                       |    2 
 util/bitops.c                            |   18 
 util/cutils.c                            |   60 
 util/fifo8.c                             |   79 
 util/hexdump.c                           |   37 
 util/iov.c                               |   36 
 util/osdep.c                             |    8 
 util/oslib-posix.c                       |    6 
 util/oslib-win32.c                       |    4 
 util/qemu-config.c                       |    1 
 util/qemu-option.c                       |   34 
 util/qemu-sockets.c                      |   72 
 util/qemu-timer-common.c                 |    4 
 vl.c                                     |  137 
 xen-all.c                                |   10 
 xen-mapcache.c                           |   58 
 1081 files changed, 84275 insertions(+), 62622 deletions(-)

New commits:
commit 9196dd411d580c27f85daa209ff9a501d719ebc0
Merge: 893986f 32aea75
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Apr 6 12:53:54 2013 +0000

    Merge branch 'arm-devs.next' of git://git.linaro.org/people/pmaydell/qemu-arm
    
    * 'arm-devs.next' of git://git.linaro.org/people/pmaydell/qemu-arm:
      hw/nand.c: Fix nand erase operation
      cadence_uart: Flush queued characters on reset
      pl330: Don't inhibit ES bits on INTEN
      pflash_cfi01: Implement migration support
      pflash_cfi01: Drop unused 'bypass' field
      hw/arm_gic_common: Use vmstate struct rather than save/load functions
      arm_gic: Fix sizes of state fields in preparation for vmstate support
      vmstate: Add support for two dimensional arrays
      hw/onenand.c: fix migration of dynamically allocated buffer "otp"
      hw/sd.c: fix migration of dynamically allocated buffer "buf"
      vmstate.h: introduce VMSTATE_BUFFER_POINTER_UNSAFE macro
      hw/arm_mptimer: Save the timer state
      pl050: Don't send always-constant is_mouse field
      hw/arm/nseries: don't print to stdout or stderr

commit 893986fe94eb229f2317f50fac0e35e068eb66ba
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 5 08:46:00 2013 -0500

    main-loop: drop the BQL if the I/O appears to be spinning
    
    The char-flow refactoring introduced a busy-wait that depended on
    an action from the VCPU thread.  However, the VCPU thread could
    never take that action because the busy-wait starved the VCPU thread
    of the BQL because it never dropped the mutex while running select.
    
    Paolo doesn't want to drop this optimization for fear that we will
    stop detecting these busy waits.  I'm afraid to keep this optimization
    even with the busy-wait fixed because I think a similar problem can
    occur just with heavy I/O thread load manifesting itself as VCPU pauses.
    
    As a compromise, introduce an artificial timeout after a thousand
    iterations but print a rate limited warning when this happens.  This
    let's us still detect when this condition occurs without it being
    a fatal error.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1365169560-11012-1-git-send-email-aliguori at us.ibm.com

diff --git a/main-loop.c b/main-loop.c
index eb80ff3..f46aece 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -188,14 +188,39 @@ static void glib_pollfds_poll(void)
     }
 }
 
+#define MAX_MAIN_LOOP_SPIN (1000)
+
 static int os_host_main_loop_wait(uint32_t timeout)
 {
     int ret;
+    static int spin_counter;
 
     glib_pollfds_fill(&timeout);
 
+    /* If the I/O thread is very busy or we are incorrectly busy waiting in
+     * the I/O thread, this can lead to starvation of the BQL such that the
+     * VCPU threads never run.  To make sure we can detect the later case,
+     * print a message to the screen.  If we run into this condition, create
+     * a fake timeout in order to give the VCPU threads a chance to run.
+     */
+    if (spin_counter > MAX_MAIN_LOOP_SPIN) {
+        static bool notified;
+
+        if (!notified) {
+            fprintf(stderr,
+                    "main-loop: WARNING: I/O thread spun for %d iterations\n",
+                    MAX_MAIN_LOOP_SPIN);
+            notified = true;
+        }
+
+        timeout = 1;
+    }
+
     if (timeout > 0) {
+        spin_counter = 0;
         qemu_mutex_unlock_iothread();
+    } else {
+        spin_counter++;
     }
 
     ret = g_poll((GPollFD *)gpollfds->data, gpollfds->len, timeout);
commit d185c094b404b4ff392b77d1244c0233da7d53bd
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Apr 5 17:59:33 2013 +0200

    qemu-char: eliminate busy waiting on can_read returning zero
    
    The character backend refactoring introduced an undesirable busy wait.
    The busy wait happens if can_read returns zero and there is data available
    on the character device's file descriptor.  Then, the I/O watch will
    fire continuously and, with TCG, the CPU thread will never run.
    
        1) Char backend asks front end if it can write
        2) Front end says no
        3) poll() finds the char backend's descriptor is available
        4) Goto (1)
    
    What we really want is this (note that step 3 avoids the busy wait):
    
        1) Char backend asks front end if it can write
        2) Front end says no
        3) poll() goes on without char backend's descriptor
        4) Goto (1) until qemu_chr_accept_input() called
    
        5) Char backend asks front end if it can write
        6) Front end says yes
        7) poll() finds the char backend's descriptor is available
        8) Backend handler called
    
    After this patch, the IOWatchPoll source and the watch source are
    separated.  The IOWatchPoll is simply a hook that runs during the prepare
    phase on each main loop iteration.  The hook adds/removes the actual
    source depending on the return value from can_read.
    
    A simple reproducer is
    
        qemu-system-i386 -serial mon:stdio
    
    ... followed by banging on the terminal as much as you can. :)  Without
    this patch, emulation will hang.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1365177573-11817-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index 0f7f32d..dd410ce 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -594,65 +594,51 @@ int recv_all(int fd, void *_buf, int len1, bool single_read)
 
 typedef struct IOWatchPoll
 {
+    GSource parent;
+
     GSource *src;
-    int max_size;
 
     IOCanReadHandler *fd_can_read;
     void *opaque;
-
-    QTAILQ_ENTRY(IOWatchPoll) node;
 } IOWatchPoll;
 
-static QTAILQ_HEAD(, IOWatchPoll) io_watch_poll_list =
-    QTAILQ_HEAD_INITIALIZER(io_watch_poll_list);
-
 static IOWatchPoll *io_watch_poll_from_source(GSource *source)
 {
-    IOWatchPoll *i;
-
-    QTAILQ_FOREACH(i, &io_watch_poll_list, node) {
-        if (i->src == source) {
-            return i;
-        }
-    }
-
-    return NULL;
+    return container_of(source, IOWatchPoll, parent);
 }
 
 static gboolean io_watch_poll_prepare(GSource *source, gint *timeout_)
 {
     IOWatchPoll *iwp = io_watch_poll_from_source(source);
-
-    iwp->max_size = iwp->fd_can_read(iwp->opaque);
-    if (iwp->max_size == 0) {
+    bool now_active = iwp->fd_can_read(iwp->opaque) > 0;
+    bool was_active = g_source_get_context(iwp->src) != NULL;
+    if (was_active == now_active) {
         return FALSE;
     }
 
-    return g_io_watch_funcs.prepare(source, timeout_);
+    if (now_active) {
+        g_source_attach(iwp->src, NULL);
+    } else {
+        g_source_remove(g_source_get_id(iwp->src));
+    }
+    return FALSE;
 }
 
 static gboolean io_watch_poll_check(GSource *source)
 {
-    IOWatchPoll *iwp = io_watch_poll_from_source(source);
-
-    if (iwp->max_size == 0) {
-        return FALSE;
-    }
-
-    return g_io_watch_funcs.check(source);
+    return FALSE;
 }
 
 static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback,
                                        gpointer user_data)
 {
-    return g_io_watch_funcs.dispatch(source, callback, user_data);
+    abort();
 }
 
 static void io_watch_poll_finalize(GSource *source)
 {
     IOWatchPoll *iwp = io_watch_poll_from_source(source);
-    QTAILQ_REMOVE(&io_watch_poll_list, iwp, node);
-    g_io_watch_funcs.finalize(source);
+    g_source_unref(iwp->src);
 }
 
 static GSourceFuncs io_watch_poll_funcs = {
@@ -669,24 +655,14 @@ static guint io_add_watch_poll(GIOChannel *channel,
                                gpointer user_data)
 {
     IOWatchPoll *iwp;
-    GSource *src;
-    guint tag;
-
-    src = g_io_create_watch(channel, G_IO_IN | G_IO_ERR | G_IO_HUP);
-    g_source_set_funcs(src, &io_watch_poll_funcs);
-    g_source_set_callback(src, (GSourceFunc)fd_read, user_data, NULL);
-    tag = g_source_attach(src, NULL);
-    g_source_unref(src);
 
-    iwp = g_malloc0(sizeof(*iwp));
-    iwp->src = src;
-    iwp->max_size = 0;
+    iwp = (IOWatchPoll *) g_source_new(&io_watch_poll_funcs, sizeof(IOWatchPoll));
     iwp->fd_can_read = fd_can_read;
     iwp->opaque = user_data;
+    iwp->src = g_io_create_watch(channel, G_IO_IN | G_IO_ERR | G_IO_HUP);
+    g_source_set_callback(iwp->src, (GSourceFunc)fd_read, user_data, NULL);
 
-    QTAILQ_INSERT_HEAD(&io_watch_poll_list, iwp, node);
-
-    return tag;
+    return g_source_attach(&iwp->parent, NULL);
 }
 
 #ifndef _WIN32
commit 91b53e4407ed8379d2d40f88a585e0b767681927
Merge: 54baa6f f1922e3
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 5 12:52:48 2013 -0500

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    # By Peter Crosthwaite (2) and others
    # Via Stefan Hajnoczi
    * stefanha/trivial-patches:
      xilinx_zynq: Cleanup ssi_create_slave
      petalogix_ml605_mmu: Cleanup ssi_create_slave()
      target-s390: Fix SRNMT
      linux-user: Don't omit comma for strace of rt_sigaction()
      test-visitor-serialization: Fix some memory leaks

commit 54baa6f3c07a155939a6edda6d17706a6e9ab11c
Merge: 5098699 9246ce8
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 5 12:52:32 2013 -0500

    Merge remote-tracking branch 'sstabellini/xen-2013-04-05' into staging
    
    # By Alex Bligh (2) and Felipe Franciosi (2)
    # Via Stefano Stabellini
    * sstabellini/xen-2013-04-05:
      Allow xen guests to plug disks of 1 TiB or more
      Introduce 64 bit integer write interface to xenstore
      Xen PV backend: Disable use of O_DIRECT by default as it results in crashes.
      Xen PV backend: Move call to bdrv_new from blk_init to blk_connect

commit 5098699a51756f7e8934dc035112c8f8aa2a0ec3
Merge: 150a470 c2b6ff5
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 5 12:49:10 2013 -0500

    Merge remote-tracking branch 'kwolf/for-anthony' into staging
    
    # By Stefan Hajnoczi (4) and Kevin Wolf (3)
    # Via Kevin Wolf
    * kwolf/for-anthony:
      qcow2: Fix L1 write error handling in qcow2_update_snapshot_refcount
      qcow2: Return real error in qcow2_update_snapshot_refcount
      block: clean up I/O throttling wait_time code
      block: drop duplicated slice extension code
      block: keep I/O throttling slice time constant
      block: fix I/O throttling accounting blind spot
      usb-storage: Forward serial number to scsi-disk

commit c2b6ff51e4a3ad1f7ec5dbc94970e9778b31d718
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Apr 5 12:57:10 2013 +0200

    qcow2: Fix L1 write error handling in qcow2_update_snapshot_refcount
    
    It ignored the error code, and at least the 'goto fail' is obvious
    nonsense as it creates an endless loop (if the next attempt doesn't
    magically succeed) and leaves the in-memory L1 table in big-endian
    instead of converting it back.
    
    In error cases, there's no point in writing an updated L1 table, so
    skip this part for them.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 4799681..b32738f 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -851,14 +851,16 @@ fail:
     }
 
     /* Update L1 only if it isn't deleted anyway (addend = -1) */
-    if (addend >= 0 && l1_modified) {
-        for(i = 0; i < l1_size; i++)
+    if (ret == 0 && addend >= 0 && l1_modified) {
+        for (i = 0; i < l1_size; i++) {
             cpu_to_be64s(&l1_table[i]);
-        if (bdrv_pwrite_sync(bs->file, l1_table_offset, l1_table,
-                        l1_size2) < 0)
-            goto fail;
-        for(i = 0; i < l1_size; i++)
+        }
+
+        ret = bdrv_pwrite_sync(bs->file, l1_table_offset, l1_table, l1_size2);
+
+        for (i = 0; i < l1_size; i++) {
             be64_to_cpus(&l1_table[i]);
+        }
     }
     if (l1_allocated)
         g_free(l1_table);
commit c2bc78b6a975ea2dcd7eee9f0dce22cc060cdcdc
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Apr 5 12:51:31 2013 +0200

    qcow2: Return real error in qcow2_update_snapshot_refcount
    
    This fixes the error message triggered by the following script:
    
        cat > /tmp/blkdebug.cfg <<EOF
        [inject-error]
        event = "cluster_free"
        errno = "28"
        immediately = "off"
        EOF
    
        $qemu_img create -f qcow2 test.qcow2 10G
        $qemu_img snapshot -c snap test.qcow2
        $qemu_img snapshot -d snap blkdebug:/tmp/blkdebug.cfg:test.qcow2
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index c38e970..4799681 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -747,10 +747,9 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
     if (l1_table_offset != s->l1_table_offset) {
         l1_table = g_malloc0(align_offset(l1_size2, 512));
         l1_allocated = 1;
-        if (bdrv_pread(bs->file, l1_table_offset,
-                       l1_table, l1_size2) != l1_size2)
-        {
-            ret = -EIO;
+
+        ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size2);
+        if (ret < 0) {
             goto fail;
         }
 
@@ -802,7 +801,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                         }
 
                         if (refcount < 0) {
-                            ret = -EIO;
+                            ret = refcount;
                             goto fail;
                         }
                     }
@@ -833,7 +832,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                 refcount = get_refcount(bs, l2_offset >> s->cluster_bits);
             }
             if (refcount < 0) {
-                ret = -EIO;
+                ret = refcount;
                 goto fail;
             } else if (refcount == 1) {
                 l2_offset |= QCOW_OFLAG_COPIED;
commit 0775437fafc5c733564645a22f75490770bf41f7
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Apr 5 11:32:22 2013 +0200

    block: clean up I/O throttling wait_time code
    
    The wait_time variable is in seconds.  Reflect this in a comment and use
    NANOSECONDS_PER_SECOND instead of BLOCK_IO_SLICE_TIME * 10 (which
    happens to have the right value).
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Tested-By: Benoit Canet <benoit at irqsave.net>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index aa16fc4..602d8a4 100644
--- a/block.c
+++ b/block.c
@@ -3800,7 +3800,7 @@ static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
                 BLOCK_IO_SLICE_TIME;
     bs->slice_end += extension;
     if (wait) {
-        *wait = wait_time * BLOCK_IO_SLICE_TIME * 10;
+        *wait = wait_time * NANOSECONDS_PER_SECOND;
     }
 
     return true;
@@ -3841,7 +3841,7 @@ static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write,
         return false;
     }
 
-    /* Calc approx time to dispatch */
+    /* Calc approx time to dispatch, in seconds */
     wait_time = (ios_base + 1) / iops_limit;
     if (wait_time > elapsed_time) {
         wait_time = wait_time - elapsed_time;
@@ -3852,7 +3852,7 @@ static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write,
     /* Exceeded current slice, extend it by another slice time */
     bs->slice_end += BLOCK_IO_SLICE_TIME;
     if (wait) {
-        *wait = wait_time * BLOCK_IO_SLICE_TIME * 10;
+        *wait = wait_time * NANOSECONDS_PER_SECOND;
     }
 
     return true;
commit e660fb8b3ccc94652774d5895d122c0f13aecb89
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Apr 5 11:32:21 2013 +0200

    block: drop duplicated slice extension code
    
    The current slice is extended when an I/O request exceeds the limit.
    There is no need to extend the slice every time we check a request.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Tested-By: Benoit Canet <benoit at irqsave.net>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 00eca27..aa16fc4 100644
--- a/block.c
+++ b/block.c
@@ -3867,10 +3867,7 @@ static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors,
     int      bps_ret, iops_ret;
 
     now = qemu_get_clock_ns(vm_clock);
-    if ((bs->slice_start < now)
-        && (bs->slice_end > now)) {
-        bs->slice_end = now + BLOCK_IO_SLICE_TIME;
-    } else {
+    if (now > bs->slice_end) {
         bs->slice_start = now;
         bs->slice_end   = now + BLOCK_IO_SLICE_TIME;
         memset(&bs->slice_submitted, 0, sizeof(bs->slice_submitted));
commit ae29d6c64bd8d55873a2cb1df50ae4321b497447
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Apr 5 11:32:20 2013 +0200

    block: keep I/O throttling slice time constant
    
    It is not necessary to adjust the slice time at runtime.  We already
    extend the current slice in order to carry over accounting into the next
    slice.  Changing the actual slice time value introduces oscillations.
    
    The guest may experience large changes in throughput or IOPS from one
    moment to the next when slice times are adjusted.
    
    Reported-by: Benoît Canet <benoit at irqsave.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Tested-By: Benoit Canet <benoit at irqsave.net>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 25976b5..00eca27 100644
--- a/block.c
+++ b/block.c
@@ -140,7 +140,6 @@ void bdrv_io_limits_disable(BlockDriverState *bs)
 
     bs->slice_start = 0;
     bs->slice_end   = 0;
-    bs->slice_time  = 0;
 }
 
 static void bdrv_block_timer(void *opaque)
@@ -1432,7 +1431,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
     bs_dest->enable_write_cache = bs_src->enable_write_cache;
 
     /* i/o timing parameters */
-    bs_dest->slice_time         = bs_src->slice_time;
     bs_dest->slice_start        = bs_src->slice_start;
     bs_dest->slice_end          = bs_src->slice_end;
     bs_dest->slice_submitted    = bs_src->slice_submitted;
@@ -3749,6 +3747,7 @@ static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
                  bool is_write, double elapsed_time, uint64_t *wait)
 {
     uint64_t bps_limit = 0;
+    uint64_t extension;
     double   bytes_limit, bytes_base, bytes_res;
     double   slice_time, wait_time;
 
@@ -3796,8 +3795,10 @@ static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
      * info can be kept until the timer fire, so it is increased and tuned
      * based on the result of experiment.
      */
-    bs->slice_time = wait_time * BLOCK_IO_SLICE_TIME * 10;
-    bs->slice_end += bs->slice_time - 3 * BLOCK_IO_SLICE_TIME;
+    extension = wait_time * NANOSECONDS_PER_SECOND;
+    extension = DIV_ROUND_UP(extension, BLOCK_IO_SLICE_TIME) *
+                BLOCK_IO_SLICE_TIME;
+    bs->slice_end += extension;
     if (wait) {
         *wait = wait_time * BLOCK_IO_SLICE_TIME * 10;
     }
@@ -3848,8 +3849,8 @@ static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write,
         wait_time = 0;
     }
 
-    bs->slice_time = wait_time * BLOCK_IO_SLICE_TIME * 10;
-    bs->slice_end += bs->slice_time - 3 * BLOCK_IO_SLICE_TIME;
+    /* Exceeded current slice, extend it by another slice time */
+    bs->slice_end += BLOCK_IO_SLICE_TIME;
     if (wait) {
         *wait = wait_time * BLOCK_IO_SLICE_TIME * 10;
     }
@@ -3868,12 +3869,10 @@ static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors,
     now = qemu_get_clock_ns(vm_clock);
     if ((bs->slice_start < now)
         && (bs->slice_end > now)) {
-        bs->slice_end = now + bs->slice_time;
+        bs->slice_end = now + BLOCK_IO_SLICE_TIME;
     } else {
-        bs->slice_time  =  5 * BLOCK_IO_SLICE_TIME;
         bs->slice_start = now;
-        bs->slice_end   = now + bs->slice_time;
-
+        bs->slice_end   = now + BLOCK_IO_SLICE_TIME;
         memset(&bs->slice_submitted, 0, sizeof(bs->slice_submitted));
     }
 
diff --git a/blockdev.c b/blockdev.c
index 8cdc9ce..6dc999d 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1069,7 +1069,6 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
     }
 
     bs->io_limits = io_limits;
-    bs->slice_time = BLOCK_IO_SLICE_TIME;
 
     if (!bs->io_limits_enabled && bdrv_io_limits_enabled(bs)) {
         bdrv_io_limits_enable(bs);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 83941d8..9aa98b5 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -252,7 +252,6 @@ struct BlockDriverState {
     unsigned int copy_on_read_in_flight;
 
     /* the time for latest disk I/O */
-    int64_t slice_time;
     int64_t slice_start;
     int64_t slice_end;
     BlockIOLimit io_limits;
commit 5905fbc9c94ccd744c1b249472eafcc2d827548a
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Apr 5 11:32:19 2013 +0200

    block: fix I/O throttling accounting blind spot
    
    I/O throttling relies on bdrv_acct_done() which is called when a request
    completes.  This leaves a blind spot since we only charge for completed
    requests, not submitted requests.
    
    For example, if there is 1 operation remaining in this time slice the
    guest could submit 3 operations and they will all be submitted
    successfully since they don't actually get accounted for until they
    complete.
    
    Originally we probably thought this is okay since the requests will be
    accounted when the time slice is extended.  In practice it causes
    fluctuations since the guest can exceed its I/O limit and it will be
    punished for this later on.
    
    Account for I/O upon submission so that I/O limits are enforced
    properly.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Tested-By: Benoit Canet <benoit at irqsave.net>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 0ae2e93..25976b5 100644
--- a/block.c
+++ b/block.c
@@ -141,7 +141,6 @@ void bdrv_io_limits_disable(BlockDriverState *bs)
     bs->slice_start = 0;
     bs->slice_end   = 0;
     bs->slice_time  = 0;
-    memset(&bs->io_base, 0, sizeof(bs->io_base));
 }
 
 static void bdrv_block_timer(void *opaque)
@@ -1436,8 +1435,8 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
     bs_dest->slice_time         = bs_src->slice_time;
     bs_dest->slice_start        = bs_src->slice_start;
     bs_dest->slice_end          = bs_src->slice_end;
+    bs_dest->slice_submitted    = bs_src->slice_submitted;
     bs_dest->io_limits          = bs_src->io_limits;
-    bs_dest->io_base            = bs_src->io_base;
     bs_dest->throttled_reqs     = bs_src->throttled_reqs;
     bs_dest->block_timer        = bs_src->block_timer;
     bs_dest->io_limits_enabled  = bs_src->io_limits_enabled;
@@ -3768,9 +3767,9 @@ static bool bdrv_exceed_bps_limits(BlockDriverState *bs, int nb_sectors,
     slice_time = bs->slice_end - bs->slice_start;
     slice_time /= (NANOSECONDS_PER_SECOND);
     bytes_limit = bps_limit * slice_time;
-    bytes_base  = bs->nr_bytes[is_write] - bs->io_base.bytes[is_write];
+    bytes_base  = bs->slice_submitted.bytes[is_write];
     if (bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]) {
-        bytes_base += bs->nr_bytes[!is_write] - bs->io_base.bytes[!is_write];
+        bytes_base += bs->slice_submitted.bytes[!is_write];
     }
 
     /* bytes_base: the bytes of data which have been read/written; and
@@ -3828,9 +3827,9 @@ static bool bdrv_exceed_iops_limits(BlockDriverState *bs, bool is_write,
     slice_time = bs->slice_end - bs->slice_start;
     slice_time /= (NANOSECONDS_PER_SECOND);
     ios_limit  = iops_limit * slice_time;
-    ios_base   = bs->nr_ops[is_write] - bs->io_base.ios[is_write];
+    ios_base   = bs->slice_submitted.ios[is_write];
     if (bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]) {
-        ios_base += bs->nr_ops[!is_write] - bs->io_base.ios[!is_write];
+        ios_base += bs->slice_submitted.ios[!is_write];
     }
 
     if (ios_base + 1 <= ios_limit) {
@@ -3875,11 +3874,7 @@ static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors,
         bs->slice_start = now;
         bs->slice_end   = now + bs->slice_time;
 
-        bs->io_base.bytes[is_write]  = bs->nr_bytes[is_write];
-        bs->io_base.bytes[!is_write] = bs->nr_bytes[!is_write];
-
-        bs->io_base.ios[is_write]    = bs->nr_ops[is_write];
-        bs->io_base.ios[!is_write]   = bs->nr_ops[!is_write];
+        memset(&bs->slice_submitted, 0, sizeof(bs->slice_submitted));
     }
 
     elapsed_time  = now - bs->slice_start;
@@ -3907,6 +3902,10 @@ static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors,
         *wait = 0;
     }
 
+    bs->slice_submitted.bytes[is_write] += (int64_t)nb_sectors *
+                                           BDRV_SECTOR_SIZE;
+    bs->slice_submitted.ios[is_write]++;
+
     return false;
 }
 
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 0986a2d..83941d8 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -256,7 +256,7 @@ struct BlockDriverState {
     int64_t slice_start;
     int64_t slice_end;
     BlockIOLimit io_limits;
-    BlockIOBaseValue  io_base;
+    BlockIOBaseValue slice_submitted;
     CoQueue      throttled_reqs;
     QEMUTimer    *block_timer;
     bool         io_limits_enabled;
commit 76534da749ceb3b4c13ec09b173bcf6d6c2e36d4
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Apr 3 12:41:46 2013 +0200

    usb-storage: Forward serial number to scsi-disk
    
    usb-storage takes care to fetch the USB serial number from -drive
    options, but it neglected to pass its own 'serial' property to the
    scsi-disk it creates. With this patch, the 'serial' qdev property and
    the 'serial' option in -drive behave the same and correctly apply the
    serial number on both USB and SCSI level.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c
index f38df30..180ee07 100644
--- a/hw/pci/pci-hotplug.c
+++ b/hw/pci/pci-hotplug.c
@@ -99,7 +99,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
     dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
     dinfo->bus = scsibus->busnr;
     scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit,
-                                        false, -1);
+                                        false, -1, NULL);
     if (!scsidev) {
         return -1;
     }
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 08787c2..ac2093a 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -207,7 +207,8 @@ static int scsi_qdev_exit(DeviceState *qdev)
 
 /* handle legacy '-drive if=scsi,...' cmd line args */
 SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
-                                      int unit, bool removable, int bootindex)
+                                      int unit, bool removable, int bootindex,
+                                      const char *serial)
 {
     const char *driver;
     DeviceState *dev;
@@ -221,6 +222,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
     if (object_property_find(OBJECT(dev), "removable", NULL)) {
         qdev_prop_set_bit(dev, "removable", removable);
     }
+    if (serial) {
+        qdev_prop_set_string(dev, "serial", serial);
+    }
     if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
         qdev_free(dev);
         return NULL;
@@ -243,7 +247,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
             continue;
         }
         qemu_opts_loc_restore(dinfo->opts);
-        if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1)) {
+        if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1, NULL)) {
             res = -1;
             break;
         }
diff --git a/hw/scsi.h b/hw/scsi.h
index 33e2e0b..02a1497 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -160,7 +160,8 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
 }
 
 SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
-                                      int unit, bool removable, int bootindex);
+                                      int unit, bool removable, int bootindex,
+                                      const char *serial);
 int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
 
 /*
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index d3f01aa..21651b3 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -625,7 +625,7 @@ static int usb_msd_initfn_storage(USBDevice *dev)
     usb_desc_init(dev);
     scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_storage);
     scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
-                                            s->conf.bootindex);
+                                            s->conf.bootindex, s->serial);
     if (!scsi_dev) {
         return -1;
     }
commit 32aea752f47f30c00878dcc323ac4debf0c9e645
Author: Wendy Liang <wendy.liang at xilinx.com>
Date:   Wed Apr 3 15:33:08 2013 +1000

    hw/nand.c: Fix nand erase operation
    
    Usually, nand erase operation has only 2 or 3 address cycles.
    We need to mask s->addr to zero unset stale high-order bytes in the nand address
    before using it as the erase address.
    
    This fixes the NAND erase operation in Linux.
    
    [PC: Generalised to work for any number of address cycles rather than just 3]
    
    Signed-off-by: Wendy Liang <jliang at xilinx.com>
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 1364967188-26711-1-git-send-email-peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/nand.c b/hw/nand.c
index de3e502..6362093 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -297,6 +297,7 @@ static void nand_command(NANDFlashState *s)
         break;
 
     case NAND_CMD_BLOCKERASE2:
+        s->addr &= (1ull << s->addrlen * 8) - 1;
         if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP)
             s->addr <<= 16;
         else
commit 1db8b5efe0c2b5000e50691eea61264a615f43de
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Wed Apr 3 14:52:21 2013 +1000

    cadence_uart: Flush queued characters on reset
    
    Reset can be used to empty the rx-fifo. As the fifo full condition is
    used to return false from can_receive, queued rx data should be flushed
    on reset accordingly.
    
    Cc: Wendy Liang <jliang at xilinx.com>
    Cc: Jason Wu <huanyu at xilinx.com>
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Reported-by: Jason Wu <huanyu at xilinx.com>
    Message-id: 494c1e005e225c915d295ddfd75d992ad2dabc3c.1364964526.git.peter.crosthwaite at xilinx.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c
index 5426f10..421ec99 100644
--- a/hw/cadence_uart.c
+++ b/hw/cadence_uart.c
@@ -157,6 +157,7 @@ static void uart_rx_reset(UartState *s)
 {
     s->rx_wpos = 0;
     s->rx_count = 0;
+    qemu_chr_accept_input(s->chr);
 
     s->r[R_SR] |= UART_SR_INTR_REMPTY;
     s->r[R_SR] &= ~UART_SR_INTR_RFUL;
commit fd7f8a99f3b08640a7fe2b2f3c3e6b68068b4983
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Tue Apr 2 17:59:29 2013 +0000

    pl330: Don't inhibit ES bits on INTEN
    
    This if-else logic inhibits setting of the event status (ES) bits
    when interrupts are enabled. This is incorrect. ES should be set
    regardless on INTEN state. INTEN only inhibits the signalling of
    events to PL330 threads, not setting of the ES register.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/pl330.c b/hw/pl330.c
index 1a04773..60aa4a8 100644
--- a/hw/pl330.c
+++ b/hw/pl330.c
@@ -870,9 +870,8 @@ static void pl330_dmasev(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
         ch->parent->int_status |= (1 << ev_id);
         DB_PRINT("event interrupt raised %d\n", ev_id);
         qemu_irq_raise(ch->parent->irq[ev_id]);
-    } else {
-        ch->parent->ev_status |= (1 << ev_id);
     }
+    ch->parent->ev_status |= (1 << ev_id);
 }
 
 static void pl330_dmast(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len)
commit 9246ce881128df2a69178779c1ef33c83df3c70d
Author: Felipe Franciosi <felipe.franciosi at citrix.com>
Date:   Fri Apr 5 15:47:59 2013 +0000

    Allow xen guests to plug disks of 1 TiB or more
    
    The current xen backend driver implementation uses int64_t variables
    to store the size of the corresponding backend disk/file. It also uses
    an int64_t variable to store the block size of that image. When writing
    the number of sectors (file_size/block_size) to xenstore, however, it
    passes these values as 32 bit signed integers. This will cause an
    overflow for any disk of 1 TiB or more.
    
    This patch changes the xen backend driver to use a 64 bit integer write
    xenstore function.
    
    Signed-off-by: Felipe Franciosi <felipe at paradoxo.org>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 1a30f0a..47a51cf 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -825,8 +825,8 @@ static int blk_connect(struct XenDevice *xendev)
 
     /* Fill in number of sector size and number of sectors */
     xenstore_write_be_int(&blkdev->xendev, "sector-size", blkdev->file_blk);
-    xenstore_write_be_int(&blkdev->xendev, "sectors",
-                          blkdev->file_size / blkdev->file_blk);
+    xenstore_write_be_int64(&blkdev->xendev, "sectors",
+                            blkdev->file_size / blkdev->file_blk);
 
     if (xenstore_read_fe_int(&blkdev->xendev, "ring-ref", &blkdev->ring_ref) == -1) {
         return -1;
commit 10bb3c623478117aee5117c312736f10833decc2
Author: Felipe Franciosi <felipe.franciosi at citrix.com>
Date:   Fri Apr 5 15:37:32 2013 +0000

    Introduce 64 bit integer write interface to xenstore
    
    The current implementation of xen_backend only provides 32 bit integer
    functions to write to xenstore. This patch adds two functions that
    allow writing 64 bit integers (one generic function and another for
    the backend only).
    
    This patch also fixes the size of the char arrays used to represent
    these integers as strings (originally 32 bytes, however no more than
    12 bytes are needed for 32 bit integers and no more than 21 bytes are
    needed for 64 bit integers).
    
    Signed-off-by: Felipe Franciosi <felipe at paradoxo.org>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_backend.c b/hw/xen_backend.c
index 24381b5..02693d7 100644
--- a/hw/xen_backend.c
+++ b/hw/xen_backend.c
@@ -85,12 +85,20 @@ char *xenstore_read_str(const char *base, const char *node)
 
 int xenstore_write_int(const char *base, const char *node, int ival)
 {
-    char val[32];
+    char val[12];
 
     snprintf(val, sizeof(val), "%d", ival);
     return xenstore_write_str(base, node, val);
 }
 
+int xenstore_write_int64(const char *base, const char *node, int64_t ival)
+{
+    char val[21];
+
+    snprintf(val, sizeof(val), "%"PRId64, ival);
+    return xenstore_write_str(base, node, val);
+}
+
 int xenstore_read_int(const char *base, const char *node, int *ival)
 {
     char *val;
@@ -114,6 +122,11 @@ int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival)
     return xenstore_write_int(xendev->be, node, ival);
 }
 
+int xenstore_write_be_int64(struct XenDevice *xendev, const char *node, int64_t ival)
+{
+    return xenstore_write_int64(xendev->be, node, ival);
+}
+
 char *xenstore_read_be_str(struct XenDevice *xendev, const char *node)
 {
     return xenstore_read_str(xendev->be, node);
diff --git a/hw/xen_backend.h b/hw/xen_backend.h
index 6d5c699..d04b985 100644
--- a/hw/xen_backend.h
+++ b/hw/xen_backend.h
@@ -63,11 +63,13 @@ extern const char *xen_protocol;
 /* xenstore helper functions */
 int xenstore_write_str(const char *base, const char *node, const char *val);
 int xenstore_write_int(const char *base, const char *node, int ival);
+int xenstore_write_int64(const char *base, const char *node, int64_t ival);
 char *xenstore_read_str(const char *base, const char *node);
 int xenstore_read_int(const char *base, const char *node, int *ival);
 
 int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val);
 int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival);
+int xenstore_write_be_int64(struct XenDevice *xendev, const char *node, int64_t ival);
 char *xenstore_read_be_str(struct XenDevice *xendev, const char *node);
 int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival);
 char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node);
commit c1a88ad1f4ac994cd70695bf08141d161e21533e
Author: Alex Bligh <alex at alex.org.uk>
Date:   Fri Apr 5 15:45:15 2013 +0000

    Xen PV backend: Disable use of O_DIRECT by default as it results in crashes.
    
    Due to what is almost certainly a kernel bug, writes with O_DIRECT may
    continue to reference the page after the write has been marked as
    completed, particularly in the case of TCP retransmit. In other
    scenarios, this "merely" risks data corruption on the write, but with
    Xen pages from domU are only transiently mapped into dom0's memory,
    resulting in kernel panics when they are subsequently accessed.
    
    This brings PV devices in line with emulated devices.  Removing
    O_DIRECT is safe as barrier operations are now correctly passed
    through.
    
    See:
       http://lists.xen.org/archives/html/xen-devel/2012-12/msg01154.html
    for more details.
    
    Signed-off-by: Alex Bligh <alex at alex.org.uk>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 24e8b24..1a30f0a 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -782,7 +782,7 @@ static int blk_connect(struct XenDevice *xendev)
     int pers, index, qflags;
 
     /* read-only ? */
-    qflags = BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO;
+    qflags = BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO;
     if (strcmp(blkdev->mode, "w") == 0) {
         qflags |= BDRV_O_RDWR;
     }
commit 86f425db3b1c4b6c4a2927eaec35627f9ab2e703
Author: Alex Bligh <alex at alex.org.uk>
Date:   Fri Apr 5 15:45:10 2013 +0000

    Xen PV backend: Move call to bdrv_new from blk_init to blk_connect
    
    This commit delays the point at which bdrv_new (and hence blk_open
    on the underlying device) is called from blk_init to blk_connect.
    This ensures that in an inbound live migrate, the block device is
    not opened until it has been closed at the other end. This is in
    preparation for supporting devices with open/close consistency
    without using O_DIRECT. This commit does NOT itself change O_DIRECT
    semantics.
    
    Signed-off-by: Alex Bligh <alex at alex.org.uk>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 83329e2..24e8b24 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -700,7 +700,7 @@ static void blk_alloc(struct XenDevice *xendev)
 static int blk_init(struct XenDevice *xendev)
 {
     struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
-    int index, qflags, info = 0;
+    int info = 0;
 
     /* read xenstore entries */
     if (blkdev->params == NULL) {
@@ -743,10 +743,7 @@ static int blk_init(struct XenDevice *xendev)
     }
 
     /* read-only ? */
-    qflags = BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO;
-    if (strcmp(blkdev->mode, "w") == 0) {
-        qflags |= BDRV_O_RDWR;
-    } else {
+    if (strcmp(blkdev->mode, "w")) {
         info  |= VDISK_READONLY;
     }
 
@@ -755,6 +752,41 @@ static int blk_init(struct XenDevice *xendev)
         info  |= VDISK_CDROM;
     }
 
+    blkdev->file_blk  = BLOCK_SIZE;
+
+    /* fill info
+     * blk_connect supplies sector-size and sectors
+     */
+    xenstore_write_be_int(&blkdev->xendev, "feature-flush-cache", 1);
+    xenstore_write_be_int(&blkdev->xendev, "feature-persistent", 1);
+    xenstore_write_be_int(&blkdev->xendev, "info", info);
+    return 0;
+
+out_error:
+    g_free(blkdev->params);
+    blkdev->params = NULL;
+    g_free(blkdev->mode);
+    blkdev->mode = NULL;
+    g_free(blkdev->type);
+    blkdev->type = NULL;
+    g_free(blkdev->dev);
+    blkdev->dev = NULL;
+    g_free(blkdev->devtype);
+    blkdev->devtype = NULL;
+    return -1;
+}
+
+static int blk_connect(struct XenDevice *xendev)
+{
+    struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
+    int pers, index, qflags;
+
+    /* read-only ? */
+    qflags = BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO;
+    if (strcmp(blkdev->mode, "w") == 0) {
+        qflags |= BDRV_O_RDWR;
+    }
+
     /* init qemu block driver */
     index = (blkdev->xendev.dev - 202 * 256) / 16;
     blkdev->dinfo = drive_get(IF_XEN, 0, index);
@@ -770,7 +802,7 @@ static int blk_init(struct XenDevice *xendev)
             }
         }
         if (!blkdev->bs) {
-            goto out_error;
+            return -1;
         }
     } else {
         /* setup via qemu cmdline -> already setup for us */
@@ -778,7 +810,6 @@ static int blk_init(struct XenDevice *xendev)
         blkdev->bs = blkdev->dinfo->bdrv;
     }
     bdrv_attach_dev_nofail(blkdev->bs, blkdev);
-    blkdev->file_blk  = BLOCK_SIZE;
     blkdev->file_size = bdrv_getlength(blkdev->bs);
     if (blkdev->file_size < 0) {
         xen_be_printf(&blkdev->xendev, 1, "bdrv_getlength: %d (%s) | drv %s\n",
@@ -792,33 +823,10 @@ static int blk_init(struct XenDevice *xendev)
                   blkdev->type, blkdev->fileproto, blkdev->filename,
                   blkdev->file_size, blkdev->file_size >> 20);
 
-    /* fill info */
-    xenstore_write_be_int(&blkdev->xendev, "feature-flush-cache", 1);
-    xenstore_write_be_int(&blkdev->xendev, "feature-persistent", 1);
-    xenstore_write_be_int(&blkdev->xendev, "info",            info);
-    xenstore_write_be_int(&blkdev->xendev, "sector-size",     blkdev->file_blk);
+    /* Fill in number of sector size and number of sectors */
+    xenstore_write_be_int(&blkdev->xendev, "sector-size", blkdev->file_blk);
     xenstore_write_be_int(&blkdev->xendev, "sectors",
                           blkdev->file_size / blkdev->file_blk);
-    return 0;
-
-out_error:
-    g_free(blkdev->params);
-    blkdev->params = NULL;
-    g_free(blkdev->mode);
-    blkdev->mode = NULL;
-    g_free(blkdev->type);
-    blkdev->type = NULL;
-    g_free(blkdev->dev);
-    blkdev->dev = NULL;
-    g_free(blkdev->devtype);
-    blkdev->devtype = NULL;
-    return -1;
-}
-
-static int blk_connect(struct XenDevice *xendev)
-{
-    struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
-    int pers;
 
     if (xenstore_read_fe_int(&blkdev->xendev, "ring-ref", &blkdev->ring_ref) == -1) {
         return -1;
commit d8d24fb78cf21205bf672d85231712dc1f0bbb39
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:18:00 2013 +0100

    pflash_cfi01: Implement migration support
    
    Add a vmstate to pflash_cfi01, so that it can be live migrated.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363717469-30980-3-git-send-email-peter.maydell at linaro.org

diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 20d10b3..646dc79 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -67,7 +67,7 @@ struct pflash_t {
     uint64_t sector_len;
     uint8_t width;
     uint8_t be;
-    int wcycle; /* if 0, the flash is read normally */
+    uint8_t wcycle; /* if 0, the flash is read normally */
     int ro;
     uint8_t cmd;
     uint8_t status;
@@ -77,7 +77,7 @@ struct pflash_t {
     uint16_t ident3;
     uint8_t cfi_len;
     uint8_t cfi_table[0x52];
-    hwaddr counter;
+    uint64_t counter;
     unsigned int writeblock_size;
     QEMUTimer *timer;
     MemoryRegion mem;
@@ -85,6 +85,19 @@ struct pflash_t {
     void *storage;
 };
 
+static const VMStateDescription vmstate_pflash = {
+    .name = "pflash_cfi01",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(wcycle, pflash_t),
+        VMSTATE_UINT8(cmd, pflash_t),
+        VMSTATE_UINT8(status, pflash_t),
+        VMSTATE_UINT64(counter, pflash_t),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static void pflash_timer (void *opaque)
 {
     pflash_t *pfl = opaque;
@@ -223,7 +236,7 @@ static inline void pflash_data_write(pflash_t *pfl, hwaddr offset,
     uint8_t *p = pfl->storage;
 
     DPRINTF("%s: block write offset " TARGET_FMT_plx
-            " value %x counter " TARGET_FMT_plx "\n",
+            " value %x counter %016" PRIx64 "\n",
             __func__, offset, value, pfl->counter);
     switch (width) {
     case 1:
@@ -701,6 +714,7 @@ static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
 
     k->init = pflash_cfi01_init;
     dc->props = pflash_cfi01_properties;
+    dc->vmsd = &vmstate_pflash;
 }
 
 
commit 5d79b80b335c5f65f148d1bb1672d9d534ace73b
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:18:00 2013 +0100

    pflash_cfi01: Drop unused 'bypass' field
    
    For pflash_cfi01 the 'bypass' field is set to zero and never changes,
    so remove it (it is a leftover from pflash_cfi02, where bypass is
    implemented).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363717469-30980-2-git-send-email-peter.maydell at linaro.org

diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 5d57bab..20d10b3 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -68,7 +68,6 @@ struct pflash_t {
     uint8_t width;
     uint8_t be;
     int wcycle; /* if 0, the flash is read normally */
-    int bypass;
     int ro;
     uint8_t cmd;
     uint8_t status;
@@ -93,12 +92,8 @@ static void pflash_timer (void *opaque)
     DPRINTF("%s: command %02x done\n", __func__, pfl->cmd);
     /* Reset flash */
     pfl->status ^= 0x80;
-    if (pfl->bypass) {
-        pfl->wcycle = 2;
-    } else {
-        memory_region_rom_device_set_readable(&pfl->mem, true);
-        pfl->wcycle = 0;
-    }
+    memory_region_rom_device_set_readable(&pfl->mem, true);
+    pfl->wcycle = 0;
     pfl->cmd = 0;
 }
 
@@ -452,7 +447,6 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
  reset_flash:
     memory_region_rom_device_set_readable(&pfl->mem, true);
 
-    pfl->bypass = 0;
     pfl->wcycle = 0;
     pfl->cmd = 0;
 }
commit 2e19a7035a8e721f32610c8d22223ab748c4232f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:18:00 2013 +0100

    hw/arm_gic_common: Use vmstate struct rather than save/load functions
    
    Update the GIC save/restore to use vmstate rather than hand-rolled
    save/load functions.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Message-id: 1363975375-3166-4-git-send-email-peter.maydell at linaro.org

diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c
index f95bec3..71594f1 100644
--- a/hw/arm_gic_common.c
+++ b/hw/arm_gic_common.c
@@ -20,90 +20,65 @@
 
 #include "hw/arm_gic_internal.h"
 
-static void gic_save(QEMUFile *f, void *opaque)
+static void gic_pre_save(void *opaque)
 {
     GICState *s = (GICState *)opaque;
     ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s);
-    int i;
-    int j;
 
     if (c->pre_save) {
         c->pre_save(s);
     }
-
-    qemu_put_be32(f, s->enabled);
-    for (i = 0; i < s->num_cpu; i++) {
-        qemu_put_be32(f, s->cpu_enabled[i]);
-        for (j = 0; j < GIC_INTERNAL; j++) {
-            qemu_put_be32(f, s->priority1[j][i]);
-        }
-        for (j = 0; j < s->num_irq; j++) {
-            qemu_put_be32(f, s->last_active[j][i]);
-        }
-        qemu_put_be32(f, s->priority_mask[i]);
-        qemu_put_be32(f, s->running_irq[i]);
-        qemu_put_be32(f, s->running_priority[i]);
-        qemu_put_be32(f, s->current_pending[i]);
-    }
-    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
-        qemu_put_be32(f, s->priority2[i]);
-    }
-    for (i = 0; i < s->num_irq; i++) {
-        qemu_put_be32(f, s->irq_target[i]);
-        qemu_put_byte(f, s->irq_state[i].enabled);
-        qemu_put_byte(f, s->irq_state[i].pending);
-        qemu_put_byte(f, s->irq_state[i].active);
-        qemu_put_byte(f, s->irq_state[i].level);
-        qemu_put_byte(f, s->irq_state[i].model);
-        qemu_put_byte(f, s->irq_state[i].trigger);
-    }
 }
 
-static int gic_load(QEMUFile *f, void *opaque, int version_id)
+static int gic_post_load(void *opaque, int version_id)
 {
     GICState *s = (GICState *)opaque;
     ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s);
-    int i;
-    int j;
-
-    if (version_id != 3) {
-        return -EINVAL;
-    }
-
-    s->enabled = qemu_get_be32(f);
-    for (i = 0; i < s->num_cpu; i++) {
-        s->cpu_enabled[i] = qemu_get_be32(f);
-        for (j = 0; j < GIC_INTERNAL; j++) {
-            s->priority1[j][i] = qemu_get_be32(f);
-        }
-        for (j = 0; j < s->num_irq; j++) {
-            s->last_active[j][i] = qemu_get_be32(f);
-        }
-        s->priority_mask[i] = qemu_get_be32(f);
-        s->running_irq[i] = qemu_get_be32(f);
-        s->running_priority[i] = qemu_get_be32(f);
-        s->current_pending[i] = qemu_get_be32(f);
-    }
-    for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
-        s->priority2[i] = qemu_get_be32(f);
-    }
-    for (i = 0; i < s->num_irq; i++) {
-        s->irq_target[i] = qemu_get_be32(f);
-        s->irq_state[i].enabled = qemu_get_byte(f);
-        s->irq_state[i].pending = qemu_get_byte(f);
-        s->irq_state[i].active = qemu_get_byte(f);
-        s->irq_state[i].level = qemu_get_byte(f);
-        s->irq_state[i].model = qemu_get_byte(f);
-        s->irq_state[i].trigger = qemu_get_byte(f);
-    }
 
     if (c->post_load) {
         c->post_load(s);
     }
-
     return 0;
 }
 
+static const VMStateDescription vmstate_gic_irq_state = {
+    .name = "arm_gic_irq_state",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(enabled, gic_irq_state),
+        VMSTATE_UINT8(pending, gic_irq_state),
+        VMSTATE_UINT8(active, gic_irq_state),
+        VMSTATE_UINT8(level, gic_irq_state),
+        VMSTATE_BOOL(model, gic_irq_state),
+        VMSTATE_BOOL(trigger, gic_irq_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_gic = {
+    .name = "arm_gic",
+    .version_id = 4,
+    .minimum_version_id = 4,
+    .pre_save = gic_pre_save,
+    .post_load = gic_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_BOOL(enabled, GICState),
+        VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, NCPU),
+        VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1,
+                             vmstate_gic_irq_state, gic_irq_state),
+        VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ),
+        VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, NCPU),
+        VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL),
+        VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, NCPU),
+        VMSTATE_UINT16_ARRAY(priority_mask, GICState, NCPU),
+        VMSTATE_UINT16_ARRAY(running_irq, GICState, NCPU),
+        VMSTATE_UINT16_ARRAY(running_priority, GICState, NCPU),
+        VMSTATE_UINT16_ARRAY(current_pending, GICState, NCPU),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static void arm_gic_common_realize(DeviceState *dev, Error **errp)
 {
     GICState *s = ARM_GIC_COMMON(dev);
@@ -131,8 +106,6 @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
                    num_irq);
         return;
     }
-
-    register_savevm(NULL, "arm_gic", -1, 3, gic_save, gic_load, s);
 }
 
 static void arm_gic_common_reset(DeviceState *dev)
@@ -182,6 +155,7 @@ static void arm_gic_common_class_init(ObjectClass *klass, void *data)
     dc->reset = arm_gic_common_reset;
     dc->realize = arm_gic_common_realize;
     dc->props = arm_gic_common_properties;
+    dc->vmsd = &vmstate_gic;
     dc->no_user = 1;
 }
 
commit c3037774be5329e584d4d709b9df7e1799bba215
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:17:59 2013 +0100

    arm_gic: Fix sizes of state fields in preparation for vmstate support
    
    In preparation for switching to vmstate for migration support, fix
    the sizes of various GIC state fields. In particular, we replace all
    the bitfields (which VMState can't deal with) with straightforward
    uint8_t values which we do bit operations on. (The bitfields made
    more sense when NCPU was set differently in different situations,
    but we now always model at the architectural limit of 8.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1363975375-3166-3-git-send-email-peter.maydell at linaro.org

diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c
index f2dc8bf..f95bec3 100644
--- a/hw/arm_gic_common.c
+++ b/hw/arm_gic_common.c
@@ -149,7 +149,7 @@ static void arm_gic_common_reset(DeviceState *dev)
         s->current_pending[i] = 1023;
         s->running_irq[i] = 1023;
         s->running_priority[i] = 0x100;
-        s->cpu_enabled[i] = 0;
+        s->cpu_enabled[i] = false;
     }
     for (i = 0; i < 16; i++) {
         GIC_SET_ENABLED(i, ALL_CPU_MASK);
@@ -161,7 +161,7 @@ static void arm_gic_common_reset(DeviceState *dev)
             s->irq_target[i] = 1;
         }
     }
-    s->enabled = 0;
+    s->enabled = false;
 }
 
 static Property arm_gic_common_properties[] = {
diff --git a/hw/arm_gic_internal.h b/hw/arm_gic_internal.h
index 3e1928b..99a3bc3 100644
--- a/hw/arm_gic_internal.h
+++ b/hw/arm_gic_internal.h
@@ -45,14 +45,14 @@
 #define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
 #define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
 #define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
-#define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1
-#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0
+#define GIC_SET_MODEL(irq) s->irq_state[irq].model = true
+#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = false
 #define GIC_TEST_MODEL(irq) s->irq_state[irq].model
 #define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
 #define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
 #define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
-#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
-#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
+#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = true
+#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = false
 #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
 #define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ?            \
                                     s->priority1[irq][cpu] :            \
@@ -61,30 +61,30 @@
 
 typedef struct gic_irq_state {
     /* The enable bits are only banked for per-cpu interrupts.  */
-    unsigned enabled:NCPU;
-    unsigned pending:NCPU;
-    unsigned active:NCPU;
-    unsigned level:NCPU;
-    unsigned model:1; /* 0 = N:N, 1 = 1:N */
-    unsigned trigger:1; /* nonzero = edge triggered.  */
+    uint8_t enabled;
+    uint8_t pending;
+    uint8_t active;
+    uint8_t level;
+    bool model; /* 0 = N:N, 1 = 1:N */
+    bool trigger; /* nonzero = edge triggered.  */
 } gic_irq_state;
 
 typedef struct GICState {
     SysBusDevice busdev;
     qemu_irq parent_irq[NCPU];
-    int enabled;
-    int cpu_enabled[NCPU];
+    bool enabled;
+    bool cpu_enabled[NCPU];
 
     gic_irq_state irq_state[GIC_MAXIRQ];
-    int irq_target[GIC_MAXIRQ];
-    int priority1[GIC_INTERNAL][NCPU];
-    int priority2[GIC_MAXIRQ - GIC_INTERNAL];
-    int last_active[GIC_MAXIRQ][NCPU];
-
-    int priority_mask[NCPU];
-    int running_irq[NCPU];
-    int running_priority[NCPU];
-    int current_pending[NCPU];
+    uint8_t irq_target[GIC_MAXIRQ];
+    uint8_t priority1[GIC_INTERNAL][NCPU];
+    uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
+    uint16_t last_active[GIC_MAXIRQ][NCPU];
+
+    uint16_t priority_mask[NCPU];
+    uint16_t running_irq[NCPU];
+    uint16_t running_priority[NCPU];
+    uint16_t current_pending[NCPU];
 
     uint32_t num_cpu;
 
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index d198cfd..2351200 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -458,10 +458,10 @@ static void armv7m_nvic_reset(DeviceState *dev)
      * as enabled by default, and with a priority mask which allows
      * all interrupts through.
      */
-    s->gic.cpu_enabled[0] = 1;
+    s->gic.cpu_enabled[0] = true;
     s->gic.priority_mask[0] = 0x100;
     /* The NVIC as a whole is always enabled. */
-    s->gic.enabled = 1;
+    s->gic.enabled = true;
     systick_reset(s);
 }
 
commit bd7f92e59e7f40ddaeda40e55f7818c8121ecf1a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:17:59 2013 +0100

    vmstate: Add support for two dimensional arrays
    
    Add support for migrating two dimensional arrays, by defining
    a set of new macros VMSTATE_*_2DARRAY paralleling the existing
    VMSTATE_*_ARRAY macros. 2D arrays are handled the same for actual
    state serialization; the only difference is that the type check
    has to change for a 2D array.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Message-id: 1363975375-3166-2-git-send-email-peter.maydell at linaro.org

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 8184123..ebc4d09 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -164,6 +164,7 @@ extern const VMStateInfo vmstate_info_buffer;
 extern const VMStateInfo vmstate_info_unused_buffer;
 extern const VMStateInfo vmstate_info_bitmap;
 
+#define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0)
 #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
 #define type_check_pointer(t1,t2) ((t1**)0 - (t2*)0)
 
@@ -179,6 +180,10 @@ extern const VMStateInfo vmstate_info_bitmap;
     (offsetof(_state, _field) +                                      \
      type_check_array(_type, typeof_field(_state, _field), _num))
 
+#define vmstate_offset_2darray(_state, _field, _type, _n1, _n2)      \
+    (offsetof(_state, _field) +                                      \
+     type_check_2darray(_type, typeof_field(_state, _field), _n1, _n2))
+
 #define vmstate_offset_sub_array(_state, _field, _type, _start)      \
     (offsetof(_state, _field[_start]))
 
@@ -224,6 +229,16 @@ extern const VMStateInfo vmstate_info_bitmap;
     .offset     = vmstate_offset_array(_state, _field, _type, _num), \
 }
 
+#define VMSTATE_2DARRAY(_field, _state, _n1, _n2, _version, _info, _type) { \
+    .name       = (stringify(_field)),                                      \
+    .version_id = (_version),                                               \
+    .num        = (_n1) * (_n2),                                            \
+    .info       = &(_info),                                                 \
+    .size       = sizeof(_type),                                            \
+    .flags      = VMS_ARRAY,                                                \
+    .offset     = vmstate_offset_2darray(_state, _field, _type, _n1, _n2),  \
+}
+
 #define VMSTATE_ARRAY_TEST(_field, _state, _num, _test, _info, _type) {\
     .name         = (stringify(_field)),                              \
     .field_exists = (_test),                                          \
@@ -592,15 +607,27 @@ extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_UINT16_ARRAY_V(_f, _s, _n, _v)                         \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint16, uint16_t)
 
+#define VMSTATE_UINT16_2DARRAY_V(_f, _s, _n1, _n2, _v)                \
+    VMSTATE_2DARRAY(_f, _s, _n1, _n2, _v, vmstate_info_uint16, uint16_t)
+
 #define VMSTATE_UINT16_ARRAY(_f, _s, _n)                               \
     VMSTATE_UINT16_ARRAY_V(_f, _s, _n, 0)
 
+#define VMSTATE_UINT16_2DARRAY(_f, _s, _n1, _n2)                      \
+    VMSTATE_UINT16_2DARRAY_V(_f, _s, _n1, _n2, 0)
+
+#define VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, _v)                 \
+    VMSTATE_2DARRAY(_f, _s, _n1, _n2, _v, vmstate_info_uint8, uint8_t)
+
 #define VMSTATE_UINT8_ARRAY_V(_f, _s, _n, _v)                         \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint8, uint8_t)
 
 #define VMSTATE_UINT8_ARRAY(_f, _s, _n)                               \
     VMSTATE_UINT8_ARRAY_V(_f, _s, _n, 0)
 
+#define VMSTATE_UINT8_2DARRAY(_f, _s, _n1, _n2)                       \
+    VMSTATE_UINT8_2DARRAY_V(_f, _s, _n1, _n2, 0)
+
 #define VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v)                        \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint32, uint32_t)
 
commit b79269b78d0182fa7f4e23b779010145d0b4eaea
Author: Igor Mitsyanko <i.mitsyanko at gmail.com>
Date:   Fri Apr 5 16:17:59 2013 +0100

    hw/onenand.c: fix migration of dynamically allocated buffer "otp"
    
    VMSTATE_BUFFER_UNSAFE should be used for buffers inlined in device state, not
    for buffers allocated dynamically. Change to VMSTATE_BUFFER_POINTER_UNSAFE macro,
    which will do migration right.
    
    Signed-off-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1362923278-4080-4-git-send-email-i.mitsyanko at gmail.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/onenand.c b/hw/onenand.c
index ddba366..57a346d 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -185,7 +185,8 @@ static const VMStateDescription vmstate_onenand = {
         VMSTATE_UINT8(ecc.cp, OneNANDState),
         VMSTATE_UINT16_ARRAY(ecc.lp, OneNANDState, 2),
         VMSTATE_UINT16(ecc.count, OneNANDState),
-        VMSTATE_BUFFER_UNSAFE(otp, OneNANDState, 0, ((64 + 2) << PAGE_SHIFT)),
+        VMSTATE_BUFFER_POINTER_UNSAFE(otp, OneNANDState, 0,
+            ((64 + 2) << PAGE_SHIFT)),
         VMSTATE_END_OF_LIST()
     }
 };
commit 5f00679ee98b1643ff652bbf982dffe1b432596e
Author: Igor Mitsyanko <i.mitsyanko at gmail.com>
Date:   Fri Apr 5 16:17:59 2013 +0100

    hw/sd.c: fix migration of dynamically allocated buffer "buf"
    
    VMSTATE_BUFFER_UNSAFE should be used for buffers inlined in device state, not
    for buffers allocated dynamically. Change to VMSTATE_BUFFER_POINTER_UNSAFE macro,
    which will do migration right.
    
    Signed-off-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Michael Walle <michael at walle.cc>
    Message-id: 1362923278-4080-3-git-send-email-i.mitsyanko at gmail.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/hw/sd.c b/hw/sd.c
index a895123..66c4014 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -478,7 +478,7 @@ static const VMStateDescription sd_vmstate = {
         VMSTATE_UINT64(data_start, SDState),
         VMSTATE_UINT32(data_offset, SDState),
         VMSTATE_UINT8_ARRAY(data, SDState, 512),
-        VMSTATE_BUFFER_UNSAFE(buf, SDState, 1, 512),
+        VMSTATE_BUFFER_POINTER_UNSAFE(buf, SDState, 1, 512),
         VMSTATE_BOOL(enable, SDState),
         VMSTATE_END_OF_LIST()
     }
commit 8070568b9aa8d93b3729ab7e9ca0ef8a6351d2bd
Author: Igor Mitsyanko <i.mitsyanko at gmail.com>
Date:   Fri Apr 5 16:17:58 2013 +0100

    vmstate.h: introduce VMSTATE_BUFFER_POINTER_UNSAFE macro
    
    Macro could be used to migrate a dynamically allocated buffer of known size.
    
    Signed-off-by: Igor Mitsyanko <i.mitsyanko at gmail.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1362923278-4080-2-git-send-email-i.mitsyanko at gmail.com
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 65918a9..8184123 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -436,6 +436,15 @@ extern const VMStateInfo vmstate_info_bitmap;
     .offset     = offsetof(_state, _field),                          \
 }
 
+#define VMSTATE_BUFFER_POINTER_UNSAFE(_field, _state, _version, _size) { \
+    .name       = (stringify(_field)),                               \
+    .version_id = (_version),                                        \
+    .size       = (_size),                                           \
+    .info       = &vmstate_info_buffer,                              \
+    .flags      = VMS_BUFFER|VMS_POINTER,                            \
+    .offset     = offsetof(_state, _field),                          \
+}
+
 #define VMSTATE_UNUSED_BUFFER(_test, _version, _size) {              \
     .name         = "unused",                                        \
     .field_exists = (_test),                                         \
commit 28092a23e6e2cb8298c1381f4f046842ffd376eb
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:17:58 2013 +0100

    hw/arm_mptimer: Save the timer state
    
    Add a missing VMSTATE_TIMER() entry to the arm_mptimer vmstate
    description; this omission meant that we would probably hang on reload
    when the timer failed to fire.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 1363967348-3044-1-git-send-email-peter.maydell at linaro.org

diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c
index f59a9f1..317f5e4 100644
--- a/hw/arm_mptimer.c
+++ b/hw/arm_mptimer.c
@@ -253,14 +253,15 @@ static int arm_mptimer_init(SysBusDevice *dev)
 
 static const VMStateDescription vmstate_timerblock = {
     .name = "arm_mptimer_timerblock",
-    .version_id = 1,
-    .minimum_version_id = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(count, TimerBlock),
         VMSTATE_UINT32(load, TimerBlock),
         VMSTATE_UINT32(control, TimerBlock),
         VMSTATE_UINT32(status, TimerBlock),
         VMSTATE_INT64(tick, TimerBlock),
+        VMSTATE_TIMER(timer, TimerBlock),
         VMSTATE_END_OF_LIST()
     }
 };
commit e8945b4f2a65fc2872cc31a5141e136fd27d0af8
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:17:58 2013 +0100

    pl050: Don't send always-constant is_mouse field
    
    The is_mouse field of the pl050 state structure is constant (it tracks
    whether this is a 'pl050_keyboard' or 'pl050_mouse'), so there's
    no need to include it in the VMState structure.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1363628480-29306-1-git-send-email-peter.maydell at linaro.org

diff --git a/hw/pl050.c b/hw/pl050.c
index bc31ab6..76735a0 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -24,14 +24,13 @@ typedef struct {
 
 static const VMStateDescription vmstate_pl050 = {
     .name = "pl050",
-    .version_id = 1,
-    .minimum_version_id = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(cr, pl050_state),
         VMSTATE_UINT32(clk, pl050_state),
         VMSTATE_UINT32(last, pl050_state),
         VMSTATE_INT32(pending, pl050_state),
-        VMSTATE_INT32(is_mouse, pl050_state),
         VMSTATE_END_OF_LIST()
     }
 };
commit 591f73f642a5f3c822c3efaae8d83a174371a4f5
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Apr 5 16:17:58 2013 +0100

    hw/arm/nseries: don't print to stdout or stderr
    
    Remove various bits of printing to stdout or stderr from the
    nseries code, replacing it with a qemu log message where there's
    an appropriate log category, and just dropping the output for
    some of the more debug-like printing.
    
    In particular, this will get rid of the 'mipid_reset' message
    you currently get from 'make check'.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1363368565-24546-1-git-send-email-peter.maydell at linaro.org

diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
index 6747c1c..b28e7d3 100644
--- a/hw/arm/nseries.c
+++ b/hw/arm/nseries.c
@@ -129,8 +129,6 @@ static void n800_mmc_cs_cb(void *opaque, int line, int level)
     /* TODO: this seems to actually be connected to the menelaus, to
      * which also both MMC slots connect.  */
     omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
-
-    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
 }
 
 static void n8x0_gpio_setup(struct n800_s *s)
@@ -428,9 +426,6 @@ struct mipid_s {
 
 static void mipid_reset(struct mipid_s *s)
 {
-    if (!s->sleep)
-        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
-
     s->pm = 0;
     s->cmd = 0;
 
@@ -578,11 +573,9 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
 
     case 0x28:	/* DISPOFF */
         s->onoff = 0;
-        fprintf(stderr, "%s: Display off\n", __FUNCTION__);
         break;
     case 0x29:	/* DISPON */
         s->onoff = 1;
-        fprintf(stderr, "%s: Display on\n", __FUNCTION__);
         break;
 
     case 0x2a:	/* CASET */
@@ -669,7 +662,8 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
 
     default:
     bad_cmd:
-        fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd);
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: unknown command %02x\n", __func__, s->cmd);
         break;
     }
 
@@ -1347,7 +1341,6 @@ static void n8x0_init(QEMUMachineInitArgs *args,
 
     if (option_rom[0].name &&
         (args->boot_device[0] == 'n' || !args->kernel_filename)) {
-        int rom_size;
         uint8_t nolo_tags[0x10000];
         /* No, wait, better start at the ROM.  */
         s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000;
@@ -1361,10 +1354,9 @@ static void n8x0_init(QEMUMachineInitArgs *args,
          *
          * The code above is for loading the `zImage' file from Nokia
          * images.  */
-        rom_size = load_image_targphys(option_rom[0].name,
-                                       OMAP2_Q2_BASE + 0x400000,
-                                       sdram_size - 0x400000);
-        printf("%i bytes of image loaded\n", rom_size);
+        load_image_targphys(option_rom[0].name,
+                            OMAP2_Q2_BASE + 0x400000,
+                            sdram_size - 0x400000);
 
         n800_setup_nolo_tags(nolo_tags);
         cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000);
commit 150a470b64c548b7539ea47526f345f15ebac355
Merge: d05ef16 4bf0bb8
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Apr 5 08:55:14 2013 -0500

    Merge remote-tracking branch 'luiz/queue/qmp' into staging
    
    # By Luiz Capitulino
    # Via Luiz Capitulino
    * luiz/queue/qmp:
      chardev: drop the Memory chardev driver
      hmp: human-monitor-command: stop using the Memory chardev driver
      Monitor: Make output buffer dynamic
      qstring: add qstring_get_length()

commit f1922e36e267eae0c9d70e8660830e081878bdfc
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Apr 4 11:04:12 2013 +1000

    xilinx_zynq: Cleanup ssi_create_slave
    
    With the recent m25p80 cleanup there is no need to use
    ssi_create_slave_no_init() anymore. Just use ssi_create_slave().
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 6f36286..5b9257a 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -86,8 +86,7 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
         spi = (SSIBus *)qdev_get_child_bus(dev, bus_name);
 
         for (j = 0; j < num_ss; ++j) {
-            flash_dev = ssi_create_slave_no_init(spi, "n25q128");
-            qdev_init_nofail(flash_dev);
+            flash_dev = ssi_create_slave(spi, "n25q128");
 
             cs_line = qdev_get_gpio_in(flash_dev, 0);
             sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line);
commit e641080fdc1e81290564e1e9ec4fe7637011fa82
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Thu Apr 4 11:04:11 2013 +1000

    petalogix_ml605_mmu: Cleanup ssi_create_slave()
    
    With the recent m25p80 cleanup there is no need to use
    ssi_create_slave_no_init() anymore. Just use ssi_create_slave().
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index cfc0220..07dc808 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -158,8 +158,7 @@ petalogix_ml605_init(QEMUMachineInitArgs *args)
         for (i = 0; i < NUM_SPI_FLASHES; i++) {
             qemu_irq cs_line;
 
-            dev = ssi_create_slave_no_init(spi, "n25q128");
-            qdev_init_nofail(dev);
+            dev = ssi_create_slave(spi, "n25q128");
             cs_line = qdev_get_gpio_in(dev, 0);
             sysbus_connect_irq(busdev, i+1, cs_line);
         }
commit 5b90a86629dcc075be294524696e6199266f72ad
Author: Richard Henderson <rth at twiddle.net>
Date:   Sat Mar 30 10:03:25 2013 -0700

    target-s390: Fix SRNMT
    
    Fallthough into abort = oops.
    
    Cc: qemu-trivial at nongnu.org
    Cc: Alexander Graf <agraf at suse.de>
    Signed-off-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index a4f2194..0c3cf68 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -3088,6 +3088,7 @@ static ExitStatus op_srnm(DisasContext *s, DisasOps *o)
         break;
     case 0xb9: /* SRNMT */
         pos = 4, len = 3;
+        break;
     default:
         tcg_abort();
     }
commit 4bf0bb8014ac2ac61b1004f5d92b2a4594d48017
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Apr 2 15:29:29 2013 -0400

    chardev: drop the Memory chardev driver
    
    It's not used anymore since the last commit.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/qemu-char.c b/qemu-char.c
index e5eb8dd..0f7f32d 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2796,70 +2796,6 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     return NULL;
 }
 
-/***********************************************************/
-/* Memory chardev */
-typedef struct {
-    size_t outbuf_size;
-    size_t outbuf_capacity;
-    uint8_t *outbuf;
-} MemoryDriver;
-
-static int mem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
-{
-    MemoryDriver *d = chr->opaque;
-
-    /* TODO: the QString implementation has the same code, we should
-     * introduce a generic way to do this in cutils.c */
-    if (d->outbuf_capacity < d->outbuf_size + len) {
-        /* grow outbuf */
-        d->outbuf_capacity += len;
-        d->outbuf_capacity *= 2;
-        d->outbuf = g_realloc(d->outbuf, d->outbuf_capacity);
-    }
-
-    memcpy(d->outbuf + d->outbuf_size, buf, len);
-    d->outbuf_size += len;
-
-    return len;
-}
-
-void qemu_chr_init_mem(CharDriverState *chr)
-{
-    MemoryDriver *d;
-
-    d = g_malloc(sizeof(*d));
-    d->outbuf_size = 0;
-    d->outbuf_capacity = 4096;
-    d->outbuf = g_malloc0(d->outbuf_capacity);
-
-    memset(chr, 0, sizeof(*chr));
-    chr->opaque = d;
-    chr->chr_write = mem_chr_write;
-}
-
-QString *qemu_chr_mem_to_qs(CharDriverState *chr)
-{
-    MemoryDriver *d = chr->opaque;
-    return qstring_from_substr((char *) d->outbuf, 0, d->outbuf_size - 1);
-}
-
-/* NOTE: this driver can not be closed with qemu_chr_delete()! */
-void qemu_chr_close_mem(CharDriverState *chr)
-{
-    MemoryDriver *d = chr->opaque;
-
-    g_free(d->outbuf);
-    g_free(chr->opaque);
-    chr->opaque = NULL;
-    chr->chr_write = NULL;
-}
-
-size_t qemu_chr_mem_osize(const CharDriverState *chr)
-{
-    const MemoryDriver *d = chr->opaque;
-    return d->outbuf_size;
-}
-
 /*********************************************************/
 /* Ring buffer chardev */
 
commit 48c043d0d1835c64b571c484a9f229fe6d220287
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Tue Apr 2 15:07:33 2013 -0400

    hmp: human-monitor-command: stop using the Memory chardev driver
    
    The Memory chardev driver was added because, as the Monitor's output
    buffer was static, we needed a way to accumulate the output of an
    HMP commmand when ran by human-monitor-command.
    
    However, the Monitor's output buffer is now dynamic, so it's possible
    for the human-monitor-command to use it instead of the Memory chardev
    driver.
    
    This commit does that change, but there are two important
    observations about it:
    
     1. We need a way to signal to the Monitor that it shouldn't call
        chardev functions when flushing its output. This is done
        by adding a new flag to the Monitor object called skip_flush
    	(which is set to true by qmp_human_monitor_command())
    
     2. The current code has buffered semantics: QMP clients will
        only see a command's output if it flushes its output with
    	a new-line character. This commit changes this to unbuffered,
    	which means that QMP clients will see a command's output
    	whenever the command prints anything.
    
    	I don't think this will matter in practice though, as I believe
    	all HMP commands print the new-line character anyway.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/monitor.c b/monitor.c
index 8712c53..b4bda77 100644
--- a/monitor.c
+++ b/monitor.c
@@ -188,6 +188,7 @@ struct Monitor {
     int reset_seen;
     int flags;
     int suspend_cnt;
+    bool skip_flush;
     QString *outbuf;
     ReadLineState *rs;
     MonitorControl *mc;
@@ -273,6 +274,10 @@ void monitor_flush(Monitor *mon)
     size_t len;
     const char *buf;
 
+    if (mon->skip_flush) {
+        return;
+    }
+
     buf = qstring_get_str(mon->outbuf);
     len = qstring_get_length(mon->outbuf);
 
@@ -675,13 +680,10 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
 {
     char *output = NULL;
     Monitor *old_mon, hmp;
-    CharDriverState mchar;
 
     memset(&hmp, 0, sizeof(hmp));
     hmp.outbuf = qstring_new();
-
-    qemu_chr_init_mem(&mchar);
-    hmp.chr = &mchar;
+    hmp.skip_flush = true;
 
     old_mon = cur_mon;
     cur_mon = &hmp;
@@ -699,17 +701,14 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
     handle_user_command(&hmp, command_line);
     cur_mon = old_mon;
 
-    if (qemu_chr_mem_osize(hmp.chr) > 0) {
-        QString *str = qemu_chr_mem_to_qs(hmp.chr);
-        output = g_strdup(qstring_get_str(str));
-        QDECREF(str);
+    if (qstring_get_length(hmp.outbuf) > 0) {
+        output = g_strdup(qstring_get_str(hmp.outbuf));
     } else {
         output = g_strdup("");
     }
 
 out:
     QDECREF(hmp.outbuf);
-    qemu_chr_close_mem(hmp.chr);
     return output;
 }
 
commit e1f2641b5926d20f63d36f0de45206be774da8da
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Mar 25 13:52:26 2013 -0400

    Monitor: Make output buffer dynamic
    
    Commit f628926bb423fa8a7e0b114511400ea9df38b76a changed monitor_flush()
    to retry on qemu_chr_fe_write() errors. However, the Monitor's output
    buffer can keep growing while the retry is not issued and this can
    cause the buffer to overflow.
    
    To reproduce this issue, just start qemu and type on the Monitor:
    
    (qemu) ?
    
    This will cause an assertion to trig.
    
    To fix this problem this commit makes the Monitor buffer dynamic,
    which means that it can grow as much as needed.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/monitor.c b/monitor.c
index 4ec1db9..8712c53 100644
--- a/monitor.c
+++ b/monitor.c
@@ -188,8 +188,7 @@ struct Monitor {
     int reset_seen;
     int flags;
     int suspend_cnt;
-    uint8_t outbuf[1024];
-    int outbuf_index;
+    QString *outbuf;
     ReadLineState *rs;
     MonitorControl *mc;
     CPUArchState *mon_cpu;
@@ -271,45 +270,52 @@ static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
 void monitor_flush(Monitor *mon)
 {
     int rc;
+    size_t len;
+    const char *buf;
+
+    buf = qstring_get_str(mon->outbuf);
+    len = qstring_get_length(mon->outbuf);
 
-    if (mon && mon->outbuf_index != 0 && !mon->mux_out) {
-        rc = qemu_chr_fe_write(mon->chr, mon->outbuf, mon->outbuf_index);
-        if (rc == mon->outbuf_index) {
+    if (mon && len && !mon->mux_out) {
+        rc = qemu_chr_fe_write(mon->chr, (const uint8_t *) buf, len);
+        if (rc == len) {
             /* all flushed */
-            mon->outbuf_index = 0;
+            QDECREF(mon->outbuf);
+            mon->outbuf = qstring_new();
             return;
         }
         if (rc > 0) {
             /* partinal write */
-            memmove(mon->outbuf, mon->outbuf + rc, mon->outbuf_index - rc);
-            mon->outbuf_index -= rc;
+            QString *tmp = qstring_from_str(buf + rc);
+            QDECREF(mon->outbuf);
+            mon->outbuf = tmp;
         }
         qemu_chr_fe_add_watch(mon->chr, G_IO_OUT, monitor_unblocked, mon);
     }
 }
 
-/* flush at every end of line or if the buffer is full */
+/* flush at every end of line */
 static void monitor_puts(Monitor *mon, const char *str)
 {
     char c;
 
     for(;;) {
-        assert(mon->outbuf_index < sizeof(mon->outbuf) - 1);
         c = *str++;
         if (c == '\0')
             break;
-        if (c == '\n')
-            mon->outbuf[mon->outbuf_index++] = '\r';
-        mon->outbuf[mon->outbuf_index++] = c;
-        if (mon->outbuf_index >= (sizeof(mon->outbuf) - 1)
-            || c == '\n')
+        if (c == '\n') {
+            qstring_append_chr(mon->outbuf, '\r');
+        }
+        qstring_append_chr(mon->outbuf, c);
+        if (c == '\n') {
             monitor_flush(mon);
+        }
     }
 }
 
 void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
 {
-    char buf[4096];
+    char *buf;
 
     if (!mon)
         return;
@@ -318,8 +324,9 @@ void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
         return;
     }
 
-    vsnprintf(buf, sizeof(buf), fmt, ap);
+    buf = g_strdup_vprintf(fmt, ap);
     monitor_puts(mon, buf);
+    g_free(buf);
 }
 
 void monitor_printf(Monitor *mon, const char *fmt, ...)
@@ -671,6 +678,8 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
     CharDriverState mchar;
 
     memset(&hmp, 0, sizeof(hmp));
+    hmp.outbuf = qstring_new();
+
     qemu_chr_init_mem(&mchar);
     hmp.chr = &mchar;
 
@@ -699,6 +708,7 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
     }
 
 out:
+    QDECREF(hmp.outbuf);
     qemu_chr_close_mem(hmp.chr);
     return output;
 }
@@ -4749,6 +4759,7 @@ void monitor_init(CharDriverState *chr, int flags)
     }
 
     mon = g_malloc0(sizeof(*mon));
+    mon->outbuf = qstring_new();
 
     mon->chr = chr;
     mon->flags = flags;
commit 54d49ac99227aff646ac940abfab3417f5cb1693
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date:   Mon Mar 25 13:46:37 2013 -0400

    qstring: add qstring_get_length()
    
    Long overdue.
    
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Acked-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h
index 0e690f4..1bc3666 100644
--- a/include/qapi/qmp/qstring.h
+++ b/include/qapi/qmp/qstring.h
@@ -26,6 +26,7 @@ typedef struct QString {
 QString *qstring_new(void);
 QString *qstring_from_str(const char *str);
 QString *qstring_from_substr(const char *str, int start, int end);
+size_t qstring_get_length(const QString *qstring);
 const char *qstring_get_str(const QString *qstring);
 void qstring_append_int(QString *qstring, int64_t value);
 void qstring_append(QString *qstring, const char *str);
diff --git a/qobject/qstring.c b/qobject/qstring.c
index 5f7376c..607b7a1 100644
--- a/qobject/qstring.c
+++ b/qobject/qstring.c
@@ -32,6 +32,14 @@ QString *qstring_new(void)
 }
 
 /**
+ * qstring_get_length(): Get the length of a QString
+ */
+size_t qstring_get_length(const QString *qstring)
+{
+    return qstring->length;
+}
+
+/**
  * qstring_from_substr(): Create a new QString from a C string substring
  *
  * Return string reference
commit abe20840166e6f04d3ab60f8d53a2ff5907bd942
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Mar 28 14:33:24 2013 +0000

    linux-user: Don't omit comma for strace of rt_sigaction()
    
    Pass the 'last' parameter of print_signal() through to
    print_raw_param(); this fixes a problem where we weren't printing
    the comma separator for strace of rt_sigaction() when the signal
    was an unnamed (ie realtime) one:
      6856 rt_sigaction(230xf6fff870,0xf6fff8fc) = 0
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 0fbae3c..ea6c1d2 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -143,7 +143,7 @@ print_signal(abi_ulong arg, int last)
     case TARGET_SIGTTOU: signal_name = "SIGTTOU"; break;
     }
     if (signal_name == NULL) {
-        print_raw_param("%ld", arg, 1);
+        print_raw_param("%ld", arg, last);
         return;
     }
     gemu_log("%s%s", signal_name, get_comma(last));
commit 2bd01ac1e238c76e201ba21f314cec46437d2c5a
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Thu Mar 28 11:18:40 2013 -0400

    test-visitor-serialization: Fix some memory leaks
    
    This patch fixes some of the memory leaks in test-visitor-serialization but not all of them.
    
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
index 3c6b8df..e84926f 100644
--- a/tests/test-visitor-serialization.c
+++ b/tests/test-visitor-serialization.c
@@ -258,6 +258,7 @@ static void test_primitives(gconstpointer opaque)
     g_assert(pt_copy != NULL);
     if (pt->type == PTYPE_STRING) {
         g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
+        g_free((char *)pt_copy->value.string);
     } else if (pt->type == PTYPE_NUMBER) {
         /* we serialize with %f for our reference visitors, so rather than fuzzy
          * floating math to test "equality", just compare the formatted values
@@ -275,6 +276,7 @@ static void test_primitives(gconstpointer opaque)
 
     ops->cleanup(serialize_data);
     g_free(args);
+    g_free(pt_copy);
 }
 
 static void test_struct(gconstpointer opaque)
@@ -660,6 +662,7 @@ static void qmp_deserialize(void **native_out, void *datap,
 
     QDECREF(output_json);
     d->qiv = qmp_input_visitor_new(obj);
+    qobject_decref(obj);
     visit(qmp_input_get_visitor(d->qiv), native_out, errp);
 }
 
@@ -668,9 +671,12 @@ static void qmp_cleanup(void *datap)
     QmpSerializeData *d = datap;
     qmp_output_visitor_cleanup(d->qov);
     qmp_input_visitor_cleanup(d->qiv);
+
+    g_free(d);
 }
 
 typedef struct StringSerializeData {
+    char *string;
     StringOutputVisitor *sov;
     StringInputVisitor *siv;
 } StringSerializeData;
@@ -690,15 +696,19 @@ static void string_deserialize(void **native_out, void *datap,
 {
     StringSerializeData *d = datap;
 
-    d->siv = string_input_visitor_new(string_output_get_string(d->sov));
+    d->string = string_output_get_string(d->sov);
+    d->siv = string_input_visitor_new(d->string);
     visit(string_input_get_visitor(d->siv), native_out, errp);
 }
 
 static void string_cleanup(void *datap)
 {
     StringSerializeData *d = datap;
+
     string_output_visitor_cleanup(d->sov);
     string_input_visitor_cleanup(d->siv);
+    g_free(d->string);
+    g_free(d);
 }
 
 /* visitor registration, test harness */
commit d05ef160453e98546a4197496dc8a3cb2defac53
Author: Brad Smith <brad at comstyle.com>
Date:   Thu Apr 4 20:37:53 2013 -0400

    Allow clock_gettime() monotonic clock to be utilized on more OS's
    
    Allow the clock_gettime() code using monotonic clock to be utilized on
    more POSIX compliannt OS's. This started as a fix for OpenBSD which was
    listed in one function as part of the previous hard coded list of OS's
    for the functions to support but not in the other.
    
    Signed-off-by: Brad Smith <brad at comstyle.com>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 20130405003748.GH884 at rox.home.comstyle.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 1766b2d..c363190 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -117,8 +117,7 @@ extern int use_rt_clock;
 
 static inline int64_t get_clock(void)
 {
-#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \
-    || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+#ifdef CLOCK_MONOTONIC
     if (use_rt_clock) {
         struct timespec ts;
         clock_gettime(CLOCK_MONOTONIC, &ts);
diff --git a/util/qemu-timer-common.c b/util/qemu-timer-common.c
index 16f5e75..95e0847 100644
--- a/util/qemu-timer-common.c
+++ b/util/qemu-timer-common.c
@@ -49,9 +49,7 @@ int use_rt_clock;
 static void __attribute__((constructor)) init_get_clock(void)
 {
     use_rt_clock = 0;
-#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \
-    || defined(__DragonFly__) || defined(__FreeBSD_kernel__) \
-    || defined(__OpenBSD__)
+#ifdef CLOCK_MONOTONIC
     {
         struct timespec ts;
         if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
commit c5a98cf333997616147a161ef4e4cf71bb9bd00a
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:22 2013 +0100

    pc_acpi_init(): don't bail as soon as failing to find default DSDT
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-11-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 09d44fc..ebbf059 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -891,9 +891,7 @@ void pc_cpus_init(const char *cpu_model)
 
 void pc_acpi_init(const char *default_dsdt)
 {
-    char *filename = NULL, *arg = NULL;
-    QemuOpts *opts;
-    Error *err = NULL;
+    char *filename;
 
     if (acpi_tables != NULL) {
         /* manually set via -acpitable, leave it alone */
@@ -903,23 +901,26 @@ void pc_acpi_init(const char *default_dsdt)
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, default_dsdt);
     if (filename == NULL) {
         fprintf(stderr, "WARNING: failed to find %s\n", default_dsdt);
-        return;
-    }
+    } else {
+        char *arg;
+        QemuOpts *opts;
+        Error *err = NULL;
 
-    arg = g_strdup_printf("file=%s", filename);
+        arg = g_strdup_printf("file=%s", filename);
 
-    /* creates a deep copy of "arg" */
-    opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0);
-    g_assert(opts != NULL);
+        /* creates a deep copy of "arg" */
+        opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0);
+        g_assert(opts != NULL);
 
-    acpi_table_add(opts, &err);
-    if (err) {
-        fprintf(stderr, "WARNING: failed to load %s: %s\n", filename,
-                error_get_pretty(err));
-        error_free(err);
+        acpi_table_add(opts, &err);
+        if (err) {
+            fprintf(stderr, "WARNING: failed to load %s: %s\n", filename,
+                    error_get_pretty(err));
+            error_free(err);
+        }
+        g_free(arg);
+        g_free(filename);
     }
-    g_free(arg);
-    g_free(filename);
 }
 
 void *pc_memory_init(MemoryRegion *system_memory,
commit 3a4a4697aacdd58b77f8bca6f2c0ce307b213506
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:21 2013 +0100

    Introduce IO_APIC_DEFAULT_ADDRESS for 0xfec00000
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-10-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 2e915ec..09d44fc 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -72,6 +72,8 @@
 #define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
 #define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
 
+#define IO_APIC_DEFAULT_ADDRESS 0xfec00000
+
 #define E820_NR_ENTRIES		16
 
 struct e820_entry {
@@ -1169,7 +1171,7 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
     }
     qdev_init_nofail(dev);
     d = SYS_BUS_DEVICE(dev);
-    sysbus_mmio_map(d, 0, 0xfec00000);
+    sysbus_mmio_map(d, 0, IO_APIC_DEFAULT_ADDRESS);
 
     for (i = 0; i < IOAPIC_NUM_PINS; i++) {
         gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
commit dab8623430926a8c55a149c22b2b8e2edb786ae3
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:20 2013 +0100

    extract/unify the constant 0xfee00000 as APIC_DEFAULT_ADDRESS
    
    A common dependency of the constant's current users:
    - hw/apic_common.c
    - hw/i386/kvmvapic.c
    - target-i386/cpu.c
    is "target-i386/cpu.h".
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-9-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/apic_common.c b/hw/apic_common.c
index d0c2616..3798509 100644
--- a/hw/apic_common.c
+++ b/hw/apic_common.c
@@ -218,7 +218,7 @@ static void apic_reset_common(DeviceState *d)
     bool bsp;
 
     bsp = cpu_is_bsp(s->cpu);
-    s->apicbase = 0xfee00000 |
+    s->apicbase = APIC_DEFAULT_ADDRESS |
         (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
 
     s->vapic_paddr = 0;
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index c151c95..cc95e5c 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -13,8 +13,6 @@
 #include "sysemu/kvm.h"
 #include "hw/apic_internal.h"
 
-#define APIC_DEFAULT_ADDRESS    0xfee00000
-
 #define VAPIC_IO_PORT           0x7e
 
 #define VAPIC_CPU_SHIFT         7
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index bf717d5..69c3570 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2049,8 +2049,6 @@ static void mce_init(X86CPU *cpu)
     }
 }
 
-#define MSI_ADDR_BASE 0xfee00000
-
 #ifndef CONFIG_USER_ONLY
 static void x86_cpu_apic_init(X86CPU *cpu, Error **errp)
 {
@@ -2090,7 +2088,7 @@ static void x86_cpu_apic_init(X86CPU *cpu, Error **errp)
            on the global memory bus. */
         /* XXX: what if the base changes? */
         sysbus_mmio_map_overlap(SYS_BUS_DEVICE(env->apic_state), 0,
-                                MSI_ADDR_BASE, 0x1000);
+                                APIC_DEFAULT_ADDRESS, 0x1000);
         apic_mapped = 1;
     }
 }
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 5284ebc..069a2e2 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -1267,4 +1267,6 @@ const char *get_register_name_32(unsigned int reg);
 uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index);
 void enable_compat_apic_id_mode(void);
 
+#define APIC_DEFAULT_ADDRESS 0xfee00000
+
 #endif /* CPU_I386_H */
commit 23084327dc5c2f42e8a1c3e39ec565e344c7f52e
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:19 2013 +0100

    like acpi_table_install(), acpi_table_add() should propagate Errors
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-8-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index 0373a58..c2cbc71 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -1106,8 +1106,13 @@ int qemu_uuid_parse(const char *str, uint8_t *uuid)
 void do_acpitable_option(const QemuOpts *opts)
 {
 #ifdef TARGET_I386
-    if (acpi_table_add(opts) < 0) {
-        fprintf(stderr, "Wrong acpi table provided\n");
+    Error *err = NULL;
+
+    acpi_table_add(opts, &err);
+    if (err) {
+        fprintf(stderr, "Wrong acpi table provided: %s\n",
+                error_get_pretty(err));
+        error_free(err);
         exit(1);
     }
 #endif
diff --git a/hw/acpi.c b/hw/acpi.c
index ec1ade7..856da81 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -229,7 +229,7 @@ static void acpi_table_install(const char unsigned *blob, size_t bloblen,
                                       ACPI_TABLE_PFX_SIZE, acpi_payload_size);
 }
 
-int acpi_table_add(const QemuOpts *opts)
+void acpi_table_add(const QemuOpts *opts, Error **errp)
 {
     AcpiTableOptions *hdrs = NULL;
     Error *err = NULL;
@@ -306,12 +306,7 @@ out:
         qapi_dealloc_visitor_cleanup(dv);
     }
 
-    if (err) {
-        fprintf(stderr, "%s\n", error_get_pretty(err));
-        error_free(err);
-        return -1;
-    }
-    return 0;
+    error_propagate(errp, err);
 }
 
 static void acpi_notify_wakeup(Notifier *notifier, void *data)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index d1bc0de..2e915ec 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -891,6 +891,7 @@ void pc_acpi_init(const char *default_dsdt)
 {
     char *filename = NULL, *arg = NULL;
     QemuOpts *opts;
+    Error *err = NULL;
 
     if (acpi_tables != NULL) {
         /* manually set via -acpitable, leave it alone */
@@ -909,8 +910,11 @@ void pc_acpi_init(const char *default_dsdt)
     opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0);
     g_assert(opts != NULL);
 
-    if (acpi_table_add(opts) != 0) {
-        fprintf(stderr, "WARNING: failed to load %s\n", filename);
+    acpi_table_add(opts, &err);
+    if (err) {
+        fprintf(stderr, "WARNING: failed to load %s: %s\n", filename,
+                error_get_pretty(err));
+        error_free(err);
     }
     g_free(arg);
     g_free(filename);
diff --git a/hw/pc.h b/hw/pc.h
index 613520d..55964ce 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -113,7 +113,7 @@ extern char unsigned *acpi_tables;
 extern size_t acpi_tables_len;
 
 void acpi_bios_init(void);
-int acpi_table_add(const QemuOpts *opts);
+void acpi_table_add(const QemuOpts *opts, Error **errp);
 
 /* acpi_piix.c */
 
commit e980f2bf0a39cb524259bb70084e0f75b92c8f39
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:18 2013 +0100

    acpi_table_add(): extract and reimplement internals
    
    The new function acpi_table_install() installs any blob the caller passes
    in. In the next patches this function will be promoted from helper role to
    extern.
    
    Reimplementing the logic should make it easier to understand. It also
    removes a buffer overflow when
    
        has_header &&
        cumulative_file_size < ACPI_TABLE_HDR_SIZE - ACPI_TABLE_PFX_SIZE
    
    (In that case the g_realloc() call in the read() loop used to shrink the
    "acpi_tables" array, causing an out-of-bounds read access when copying the
    header out of "acpi_tables".)
    
    The new code isn't more daring alignment-wise than its predecessor:
    "acpi_table_header" is packed, and the uint32_t fields are at offsets 6,
    26, and 34.
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-7-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi.c b/hw/acpi.c
index 1aca458..ec1ade7 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -30,7 +30,7 @@
 
 struct acpi_table_header {
     uint16_t _length;         /* our length, not actual part of the hdr */
-                              /* XXX why we have 2 length fields here? */
+                              /* allows easier parsing for fw_cfg clients */
     char sig[4];              /* ACPI signature (4 ASCII characters) */
     uint32_t length;          /* Length of table, in bytes, including header */
     uint8_t revision;         /* ACPI Specification minor version # */
@@ -45,8 +45,7 @@ struct acpi_table_header {
 #define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header)
 #define ACPI_TABLE_PFX_SIZE sizeof(uint16_t)  /* size of the extra prefix */
 
-static const char unsigned dfl_hdr[ACPI_TABLE_HDR_SIZE] =
-    "\0\0"                   /* fake _length (2) */
+static const char unsigned dfl_hdr[ACPI_TABLE_HDR_SIZE - ACPI_TABLE_PFX_SIZE] =
     "QEMU\0\0\0\0\1\0"       /* sig (4), len(4), revno (1), csum (1) */
     "QEMUQEQEMUQEMU\1\0\0\0" /* OEM id (6), table (8), revno (4) */
     "QEMU\1\0\0\0"           /* ASL compiler ID (4), version (4) */
@@ -79,19 +78,165 @@ static int acpi_checksum(const uint8_t *data, int len)
     return (-sum) & 0xff;
 }
 
+
+/* Install a copy of the ACPI table specified in @blob.
+ *
+ * If @has_header is set, @blob starts with the System Description Table Header
+ * structure. Otherwise, "dfl_hdr" is prepended. In any case, each header field
+ * is optionally overwritten from @hdrs.
+ *
+ * It is valid to call this function with
+ * (@blob == NULL && bloblen == 0 && !has_header).
+ *
+ * @hdrs->file and @hdrs->data are ignored.
+ *
+ * SIZE_MAX is considered "infinity" in this function.
+ *
+ * The number of tables that can be installed is not limited, but the 16-bit
+ * counter at the beginning of "acpi_tables" wraps around after UINT16_MAX.
+ */
+static void acpi_table_install(const char unsigned *blob, size_t bloblen,
+                               bool has_header,
+                               const struct AcpiTableOptions *hdrs,
+                               Error **errp)
+{
+    size_t body_start;
+    const char unsigned *hdr_src;
+    size_t body_size, acpi_payload_size;
+    struct acpi_table_header *ext_hdr;
+    unsigned changed_fields;
+
+    /* Calculate where the ACPI table body starts within the blob, plus where
+     * to copy the ACPI table header from.
+     */
+    if (has_header) {
+        /*   _length             | ACPI header in blob | blob body
+         *   ^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^
+         *   ACPI_TABLE_PFX_SIZE     sizeof dfl_hdr      body_size
+         *                           == body_start
+         *
+         *                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+         *                           acpi_payload_size == bloblen
+         */
+        body_start = sizeof dfl_hdr;
+
+        if (bloblen < body_start) {
+            error_setg(errp, "ACPI table claiming to have header is too "
+                       "short, available: %zu, expected: %zu", bloblen,
+                       body_start);
+            return;
+        }
+        hdr_src = blob;
+    } else {
+        /*   _length             | ACPI header in template | blob body
+         *   ^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^
+         *   ACPI_TABLE_PFX_SIZE       sizeof dfl_hdr        body_size
+         *                                                   == bloblen
+         *
+         *                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+         *                                  acpi_payload_size
+         */
+        body_start = 0;
+        hdr_src = dfl_hdr;
+    }
+    body_size = bloblen - body_start;
+    acpi_payload_size = sizeof dfl_hdr + body_size;
+
+    if (acpi_payload_size > UINT16_MAX) {
+        error_setg(errp, "ACPI table too big, requested: %zu, max: %u",
+                   acpi_payload_size, (unsigned)UINT16_MAX);
+        return;
+    }
+
+    /* We won't fail from here on. Initialize / extend the globals. */
+    if (acpi_tables == NULL) {
+        acpi_tables_len = sizeof(uint16_t);
+        acpi_tables = g_malloc0(acpi_tables_len);
+    }
+
+    acpi_tables = g_realloc(acpi_tables, acpi_tables_len +
+                                         ACPI_TABLE_PFX_SIZE +
+                                         sizeof dfl_hdr + body_size);
+
+    ext_hdr = (struct acpi_table_header *)(acpi_tables + acpi_tables_len);
+    acpi_tables_len += ACPI_TABLE_PFX_SIZE;
+
+    memcpy(acpi_tables + acpi_tables_len, hdr_src, sizeof dfl_hdr);
+    acpi_tables_len += sizeof dfl_hdr;
+
+    if (blob != NULL) {
+        memcpy(acpi_tables + acpi_tables_len, blob + body_start, body_size);
+        acpi_tables_len += body_size;
+    }
+
+    /* increase number of tables */
+    cpu_to_le16wu((uint16_t *)acpi_tables,
+                  le16_to_cpupu((uint16_t *)acpi_tables) + 1u);
+
+    /* Update the header fields. The strings need not be NUL-terminated. */
+    changed_fields = 0;
+    ext_hdr->_length = cpu_to_le16(acpi_payload_size);
+
+    if (hdrs->has_sig) {
+        strncpy(ext_hdr->sig, hdrs->sig, sizeof ext_hdr->sig);
+        ++changed_fields;
+    }
+
+    if (has_header && le32_to_cpu(ext_hdr->length) != acpi_payload_size) {
+        fprintf(stderr,
+                "warning: ACPI table has wrong length, header says "
+                "%" PRIu32 ", actual size %zu bytes\n",
+                le32_to_cpu(ext_hdr->length), acpi_payload_size);
+    }
+    ext_hdr->length = cpu_to_le32(acpi_payload_size);
+
+    if (hdrs->has_rev) {
+        ext_hdr->revision = hdrs->rev;
+        ++changed_fields;
+    }
+
+    ext_hdr->checksum = 0;
+
+    if (hdrs->has_oem_id) {
+        strncpy(ext_hdr->oem_id, hdrs->oem_id, sizeof ext_hdr->oem_id);
+        ++changed_fields;
+    }
+    if (hdrs->has_oem_table_id) {
+        strncpy(ext_hdr->oem_table_id, hdrs->oem_table_id,
+                sizeof ext_hdr->oem_table_id);
+        ++changed_fields;
+    }
+    if (hdrs->has_oem_rev) {
+        ext_hdr->oem_revision = cpu_to_le32(hdrs->oem_rev);
+        ++changed_fields;
+    }
+    if (hdrs->has_asl_compiler_id) {
+        strncpy(ext_hdr->asl_compiler_id, hdrs->asl_compiler_id,
+                sizeof ext_hdr->asl_compiler_id);
+        ++changed_fields;
+    }
+    if (hdrs->has_asl_compiler_rev) {
+        ext_hdr->asl_compiler_revision = cpu_to_le32(hdrs->asl_compiler_rev);
+        ++changed_fields;
+    }
+
+    if (!has_header && changed_fields == 0) {
+        fprintf(stderr, "warning: ACPI table: no headers are specified\n");
+    }
+
+    /* recalculate checksum */
+    ext_hdr->checksum = acpi_checksum((const char unsigned *)ext_hdr +
+                                      ACPI_TABLE_PFX_SIZE, acpi_payload_size);
+}
+
 int acpi_table_add(const QemuOpts *opts)
 {
     AcpiTableOptions *hdrs = NULL;
     Error *err = NULL;
     char **pathnames = NULL;
     char **cur;
-
-    size_t len, start, allen;
-    bool has_header;
-    int changed;
-    int r;
-    struct acpi_table_header hdr;
-    char unsigned *table_start;
+    size_t bloblen = 0;
+    char unsigned *blob = NULL;
 
     {
         OptsVisitor *ov;
@@ -108,7 +253,6 @@ int acpi_table_add(const QemuOpts *opts)
         error_setg(&err, "'-acpitable' requires one of 'data' or 'file'");
         goto out;
     }
-    has_header = hdrs->has_file;
 
     pathnames = g_strsplit(hdrs->has_file ? hdrs->file : hdrs->data, ":", 0);
     if (pathnames == NULL || pathnames[0] == NULL) {
@@ -116,19 +260,7 @@ int acpi_table_add(const QemuOpts *opts)
         goto out;
     }
 
-    if (!acpi_tables) {
-        allen = sizeof(uint16_t);
-        acpi_tables = g_malloc0(allen);
-    } else {
-        allen = acpi_tables_len;
-    }
-
-    start = allen;
-    acpi_tables = g_realloc(acpi_tables, start + ACPI_TABLE_HDR_SIZE);
-    allen += has_header ? ACPI_TABLE_PFX_SIZE : ACPI_TABLE_HDR_SIZE;
-
     /* now read in the data files, reallocating buffer as needed */
-
     for (cur = pathnames; *cur; ++cur) {
         int fd = open(*cur, O_RDONLY | O_BINARY);
 
@@ -139,13 +271,15 @@ int acpi_table_add(const QemuOpts *opts)
 
         for (;;) {
             char unsigned data[8192];
-            r = read(fd, data, sizeof(data));
+            ssize_t r;
+
+            r = read(fd, data, sizeof data);
             if (r == 0) {
                 break;
             } else if (r > 0) {
-                acpi_tables = g_realloc(acpi_tables, allen + r);
-                memcpy(acpi_tables + allen, data, r);
-                allen += r;
+                blob = g_realloc(blob, bloblen + r);
+                memcpy(blob + bloblen, data, r);
+                bloblen += r;
             } else if (errno != EINTR) {
                 error_setg(&err, "can't read file %s: %s",
                            *cur, strerror(errno));
@@ -157,102 +291,10 @@ int acpi_table_add(const QemuOpts *opts)
         close(fd);
     }
 
-    /* now fill in the header fields */
-
-    table_start = acpi_tables + start;   /* start of the table */
-    changed = 0;
-
-    /* copy the header to temp place to align the fields */
-    memcpy(&hdr, has_header ? table_start : dfl_hdr, ACPI_TABLE_HDR_SIZE);
-
-    /* length of the table minus our prefix */
-    len = allen - start - ACPI_TABLE_PFX_SIZE;
-
-    hdr._length = cpu_to_le16(len);
-
-    if (hdrs->has_sig) {
-        /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.sig, hdrs->sig, sizeof(hdr.sig));
-        ++changed;
-    }
-
-    /* length of the table including header, in bytes */
-    if (has_header) {
-        unsigned long val;
-
-        /* check if actual length is correct */
-        val = le32_to_cpu(hdr.length);
-        if (val != len) {
-            fprintf(stderr,
-                "warning: acpitable has wrong length,"
-                " header says %lu, actual size %zu bytes\n",
-                val, len);
-            ++changed;
-        }
-    }
-    /* we may avoid putting length here if has_header is true */
-    hdr.length = cpu_to_le32(len);
-
-    if (hdrs->has_rev) {
-        hdr.revision = hdrs->rev;
-        ++changed;
-    }
-
-    if (hdrs->has_oem_id) {
-        /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.oem_id, hdrs->oem_id, sizeof(hdr.oem_id));
-        ++changed;
-    }
-
-    if (hdrs->has_oem_table_id) {
-        /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.oem_table_id, hdrs->oem_table_id,
-                sizeof(hdr.oem_table_id));
-        ++changed;
-    }
-
-    if (hdrs->has_oem_rev) {
-        hdr.oem_revision = cpu_to_le32(hdrs->oem_rev);
-        ++changed;
-    }
-
-    if (hdrs->has_asl_compiler_id) {
-        /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.asl_compiler_id, hdrs->asl_compiler_id,
-                sizeof(hdr.asl_compiler_id));
-        ++changed;
-    }
-
-    if (hdrs->has_asl_compiler_rev) {
-        hdr.asl_compiler_revision = cpu_to_le32(hdrs->asl_compiler_rev);
-        ++changed;
-    }
-
-    if (!has_header && !changed) {
-        fprintf(stderr, "warning: acpitable: no table headers are specified\n");
-    }
-
-
-    /* now calculate checksum of the table, complete with the header */
-    /* we may as well leave checksum intact if has_header is true */
-    /* alternatively there may be a way to set cksum to a given value */
-    hdr.checksum = 0;    /* for checksum calculation */
-
-    /* put header back */
-    memcpy(table_start, &hdr, sizeof(hdr));
-
-    if (changed || !has_header || 1) {
-        ((struct acpi_table_header *)table_start)->checksum =
-            acpi_checksum((uint8_t *)table_start + ACPI_TABLE_PFX_SIZE, len);
-    }
-
-    /* increase number of tables */
-    (*(uint16_t *)acpi_tables) =
-        cpu_to_le32(le32_to_cpu(*(uint16_t *)acpi_tables) + 1);
-
-    acpi_tables_len = allen;
+    acpi_table_install(blob, bloblen, hdrs->has_file, hdrs, &err);
 
 out:
+    g_free(blob);
     g_strfreev(pathnames);
 
     if (hdrs != NULL) {
commit 0c764a9dfc0d480c21f325480aa2e69581841858
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:17 2013 +0100

    acpi_table_add(): accept QemuOpts and parse it with OptsVisitor
    
    As one consequence, strtok() -- which modifies its argument -- is replaced
    with g_strsplit().
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-6-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index 2ed12fa..0373a58 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -1103,10 +1103,10 @@ int qemu_uuid_parse(const char *str, uint8_t *uuid)
     return 0;
 }
 
-void do_acpitable_option(const char *optarg)
+void do_acpitable_option(const QemuOpts *opts)
 {
 #ifdef TARGET_I386
-    if (acpi_table_add(optarg) < 0) {
+    if (acpi_table_add(opts) < 0) {
         fprintf(stderr, "Wrong acpi table provided\n");
         exit(1);
     }
diff --git a/hw/acpi.c b/hw/acpi.c
index 1d1916b..1aca458 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -23,6 +23,10 @@
 #include "hw/pc.h"
 #include "hw/acpi.h"
 #include "monitor/monitor.h"
+#include "qemu/config-file.h"
+#include "qapi/opts-visitor.h"
+#include "qapi/dealloc-visitor.h"
+#include "qapi-visit.h"
 
 struct acpi_table_header {
     uint16_t _length;         /* our length, not actual part of the hdr */
@@ -51,6 +55,20 @@ static const char unsigned dfl_hdr[ACPI_TABLE_HDR_SIZE] =
 char unsigned *acpi_tables;
 size_t acpi_tables_len;
 
+static QemuOptsList qemu_acpi_opts = {
+    .name = "acpi",
+    .implied_opt_name = "data",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_acpi_opts.head),
+    .desc = { { 0 } } /* validated with OptsVisitor */
+};
+
+static void acpi_register_config(void)
+{
+    qemu_add_opts(&qemu_acpi_opts);
+}
+
+machine_init(acpi_register_config);
+
 static int acpi_checksum(const uint8_t *data, int len)
 {
     int sum, i;
@@ -61,12 +79,13 @@ static int acpi_checksum(const uint8_t *data, int len)
     return (-sum) & 0xff;
 }
 
-/* XXX fixme: this function uses obsolete argument parsing interface */
-int acpi_table_add(const char *t)
+int acpi_table_add(const QemuOpts *opts)
 {
+    AcpiTableOptions *hdrs = NULL;
     Error *err = NULL;
-    char buf[1024], *p, *f;
-    unsigned long val;
+    char **pathnames = NULL;
+    char **cur;
+
     size_t len, start, allen;
     bool has_header;
     int changed;
@@ -74,21 +93,26 @@ int acpi_table_add(const char *t)
     struct acpi_table_header hdr;
     char unsigned *table_start;
 
-    r = 0;
-    r |= get_param_value(buf, sizeof(buf), "data", t) ? 1 : 0;
-    r |= get_param_value(buf, sizeof(buf), "file", t) ? 2 : 0;
-    switch (r) {
-    case 0:
-        buf[0] = '\0';
-        /* fallthrough for default behavior */
-    case 1:
-        has_header = false;
-        break;
-    case 2:
-        has_header = true;
-        break;
-    default:
-        error_setg(&err, "acpitable: both data and file are specified");
+    {
+        OptsVisitor *ov;
+
+        ov = opts_visitor_new(opts);
+        visit_type_AcpiTableOptions(opts_get_visitor(ov), &hdrs, NULL, &err);
+        opts_visitor_cleanup(ov);
+    }
+
+    if (err) {
+        goto out;
+    }
+    if (hdrs->has_file == hdrs->has_data) {
+        error_setg(&err, "'-acpitable' requires one of 'data' or 'file'");
+        goto out;
+    }
+    has_header = hdrs->has_file;
+
+    pathnames = g_strsplit(hdrs->has_file ? hdrs->file : hdrs->data, ":", 0);
+    if (pathnames == NULL || pathnames[0] == NULL) {
+        error_setg(&err, "'-acpitable' requires at least one pathname");
         goto out;
     }
 
@@ -105,11 +129,11 @@ 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 | O_BINARY);
+    for (cur = pathnames; *cur; ++cur) {
+        int fd = open(*cur, O_RDONLY | O_BINARY);
 
         if (fd < 0) {
-            error_setg(&err, "can't open file %s: %s", f, strerror(errno));
+            error_setg(&err, "can't open file %s: %s", *cur, strerror(errno));
             goto out;
         }
 
@@ -124,7 +148,7 @@ int acpi_table_add(const char *t)
                 allen += r;
             } else if (errno != EINTR) {
                 error_setg(&err, "can't read file %s: %s",
-                           f, strerror(errno));
+                           *cur, strerror(errno));
                 close(fd);
                 goto out;
             }
@@ -146,14 +170,16 @@ int acpi_table_add(const char *t)
 
     hdr._length = cpu_to_le16(len);
 
-    if (get_param_value(buf, sizeof(buf), "sig", t)) {
+    if (hdrs->has_sig) {
         /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.sig, buf, sizeof(hdr.sig));
+        strncpy(hdr.sig, hdrs->sig, sizeof(hdr.sig));
         ++changed;
     }
 
     /* length of the table including header, in bytes */
     if (has_header) {
+        unsigned long val;
+
         /* check if actual length is correct */
         val = le32_to_cpu(hdr.length);
         if (val != len) {
@@ -167,52 +193,38 @@ int acpi_table_add(const char *t)
     /* we may avoid putting length here if has_header is true */
     hdr.length = cpu_to_le32(len);
 
-    if (get_param_value(buf, sizeof(buf), "rev", t)) {
-        val = strtoul(buf, &p, 0);
-        if (val > 255 || *p) {
-            error_setg(&err, "acpitable: \"rev=%s\" is invalid", buf);
-            goto out;
-        }
-        hdr.revision = (uint8_t)val;
+    if (hdrs->has_rev) {
+        hdr.revision = hdrs->rev;
         ++changed;
     }
 
-    if (get_param_value(buf, sizeof(buf), "oem_id", t)) {
+    if (hdrs->has_oem_id) {
         /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.oem_id, buf, sizeof(hdr.oem_id));
+        strncpy(hdr.oem_id, hdrs->oem_id, sizeof(hdr.oem_id));
         ++changed;
     }
 
-    if (get_param_value(buf, sizeof(buf), "oem_table_id", t)) {
+    if (hdrs->has_oem_table_id) {
         /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.oem_table_id, buf, sizeof(hdr.oem_table_id));
+        strncpy(hdr.oem_table_id, hdrs->oem_table_id,
+                sizeof(hdr.oem_table_id));
         ++changed;
     }
 
-    if (get_param_value(buf, sizeof(buf), "oem_rev", t)) {
-        val = strtol(buf, &p, 0);
-        if (*p) {
-            error_setg(&err, "acpitable: \"oem_rev=%s\" is invalid", buf);
-            goto out;
-        }
-        hdr.oem_revision = cpu_to_le32(val);
+    if (hdrs->has_oem_rev) {
+        hdr.oem_revision = cpu_to_le32(hdrs->oem_rev);
         ++changed;
     }
 
-    if (get_param_value(buf, sizeof(buf), "asl_compiler_id", t)) {
+    if (hdrs->has_asl_compiler_id) {
         /* strncpy is justified: the field need not be NUL-terminated. */
-        strncpy(hdr.asl_compiler_id, buf, sizeof(hdr.asl_compiler_id));
+        strncpy(hdr.asl_compiler_id, hdrs->asl_compiler_id,
+                sizeof(hdr.asl_compiler_id));
         ++changed;
     }
 
-    if (get_param_value(buf, sizeof(buf), "asl_compiler_rev", t)) {
-        val = strtol(buf, &p, 0);
-        if (*p) {
-            error_setg(&err, "acpitable: \"%s=%s\" is invalid",
-                       "asl_compiler_rev", buf);
-            goto out;
-        }
-        hdr.asl_compiler_revision = cpu_to_le32(val);
+    if (hdrs->has_asl_compiler_rev) {
+        hdr.asl_compiler_revision = cpu_to_le32(hdrs->asl_compiler_rev);
         ++changed;
     }
 
@@ -239,12 +251,25 @@ int acpi_table_add(const char *t)
         cpu_to_le32(le32_to_cpu(*(uint16_t *)acpi_tables) + 1);
 
     acpi_tables_len = allen;
-    return 0;
 
 out:
-    fprintf(stderr, "%s\n", error_get_pretty(err));
-    error_free(err);
-    return -1;
+    g_strfreev(pathnames);
+
+    if (hdrs != NULL) {
+        QapiDeallocVisitor *dv;
+
+        dv = qapi_dealloc_visitor_new();
+        visit_type_AcpiTableOptions(qapi_dealloc_get_visitor(dv), &hdrs, NULL,
+                                    NULL);
+        qapi_dealloc_visitor_cleanup(dv);
+    }
+
+    if (err) {
+        fprintf(stderr, "%s\n", error_get_pretty(err));
+        error_free(err);
+        return -1;
+    }
+    return 0;
 }
 
 static void acpi_notify_wakeup(Notifier *notifier, void *data)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index b1e06fa..d1bc0de 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -51,6 +51,7 @@
 #include "exec/address-spaces.h"
 #include "sysemu/arch_init.h"
 #include "qemu/bitmap.h"
+#include "qemu/config-file.h"
 
 /* debug PC/ISA interrupts */
 //#define DEBUG_IRQ
@@ -889,6 +890,7 @@ void pc_cpus_init(const char *cpu_model)
 void pc_acpi_init(const char *default_dsdt)
 {
     char *filename = NULL, *arg = NULL;
+    QemuOpts *opts;
 
     if (acpi_tables != NULL) {
         /* manually set via -acpitable, leave it alone */
@@ -902,7 +904,12 @@ void pc_acpi_init(const char *default_dsdt)
     }
 
     arg = g_strdup_printf("file=%s", filename);
-    if (acpi_table_add(arg) != 0) {
+
+    /* creates a deep copy of "arg" */
+    opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0);
+    g_assert(opts != NULL);
+
+    if (acpi_table_add(opts) != 0) {
         fprintf(stderr, "WARNING: failed to load %s\n", filename);
     }
     g_free(arg);
diff --git a/hw/pc.h b/hw/pc.h
index c967e9f..613520d 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -113,7 +113,7 @@ extern char unsigned *acpi_tables;
 extern size_t acpi_tables_len;
 
 void acpi_bios_init(void);
-int acpi_table_add(const char *table_desc);
+int acpi_table_add(const QemuOpts *opts);
 
 /* acpi_piix.c */
 
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 8c8d78e..aed3d1d 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -2,6 +2,7 @@
 #define QEMU_ARCH_INIT_H
 
 #include "qmp-commands.h"
+#include "qemu/option.h"
 
 enum {
     QEMU_ARCH_ALL = -1,
@@ -26,7 +27,7 @@ enum {
 extern const uint32_t arch_type;
 
 void select_soundhw(const char *optarg);
-void do_acpitable_option(const char *optarg);
+void do_acpitable_option(const QemuOpts *opts);
 void do_smbios_option(const char *optarg);
 void cpudef_init(void);
 int audio_available(void);
diff --git a/vl.c b/vl.c
index 0ac9c00..a8bba04 100644
--- a/vl.c
+++ b/vl.c
@@ -3587,7 +3587,9 @@ int main(int argc, char **argv, char **envp)
                 break;
             }
             case QEMU_OPTION_acpitable:
-                do_acpitable_option(optarg);
+                opts = qemu_opts_parse(qemu_find_opts("acpi"), optarg, 1);
+                g_assert(opts != NULL);
+                do_acpitable_option(opts);
                 break;
             case QEMU_OPTION_smbios:
                 do_smbios_option(optarg);
commit 8ccbad5c7b61c46c1b69b8089b8965cd69c0a8de
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:16 2013 +0100

    qapi schema: add AcpiTableOptions
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-5-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index bfd7a8a..db542f6 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3455,3 +3455,61 @@
 # Since: 1.5
 ##
 { 'command': 'query-tpm', 'returns': ['TPMInfo'] }
+
+##
+# @AcpiTableOptions
+#
+# Specify an ACPI table on the command line to load.
+#
+# At most one of @file and @data can be specified. The list of files specified
+# by any one of them is loaded and concatenated in order. If both are omitted,
+# @data is implied.
+#
+# Other fields / optargs can be used to override fields of the generic ACPI
+# table header; refer to the ACPI specification 5.0, section 5.2.6 System
+# Description Table Header. If a header field is not overridden, then the
+# corresponding value from the concatenated blob is used (in case of @file), or
+# it is filled in with a hard-coded value (in case of @data).
+#
+# String fields are copied into the matching ACPI member from lowest address
+# upwards, and silently truncated / NUL-padded to length.
+#
+# @sig: #optional table signature / identifier (4 bytes)
+#
+# @rev: #optional table revision number (dependent on signature, 1 byte)
+#
+# @oem_id: #optional OEM identifier (6 bytes)
+#
+# @oem_table_id: #optional OEM table identifier (8 bytes)
+#
+# @oem_rev: #optional OEM-supplied revision number (4 bytes)
+#
+# @asl_compiler_id: #optional identifier of the utility that created the table
+#                   (4 bytes)
+#
+# @asl_compiler_rev: #optional revision number of the utility that created the
+#                    table (4 bytes)
+#
+# @file: #optional colon (:) separated list of pathnames to load and
+#        concatenate as table data. The resultant binary blob is expected to
+#        have an ACPI table header. At least one file is required. This field
+#        excludes @data.
+#
+# @data: #optional colon (:) separated list of pathnames to load and
+#        concatenate as table data. The resultant binary blob must not have an
+#        ACPI table header. At least one file is required. This field excludes
+#        @file.
+#
+# Since 1.5
+##
+{ 'type': 'AcpiTableOptions',
+  'data': {
+    '*sig':               'str',
+    '*rev':               'uint8',
+    '*oem_id':            'str',
+    '*oem_table_id':      'str',
+    '*oem_rev':           'uint32',
+    '*asl_compiler_id':   'str',
+    '*asl_compiler_rev':  'uint32',
+    '*file':              'str',
+    '*data':              'str' }}
commit 445d9cae371960671c1d762330d0d498c352dd3c
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:15 2013 +0100

    acpi_table_add(): report fatal errors through an internal Error object
    
    The upcoming changes will need a cleanup section at the end of the
    function, plus OptsVisitor reports errors via Error. For now keep
    channeling any Errors to stderr.
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-4-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi.c b/hw/acpi.c
index d9cf4da..1d1916b 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -64,6 +64,7 @@ static int acpi_checksum(const uint8_t *data, int len)
 /* XXX fixme: this function uses obsolete argument parsing interface */
 int acpi_table_add(const char *t)
 {
+    Error *err = NULL;
     char buf[1024], *p, *f;
     unsigned long val;
     size_t len, start, allen;
@@ -87,8 +88,8 @@ int acpi_table_add(const char *t)
         has_header = true;
         break;
     default:
-        fprintf(stderr, "acpitable: both data and file are specified\n");
-        return -1;
+        error_setg(&err, "acpitable: both data and file are specified");
+        goto out;
     }
 
     if (!acpi_tables) {
@@ -108,8 +109,8 @@ int acpi_table_add(const char *t)
         int fd = open(f, O_RDONLY | O_BINARY);
 
         if (fd < 0) {
-            fprintf(stderr, "can't open file %s: %s\n", f, strerror(errno));
-            return -1;
+            error_setg(&err, "can't open file %s: %s", f, strerror(errno));
+            goto out;
         }
 
         for (;;) {
@@ -122,10 +123,10 @@ int acpi_table_add(const char *t)
                 memcpy(acpi_tables + allen, data, r);
                 allen += r;
             } else if (errno != EINTR) {
-                fprintf(stderr, "can't read file %s: %s\n",
-                        f, strerror(errno));
+                error_setg(&err, "can't read file %s: %s",
+                           f, strerror(errno));
                 close(fd);
-                return -1;
+                goto out;
             }
         }
 
@@ -169,8 +170,8 @@ int acpi_table_add(const char *t)
     if (get_param_value(buf, sizeof(buf), "rev", t)) {
         val = strtoul(buf, &p, 0);
         if (val > 255 || *p) {
-            fprintf(stderr, "acpitable: \"rev=%s\" is invalid\n", buf);
-            return -1;
+            error_setg(&err, "acpitable: \"rev=%s\" is invalid", buf);
+            goto out;
         }
         hdr.revision = (uint8_t)val;
         ++changed;
@@ -191,8 +192,8 @@ int acpi_table_add(const char *t)
     if (get_param_value(buf, sizeof(buf), "oem_rev", t)) {
         val = strtol(buf, &p, 0);
         if (*p) {
-            fprintf(stderr, "acpitable: \"oem_rev=%s\" is invalid\n", buf);
-            return -1;
+            error_setg(&err, "acpitable: \"oem_rev=%s\" is invalid", buf);
+            goto out;
         }
         hdr.oem_revision = cpu_to_le32(val);
         ++changed;
@@ -207,9 +208,9 @@ int acpi_table_add(const char *t)
     if (get_param_value(buf, sizeof(buf), "asl_compiler_rev", t)) {
         val = strtol(buf, &p, 0);
         if (*p) {
-            fprintf(stderr, "acpitable: \"%s=%s\" is invalid\n",
-                    "asl_compiler_rev", buf);
-            return -1;
+            error_setg(&err, "acpitable: \"%s=%s\" is invalid",
+                       "asl_compiler_rev", buf);
+            goto out;
         }
         hdr.asl_compiler_revision = cpu_to_le32(val);
         ++changed;
@@ -240,6 +241,10 @@ int acpi_table_add(const char *t)
     acpi_tables_len = allen;
     return 0;
 
+out:
+    fprintf(stderr, "%s\n", error_get_pretty(err));
+    error_free(err);
+    return -1;
 }
 
 static void acpi_notify_wakeup(Notifier *notifier, void *data)
commit cb88a4ea79193cdbfb9b27bf9deb36c88ec9b6dc
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:14 2013 +0100

    change element type from "char" to "unsigned char" in ACPI table data
    
    The data is binary, not textual.
    
    Also, acpi_table_add() abuses the "char *f" pointer -- which normally
    points to file names to load -- to poke into the table. Introduce "char
    unsigned *table_start" for that purpose.
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-3-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi.c b/hw/acpi.c
index e9b73cf..d9cf4da 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -41,14 +41,14 @@ struct acpi_table_header {
 #define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header)
 #define ACPI_TABLE_PFX_SIZE sizeof(uint16_t)  /* size of the extra prefix */
 
-static const char dfl_hdr[ACPI_TABLE_HDR_SIZE] =
+static const char unsigned dfl_hdr[ACPI_TABLE_HDR_SIZE] =
     "\0\0"                   /* fake _length (2) */
     "QEMU\0\0\0\0\1\0"       /* sig (4), len(4), revno (1), csum (1) */
     "QEMUQEQEMUQEMU\1\0\0\0" /* OEM id (6), table (8), revno (4) */
     "QEMU\1\0\0\0"           /* ASL compiler ID (4), version (4) */
     ;
 
-char *acpi_tables;
+char unsigned *acpi_tables;
 size_t acpi_tables_len;
 
 static int acpi_checksum(const uint8_t *data, int len)
@@ -71,6 +71,7 @@ int acpi_table_add(const char *t)
     int changed;
     int r;
     struct acpi_table_header hdr;
+    char unsigned *table_start;
 
     r = 0;
     r |= get_param_value(buf, sizeof(buf), "data", t) ? 1 : 0;
@@ -112,7 +113,7 @@ int acpi_table_add(const char *t)
         }
 
         for (;;) {
-            char data[8192];
+            char unsigned data[8192];
             r = read(fd, data, sizeof(data));
             if (r == 0) {
                 break;
@@ -133,11 +134,11 @@ int acpi_table_add(const char *t)
 
     /* now fill in the header fields */
 
-    f = acpi_tables + start;   /* start of the table */
+    table_start = acpi_tables + start;   /* start of the table */
     changed = 0;
 
     /* copy the header to temp place to align the fields */
-    memcpy(&hdr, has_header ? f : dfl_hdr, ACPI_TABLE_HDR_SIZE);
+    memcpy(&hdr, has_header ? table_start : dfl_hdr, ACPI_TABLE_HDR_SIZE);
 
     /* length of the table minus our prefix */
     len = allen - start - ACPI_TABLE_PFX_SIZE;
@@ -225,11 +226,11 @@ int acpi_table_add(const char *t)
     hdr.checksum = 0;    /* for checksum calculation */
 
     /* put header back */
-    memcpy(f, &hdr, sizeof(hdr));
+    memcpy(table_start, &hdr, sizeof(hdr));
 
     if (changed || !has_header || 1) {
-        ((struct acpi_table_header *)f)->checksum =
-            acpi_checksum((uint8_t *)f + ACPI_TABLE_PFX_SIZE, len);
+        ((struct acpi_table_header *)table_start)->checksum =
+            acpi_checksum((uint8_t *)table_start + ACPI_TABLE_PFX_SIZE, len);
     }
 
     /* increase number of tables */
diff --git a/hw/pc.h b/hw/pc.h
index 8e1dd4c..c967e9f 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -109,7 +109,7 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name);
 
 /* acpi.c */
 extern int acpi_enabled;
-extern char *acpi_tables;
+extern char unsigned *acpi_tables;
 extern size_t acpi_tables_len;
 
 void acpi_bios_init(void);
commit 4d8b3c6302fe50e9192854d8affda883e078fd4d
Author: Laszlo Ersek <lersek at redhat.com>
Date:   Thu Mar 21 00:23:13 2013 +0100

    strip some whitespace
    
    Signed-off-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1363821803-3380-2-git-send-email-lersek at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/arch_init.c b/arch_init.c
index 4ef5a15..2ed12fa 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -142,7 +142,7 @@ int qemu_read_default_config_files(bool userconfig)
             return ret;
         }
     }
-    
+
     return 0;
 }
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 48f41ca..5284ebc 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -185,7 +185,7 @@
 #define HF2_VINTR_SHIFT      3 /* value of V_INTR_MASKING bit */
 
 #define HF2_GIF_MASK          (1 << HF2_GIF_SHIFT)
-#define HF2_HIF_MASK          (1 << HF2_HIF_SHIFT) 
+#define HF2_HIF_MASK          (1 << HF2_HIF_SHIFT)
 #define HF2_NMI_MASK          (1 << HF2_NMI_SHIFT)
 #define HF2_VINTR_MASK        (1 << HF2_VINTR_SHIFT)
 
diff --git a/vl.c b/vl.c
index 33f30b6..0ac9c00 100644
--- a/vl.c
+++ b/vl.c
@@ -2546,7 +2546,7 @@ static int virtcon_parse(const char *devname)
         qemu_opt_set(bus_opts, "driver", "virtio-serial-s390");
     } else {
         qemu_opt_set(bus_opts, "driver", "virtio-serial-pci");
-    } 
+    }
 
     dev_opts = qemu_opts_create_nofail(device);
     qemu_opt_set(dev_opts, "driver", "virtconsole");
@@ -2598,7 +2598,7 @@ static int sclp_parse(const char *devname)
 }
 
 static int debugcon_parse(const char *devname)
-{   
+{
     QemuOpts *opts;
 
     if (!qemu_chr_new("debugcon", devname, NULL)) {
@@ -3735,8 +3735,8 @@ int main(int argc, char **argv, char **envp)
 			}
 			p += 8;
 			os_set_proc_name(p);
-		     }	
-		 }	
+		     }
+		 }
                 break;
             case QEMU_OPTION_prom_env:
                 if (nb_prom_envs >= MAX_PROM_ENVS) {
commit b9936159ff601562a7bb16b5b9c7713e6cec9559
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 27 20:29:41 2013 +0100

    ipoctal232: Convert to use chardev properties directly
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Alberto Garcia <agarcia at igalia.com>
    Message-id: 1364412581-3672-4-git-send-email-hdegoede at redhat.com
    Cc: Alberto Garcia <agarcia at igalia.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ipoctal232.c b/hw/ipoctal232.c
index 345efae..685fee2 100644
--- a/hw/ipoctal232.c
+++ b/hw/ipoctal232.c
@@ -93,7 +93,6 @@ typedef struct SCC2698Block SCC2698Block;
 struct SCC2698Channel {
     IPOctalState *ipoctal;
     CharDriverState *dev;
-    char *devpath;
     bool rx_enabled;
     uint8_t mr[2];
     uint8_t mr_idx;
@@ -545,26 +544,12 @@ static int ipoctal_init(IPackDevice *ip)
         ch->ipoctal = s;
 
         /* Redirect IP-Octal channels to host character devices */
-        if (ch->devpath) {
-            const char chr_name[] = "ipoctal";
-            char label[ARRAY_SIZE(chr_name) + 2];
-            static int index;
-
-            snprintf(label, sizeof(label), "%s%d", chr_name, index);
-
-            ch->dev = qemu_chr_new(label, ch->devpath, NULL);
-
-            if (ch->dev) {
-                index++;
-                qemu_chr_fe_claim_no_fail(ch->dev);
-                qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
-                                      hostdev_receive, hostdev_event, ch);
-                DPRINTF("Redirecting channel %u to %s (%s)\n",
-                        i, ch->devpath, label);
-            } else {
-                DPRINTF("Could not redirect channel %u to %s\n",
-                        i, ch->devpath);
-            }
+        if (ch->dev) {
+            qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
+                                  hostdev_receive, hostdev_event, ch);
+            DPRINTF("Redirecting channel %u to %s\n", i, ch->dev->label);
+        } else {
+            DPRINTF("Could not redirect channel %u, no chardev set\n", i);
         }
     }
 
@@ -572,14 +557,14 @@ static int ipoctal_init(IPackDevice *ip)
 }
 
 static Property ipoctal_properties[] = {
-    DEFINE_PROP_STRING("serial0", IPOctalState, ch[0].devpath),
-    DEFINE_PROP_STRING("serial1", IPOctalState, ch[1].devpath),
-    DEFINE_PROP_STRING("serial2", IPOctalState, ch[2].devpath),
-    DEFINE_PROP_STRING("serial3", IPOctalState, ch[3].devpath),
-    DEFINE_PROP_STRING("serial4", IPOctalState, ch[4].devpath),
-    DEFINE_PROP_STRING("serial5", IPOctalState, ch[5].devpath),
-    DEFINE_PROP_STRING("serial6", IPOctalState, ch[6].devpath),
-    DEFINE_PROP_STRING("serial7", IPOctalState, ch[7].devpath),
+    DEFINE_PROP_CHR("chardev0", IPOctalState, ch[0].dev),
+    DEFINE_PROP_CHR("chardev1", IPOctalState, ch[1].dev),
+    DEFINE_PROP_CHR("chardev2", IPOctalState, ch[2].dev),
+    DEFINE_PROP_CHR("chardev3", IPOctalState, ch[3].dev),
+    DEFINE_PROP_CHR("chardev4", IPOctalState, ch[4].dev),
+    DEFINE_PROP_CHR("chardev5", IPOctalState, ch[5].dev),
+    DEFINE_PROP_CHR("chardev6", IPOctalState, ch[6].dev),
+    DEFINE_PROP_CHR("chardev7", IPOctalState, ch[7].dev),
     DEFINE_PROP_END_OF_LIST(),
 };
 
commit 456d60692310e7ac25cf822cc1e98192ad636ece
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 27 20:29:40 2013 +0100

    qemu-char: Call fe_claim / fe_release when not using qdev chr properties
    
    chardev-frontends need to explictly check, increase and decrement the
    avail_connections "property" of the chardev when they are not using a
    qdev-chardev-property for the chardev.
    
    This fixes things like:
    qemu-kvm -chardev stdio,id=foo -device isa-serial,chardev=foo \
      -mon chardev=foo
    
    Working, where they should fail. Most of the changes here are due to
    old hardware emulation code which is using serial_hds directly rather then
    a qdev-chardev-property.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364412581-3672-3-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/backends/rng-egd.c b/backends/rng-egd.c
index 5e012e9..cc6f5ee 100644
--- a/backends/rng-egd.c
+++ b/backends/rng-egd.c
@@ -149,6 +149,11 @@ static void rng_egd_opened(RngBackend *b, Error **errp)
         return;
     }
 
+    if (qemu_chr_fe_claim(s->chr) != 0) {
+        error_set(errp, QERR_DEVICE_IN_USE, s->chr_name);
+        return;
+    }
+
     /* FIXME we should resubmit pending requests when the CDS reconnects. */
     qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read,
                           NULL, s);
@@ -191,6 +196,7 @@ static void rng_egd_finalize(Object *obj)
 
     if (s->chr) {
         qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
+        qemu_chr_fe_release(s->chr);
     }
 
     g_free(s->chr_name);
diff --git a/gdbstub.c b/gdbstub.c
index a666cb5..a0288a7 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -3025,6 +3025,7 @@ int gdbserver_start(const char *device)
         if (!chr)
             return -1;
 
+        qemu_chr_fe_claim_no_fail(chr);
         qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
                               gdb_chr_event, NULL);
     }
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 7467cca..b7ca511 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -1981,9 +1981,11 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
     memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
-    if (chr)
+    if (chr) {
+        qemu_chr_fe_claim_no_fail(chr);
         qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
                         pxa2xx_fir_rx, pxa2xx_fir_event, s);
+    }
 
     register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
                     pxa2xx_fir_load, s);
diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c
index e4ada3c..55c819b 100644
--- a/hw/bt-hci-csr.c
+++ b/hw/bt-hci-csr.c
@@ -439,6 +439,7 @@ CharDriverState *uart_hci_init(qemu_irq wakeup)
     s->chr.opaque = s;
     s->chr.chr_write = csrhci_write;
     s->chr.chr_ioctl = csrhci_ioctl;
+    s->chr.avail_connections = 1;
 
     s->hci = qemu_next_hci();
     s->hci->opaque = s;
diff --git a/hw/ipoctal232.c b/hw/ipoctal232.c
index 1da6a99..345efae 100644
--- a/hw/ipoctal232.c
+++ b/hw/ipoctal232.c
@@ -556,6 +556,7 @@ static int ipoctal_init(IPackDevice *ip)
 
             if (ch->dev) {
                 index++;
+                qemu_chr_fe_claim_no_fail(ch->dev);
                 qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
                                       hostdev_receive, hostdev_event, ch);
                 DPRINTF("Redirecting channel %u to %s (%s)\n",
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index 68a2cf2..af2789e 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -292,6 +292,7 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *
         fprintf(stderr, "creating eventfd for eventfd %d failed\n", eventfd);
         exit(-1);
     }
+    qemu_chr_fe_claim_no_fail(chr);
 
     /* if MSI is supported we need multiple interrupts */
     if (ivshmem_has_feature(s, IVSHMEM_MSI)) {
diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c
index aacf0f0..e5de801 100644
--- a/hw/mcf_uart.c
+++ b/hw/mcf_uart.c
@@ -280,6 +280,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
     s->chr = chr;
     s->irq = irq;
     if (chr) {
+        qemu_chr_fe_claim_no_fail(chr);
         qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
                               mcf_uart_event, s);
     }
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index 40e797c..4629695 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -396,9 +396,11 @@ void sh_serial_init(MemoryRegion *sysmem,
 
     s->chr = chr;
 
-    if (chr)
+    if (chr) {
+        qemu_chr_fe_claim_no_fail(chr);
         qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
 			      sh_serial_event, s);
+    }
 
     s->eri = eri_source;
     s->rxi = rxi_source;
diff --git a/hw/xen_console.c b/hw/xen_console.c
index a8db6f8..c56ef47 100644
--- a/hw/xen_console.c
+++ b/hw/xen_console.c
@@ -241,9 +241,17 @@ static int con_initialise(struct XenDevice *xendev)
 	return -1;
 
     xen_be_bind_evtchn(&con->xendev);
-    if (con->chr)
-        qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive,
-                              NULL, con);
+    if (con->chr) {
+        if (qemu_chr_fe_claim(con->chr) == 0) {
+            qemu_chr_add_handlers(con->chr, xencons_can_receive,
+                                  xencons_receive, NULL, con);
+        } else {
+            xen_be_printf(xendev, 0,
+                          "xen_console_init error chardev %s already used\n",
+                          con->chr->label);
+            con->chr = NULL;
+        }
+    }
 
     xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
 		  con->ring_ref,
@@ -260,8 +268,10 @@ static void con_disconnect(struct XenDevice *xendev)
     if (!xendev->dev) {
         return;
     }
-    if (con->chr)
+    if (con->chr) {
         qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
+        qemu_chr_fe_release(con->chr);
+    }
     xen_be_unbind_evtchn(&con->xendev);
 
     if (con->sring) {
diff --git a/net/slirp.c b/net/slirp.c
index 4df550f..eabfee6 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -660,6 +660,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
         fwd->port = port;
         fwd->slirp = s->slirp;
 
+        qemu_chr_fe_claim_no_fail(fwd->hd);
         qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
                               NULL, fwd);
     }
diff --git a/qemu-char.c b/qemu-char.c
index 100f9a9..e5eb8dd 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3411,6 +3411,7 @@ CharDriverState *qemu_chr_new(const char *label, const char *filename, void (*in
         error_free(err);
     }
     if (chr && qemu_opt_get_bool(opts, "mux", 0)) {
+        qemu_chr_fe_claim_no_fail(chr);
         monitor_init(chr, MONITOR_USE_READLINE);
     }
     return chr;
@@ -3523,9 +3524,16 @@ CharDriverState *qemu_chr_find(const char *name)
 CharDriverState *qemu_char_get_next_serial(void)
 {
     static int next_serial;
+    CharDriverState *chr;
 
     /* FIXME: This function needs to go away: use chardev properties!  */
-    return serial_hds[next_serial++];
+
+    while (next_serial < MAX_SERIAL_PORTS && serial_hds[next_serial]) {
+        chr = serial_hds[next_serial++];
+        qemu_chr_fe_claim_no_fail(chr);
+        return chr;
+    }
+    return NULL;
 }
 
 QemuOptsList qemu_chardev_opts = {
diff --git a/vl.c b/vl.c
index e2c9706..33f30b6 100644
--- a/vl.c
+++ b/vl.c
@@ -2396,6 +2396,7 @@ static int mon_init_func(QemuOpts *opts, void *opaque)
         exit(1);
     }
 
+    qemu_chr_fe_claim_no_fail(chr);
     monitor_init(chr, flags);
     return 0;
 }
commit 44c473decd4de5559487430f876de53c607b1e9d
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 27 20:29:39 2013 +0100

    qemu-char: Add qemu_chr_fe_claim / _release helper functions
    
    Add qemu_chr_fe_claim / _release helper functions for properly dealing with
    avail_connections.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364412581-3672-2-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c
index d9934b5..a22b155 100644
--- a/hw/qdev-properties-system.c
+++ b/hw/qdev-properties-system.c
@@ -123,11 +123,10 @@ static int parse_chr(DeviceState *dev, const char *str, void **ptr)
     if (chr == NULL) {
         return -ENOENT;
     }
-    if (chr->avail_connections < 1) {
+    if (qemu_chr_fe_claim(chr) != 0) {
         return -EEXIST;
     }
     *ptr = chr;
-    --chr->avail_connections;
     return 0;
 }
 
@@ -140,7 +139,7 @@ static void release_chr(Object *obj, const char *name, void *opaque)
 
     if (chr) {
         qemu_chr_add_handlers(chr, NULL, NULL, NULL, NULL);
-        ++chr->avail_connections;
+        qemu_chr_fe_release(chr);
     }
 }
 
diff --git a/include/char/char.h b/include/char/char.h
index 32c9999..9d1ea46 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -203,6 +203,35 @@ int qemu_chr_fe_ioctl(CharDriverState *s, int cmd, void *arg);
 int qemu_chr_fe_get_msgfd(CharDriverState *s);
 
 /**
+ * @qemu_chr_fe_claim:
+ *
+ * Claim a backend before using it, should be called before calling
+ * qemu_chr_add_handlers(). 
+ *
+ * Returns: -1 if the backend is already in use by another frontend, 0 on
+ *          success.
+ */
+int qemu_chr_fe_claim(CharDriverState *s);
+
+/**
+ * @qemu_chr_fe_claim_no_fail:
+ *
+ * Like qemu_chr_fe_claim, but will exit qemu with an error when the
+ * backend is already in use.
+ */
+void qemu_chr_fe_claim_no_fail(CharDriverState *s);
+
+/**
+ * @qemu_chr_fe_claim:
+ *
+ * Release a backend for use by another frontend.
+ *
+ * Returns: -1 if the backend is already in use by another frontend, 0 on
+ *          success.
+ */
+void qemu_chr_fe_release(CharDriverState *s);
+
+/**
  * @qemu_chr_be_can_write:
  *
  * Determine how much data the front end can currently accept.  This function
diff --git a/qemu-char.c b/qemu-char.c
index 505a773..100f9a9 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3452,6 +3452,29 @@ int qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
     return tag;
 }
 
+int qemu_chr_fe_claim(CharDriverState *s)
+{
+    if (s->avail_connections < 1) {
+        return -1;
+    }
+    s->avail_connections--;
+    return 0;
+}
+
+void qemu_chr_fe_claim_no_fail(CharDriverState *s)
+{
+    if (qemu_chr_fe_claim(s) != 0) {
+        fprintf(stderr, "%s: error chardev \"%s\" already used\n",
+                __func__, s->label);
+        exit(1);
+    }
+}
+
+void qemu_chr_fe_release(CharDriverState *s)
+{
+    s->avail_connections++;
+}
+
 void qemu_chr_delete(CharDriverState *chr)
 {
     QTAILQ_REMOVE(&chardevs, chr, next);
commit 4dbb9ed3263e0f48282a2fc3d05099ba63e5b0e2
Author: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
Date:   Wed Apr 3 14:04:09 2013 +1000

    xilinx_axienet: pump events as appropriate
    
    When the conditions blocking receiving are cleared, check for buffered rx
    packets.
    
    Signed-off-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index 5785290..07c4bad 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -516,6 +516,8 @@ static void enet_write(void *opaque, hwaddr addr,
             s->rcw[addr & 1] = value;
             if ((addr & 1) && value & RCW1_RST) {
                 axienet_rx_reset(s);
+            } else {
+                qemu_flush_queued_packets(qemu_get_queue(s->nic));
             }
             break;
 
commit bd4a47330ed5b9661205dd4ac2023e452b856bf9
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Apr 2 11:28:25 2013 +0200

    po: Update German translation
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/po/de_DE.po b/po/de_DE.po
index 2566674..92c5df5 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -18,27 +18,27 @@ msgstr ""
 
 #: ../ui/gtk.c:213
 msgid " - Press Ctrl+Alt+G to release grab"
-msgstr ""
+msgstr "- Strg+Alt+G drücken, um Eingabegeräte freizugeben"
 
 #: ../ui/gtk.c:217
 msgid " [Paused]"
-msgstr ""
+msgstr "[Angehalten]"
 
 #: ../ui/gtk.c:1250
 msgid "_Machine"
-msgstr ""
+msgstr "_Maschine"
 
 #: ../ui/gtk.c:1252
 msgid "_Pause"
-msgstr ""
+msgstr "_Angehalten"
 
 #: ../ui/gtk.c:1258
 msgid "_Reset"
-msgstr ""
+msgstr "_Reset"
 
 #: ../ui/gtk.c:1261
 msgid "Power _Down"
-msgstr ""
+msgstr "_Herunterfahren"
 
 #: ../ui/gtk.c:1276
 msgid "_View"
commit a23da65924fffc6390f74e75afd33f5300091b4e
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Apr 2 11:28:24 2013 +0200

    po/Makefile: Fix dependency for %.mo
    
    Otherwise make will refuse to build updated .po files.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/po/Makefile b/po/Makefile
index 8297ab5..60ccd7d 100644
--- a/po/Makefile
+++ b/po/Makefile
@@ -30,7 +30,7 @@ install: $(OBJS)
 	    $(INSTALL) -m644 $$obj $(DESTDIR)$(prefix)/share/locale/$$base/LC_MESSAGES/qemu.mo; \
 	done
 
-%.mo:
+%.mo: %.po
 	@msgfmt -o $@ $(SRC_PATH)/po/`basename $@ .mo`.po
 
 messages.po: $(SRC_PATH)/ui/gtk.c
commit ec3960148f95dd90e94511a6a64838bc3f474bcc
Author: Jason Wang <jasowang at redhat.com>
Date:   Fri Feb 22 22:57:52 2013 +0800

    help: add docs for missing 'queues' option of tap
    
    Cc: Markus Armbruster <armbru at redhat.com>
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Message-id: 1361545072-30426-1-git-send-email-jasowang at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qapi-schema.json b/qapi-schema.json
index f629a24..bfd7a8a 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2591,6 +2591,8 @@
 #
 # @vhostforce: #optional vhost on for non-MSIX virtio guests
 #
+# @queues: #optional number of queues to be created for multiqueue capable tap
+#
 # Since 1.2
 ##
 { 'type': 'NetdevTapOptions',
diff --git a/qemu-options.hx b/qemu-options.hx
index c40ba55..7cd6002 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1360,7 +1360,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "-net tap[,vlan=n][,name=str],ifname=name\n"
     "                connect the host TAP network interface to VLAN 'n'\n"
 #else
-    "-net tap[,vlan=n][,name=str][,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile][,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off]\n"
+    "-net tap[,vlan=n][,name=str][,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile][,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off][,queues=n]\n"
     "                connect the host TAP network interface to VLAN 'n'\n"
     "                use network scripts 'file' (default=" DEFAULT_NETWORK_SCRIPT ")\n"
     "                to configure it and 'dfile' (default=" DEFAULT_NETWORK_DOWN_SCRIPT ")\n"
@@ -1379,6 +1379,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "                use vhostforce=on to force vhost on for non-MSIX virtio guests\n"
     "                use 'vhostfd=h' to connect to an already opened vhost net device\n"
     "                use 'vhostfds=x:y:...:z to connect to multiple already opened vhost net devices\n"
+    "                use 'queues=n' to specify the number of queues to be created for multiqueue TAP\n"
     "-net bridge[,vlan=n][,name=str][,br=bridge][,helper=helper]\n"
     "                connects a host TAP network interface to a host bridge device 'br'\n"
     "                (default=" DEFAULT_BRIDGE_INTERFACE ") using the program 'helper'\n"
commit 560e63965232e37d1916a447125cf91c18a96930
Author: Bruce Rogers <brogers at suse.com>
Date:   Tue Apr 2 12:41:40 2013 -0600

    acpi: initialize s4_val used in s4 shutdown
    
    While investigating why a 32 bit Windows 2003 guest wasn't able to
    successfully perform a shutdown /h, it was discovered that commit
    afafe4bbe0cf7d3318e1ac7b40925561f86a6bd4 inadvertently dropped the
    initialization of the s4_val used to handle s4 shutdown.
    Initialize the value as before.
    
    Signed-off-by: Bruce Rogers <brogers at suse.com>
    Message-id: 1364928100-487-1-git-send-email-brogers at suse.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/acpi.c b/hw/acpi.c
index 53e47d5..e9b73cf 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -472,8 +472,9 @@ static const MemoryRegionOps acpi_pm_cnt_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent)
+void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, uint8_t s4_val)
 {
+    ar->pm1.cnt.s4_val = s4_val;
     ar->wakeup.notify = acpi_notify_wakeup;
     qemu_register_wakeup_notifier(&ar->wakeup);
     memory_region_init_io(&ar->pm1.cnt.io, &acpi_pm_cnt_ops, ar, "acpi-cnt", 2);
diff --git a/hw/acpi.h b/hw/acpi.h
index c3628d0..e18ef28 100644
--- a/hw/acpi.h
+++ b/hw/acpi.h
@@ -142,7 +142,7 @@ void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci,
                        MemoryRegion *parent);
 
 /* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */
-void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent);
+void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, uint8_t s4_val);
 void acpi_pm1_cnt_update(ACPIREGS *ar,
                          bool sci_enable, bool sci_disable);
 void acpi_pm1_cnt_reset(ACPIREGS *ar);
diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c
index 29f84ff..7b34a03 100644
--- a/hw/acpi_ich9.c
+++ b/hw/acpi_ich9.c
@@ -212,7 +212,7 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
 
     acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
     acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
-    acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io);
+    acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, 2);
 
     acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
     memory_region_init_io(&pm->io_gpe, &ich9_gpe_ops, pm, "apci-gpe0",
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 7a4b712..48a32b5 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -418,7 +418,7 @@ static int piix4_pm_initfn(PCIDevice *dev)
 
     acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
     acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
-    acpi_pm1_cnt_init(&s->ar, &s->io);
+    acpi_pm1_cnt_init(&s->ar, &s->io, s->s4_val);
     acpi_gpe_init(&s->ar, GPE_LEN);
 
     s->powerdown_notifier.notify = piix4_pm_powerdown_req;
diff --git a/hw/vt82c686.c b/hw/vt82c686.c
index 4529508..9d9b64e 100644
--- a/hw/vt82c686.c
+++ b/hw/vt82c686.c
@@ -360,7 +360,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev)
 
     acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io);
     acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
-    acpi_pm1_cnt_init(&s->ar, &s->io);
+    acpi_pm1_cnt_init(&s->ar, &s->io, 2);
 
     return 0;
 }
commit a509d632c877f7b5fa07368879b8ae5919a6d345
Author: Eduardo Habkost <ehabkost at redhat.com>
Date:   Tue Apr 2 17:48:12 2013 -0300

    target-i386: Check for host features before filter_features_for_kvm()
    
    commit 5ec01c2e96910e1588d1a0de8609b9dda7618c7f broke "-cpu ..,enforce",
    as it has moved kvm_check_features_against_host() after the
    filter_features_for_kvm() call. filter_features_for_kvm() removes all
    features not supported by the host, so this effectively made
    kvm_check_features_against_host() impossible to fail.
    
    This patch changes the call so we check for host feature support before
    filtering the feature bits.
    
    Signed-off-by: Eduardo Habkost <ehabkost at redhat.com>
    Message-id: 1364935692-24004-1-git-send-email-ehabkost at redhat.com
    Cc: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 4b43759..bf717d5 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2131,14 +2131,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
         env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
         env->cpuid_svm_features &= TCG_SVM_FEATURES;
     } else {
-#ifdef CONFIG_KVM
-        filter_features_for_kvm(cpu);
-#endif
         if (check_cpuid && kvm_check_features_against_host(cpu)
             && enforce_cpuid) {
             error_setg(errp, "Host's CPU doesn't support requested features");
             return;
         }
+#ifdef CONFIG_KVM
+        filter_features_for_kvm(cpu);
+#endif
     }
 
 #ifndef CONFIG_USER_ONLY
commit 8243b0464b247ff460178a15f1fe306ef9c70b49
Author: Stefan Weil <sw at weilnetz.de>
Date:   Tue Apr 2 22:14:51 2013 +0200

    tpm: Fix several compiler warnings (redefined data types)
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Message-id: 1364933691-21197-1-git-send-email-sw at weilnetz.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/tpm/tpm_int.h b/tpm/tpm_int.h
index b4787ad..340bfd5 100644
--- a/tpm/tpm_int.h
+++ b/tpm/tpm_int.h
@@ -15,11 +15,8 @@
 #include "exec/memory.h"
 #include "tpm/tpm_tis.h"
 
-struct TPMDriverOps;
-typedef struct TPMDriverOps TPMDriverOps;
-
 /* overall state of the TPM interface */
-typedef struct TPMState {
+struct TPMState {
     ISADevice busdev;
     MemoryRegion mmio;
 
@@ -32,12 +29,10 @@ typedef struct TPMState {
 
     char *backend;
     TPMBackend *be_driver;
-} TPMState;
+};
 
 #define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS)
 
-typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty);
-
 struct TPMDriverOps {
     enum TpmType type;
     /* get a descriptive text of the backend to display to the user */
diff --git a/tpm/tpm_tis.h b/tpm/tpm_tis.h
index 0c8df80..7f216e5 100644
--- a/tpm/tpm_tis.h
+++ b/tpm/tpm_tis.h
@@ -35,10 +35,10 @@
 #define TYPE_TPM_TIS                "tpm-tis"
 
 
-typedef struct TPMSizedBuffer {
+struct TPMSizedBuffer {
     uint32_t size;
     uint8_t  *buffer;
-} TPMSizedBuffer;
+};
 
 typedef enum {
     TPM_TIS_STATE_IDLE = 0,
commit eabb21aac9665097676b97fa3e053ae2982eba1e
Merge: 162cbbd 044d4e1
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Apr 3 15:05:52 2013 -0500

    Merge remote-tracking branch 'sstabellini/xen-2013-04-03' into staging
    
    # By Hanweidong (1) and Stefano Stabellini (1)
    # Via Stefano Stabellini
    * sstabellini/xen-2013-04-03:
      xen-mapcache: pass the right size argument to test_bits
      xen-mapcache: replace last_address_index with a last_entry pointer

commit 044d4e1aae539bd4214175bd9591b3de7986cf18
Author: Hanweidong <hanweidong at huawei.com>
Date:   Tue Apr 2 13:22:41 2013 +0000

    xen-mapcache: pass the right size argument to test_bits
    
    Compute the correct size for test_bits().
    qemu_get_ram_ptr() and qemu_safe_ram_ptr() will call xen_map_cache()
    with size is 0 if the requested address is in the RAM.  Then
    xen_map_cache() will pass the size 0 to test_bits() for checking if the
    corresponding pfn was mapped in cache. But test_bits() will always
    return 1 when size is 0 without any bit testing. Actually, for this
    case, test_bits should check one bit. So this patch introduced a
    __test_bit_size which is greater than 0 and a multiple of XC_PAGE_SIZE,
    then test_bits can work correctly with __test_bit_size
    >> XC_PAGE_SHIFT as its size.
    
    Signed-off-by: Zhenguo Wang <wangzhenguo at huawei.com>
    Signed-off-by: Weidong Han <hanweidong at huawei.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/xen-mapcache.c b/xen-mapcache.c
index a80cbdb..5a626cd 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -200,6 +200,7 @@ uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size,
     hwaddr address_index;
     hwaddr address_offset;
     hwaddr __size = size;
+    hwaddr __test_bit_size = size;
     bool translated = false;
 
 tryagain:
@@ -208,9 +209,23 @@ tryagain:
 
     trace_xen_map_cache(phys_addr);
 
+    /* __test_bit_size is always a multiple of XC_PAGE_SIZE */
+    if (size) {
+        __test_bit_size = size + (phys_addr & (XC_PAGE_SIZE - 1));
+
+        if (__test_bit_size % XC_PAGE_SIZE) {
+            __test_bit_size += XC_PAGE_SIZE - (__test_bit_size % XC_PAGE_SIZE);
+        }
+    } else {
+        __test_bit_size = XC_PAGE_SIZE;
+    }
+
     if (mapcache->last_entry != NULL &&
         mapcache->last_entry->paddr_index == address_index &&
-        !lock && !__size) {
+        !lock && !__size &&
+        test_bits(address_offset >> XC_PAGE_SHIFT,
+                  __test_bit_size >> XC_PAGE_SHIFT,
+                  mapcache->last_entry->valid_mapping)) {
         trace_xen_map_cache_return(mapcache->last_entry->vaddr_base + address_offset);
         return mapcache->last_entry->vaddr_base + address_offset;
     }
@@ -229,7 +244,8 @@ tryagain:
 
     while (entry && entry->lock && entry->vaddr_base &&
             (entry->paddr_index != address_index || entry->size != __size ||
-             !test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
+             !test_bits(address_offset >> XC_PAGE_SHIFT,
+                 __test_bit_size >> XC_PAGE_SHIFT,
                  entry->valid_mapping))) {
         pentry = entry;
         entry = entry->next;
@@ -241,13 +257,15 @@ tryagain:
     } else if (!entry->lock) {
         if (!entry->vaddr_base || entry->paddr_index != address_index ||
                 entry->size != __size ||
-                !test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
+                !test_bits(address_offset >> XC_PAGE_SHIFT,
+                    __test_bit_size >> XC_PAGE_SHIFT,
                     entry->valid_mapping)) {
             xen_remap_bucket(entry, __size, address_index);
         }
     }
 
-    if(!test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
+    if(!test_bits(address_offset >> XC_PAGE_SHIFT,
+                __test_bit_size >> XC_PAGE_SHIFT,
                 entry->valid_mapping)) {
         mapcache->last_entry = NULL;
         if (!translated && mapcache->phys_offset_to_gaddr) {
commit e2deee3ea6136b6189e8cfd26379420b9a398d96
Author: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Date:   Tue Apr 2 13:23:40 2013 +0000

    xen-mapcache: replace last_address_index with a last_entry pointer
    
    Replace last_address_index and last_address_vaddr with a single pointer
    to the last MapCacheEntry used.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>

diff --git a/xen-mapcache.c b/xen-mapcache.c
index dc6d1fa..a80cbdb 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -74,8 +74,7 @@ typedef struct MapCache {
     QTAILQ_HEAD(map_cache_head, MapCacheRev) locked_entries;
 
     /* For most cases (>99.9%), the page address is the same. */
-    hwaddr last_address_index;
-    uint8_t *last_address_vaddr;
+    MapCacheEntry *last_entry;
     unsigned long max_mcache_size;
     unsigned int mcache_bucket_shift;
 
@@ -105,7 +104,6 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
     mapcache->opaque = opaque;
 
     QTAILQ_INIT(&mapcache->locked_entries);
-    mapcache->last_address_index = -1;
 
     if (geteuid() == 0) {
         rlimit_as.rlim_cur = RLIM_INFINITY;
@@ -210,9 +208,11 @@ tryagain:
 
     trace_xen_map_cache(phys_addr);
 
-    if (address_index == mapcache->last_address_index && !lock && !__size) {
-        trace_xen_map_cache_return(mapcache->last_address_vaddr + address_offset);
-        return mapcache->last_address_vaddr + address_offset;
+    if (mapcache->last_entry != NULL &&
+        mapcache->last_entry->paddr_index == address_index &&
+        !lock && !__size) {
+        trace_xen_map_cache_return(mapcache->last_entry->vaddr_base + address_offset);
+        return mapcache->last_entry->vaddr_base + address_offset;
     }
 
     /* size is always a multiple of MCACHE_BUCKET_SIZE */
@@ -249,7 +249,7 @@ tryagain:
 
     if(!test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
                 entry->valid_mapping)) {
-        mapcache->last_address_index = -1;
+        mapcache->last_entry = NULL;
         if (!translated && mapcache->phys_offset_to_gaddr) {
             phys_addr = mapcache->phys_offset_to_gaddr(phys_addr, size, mapcache->opaque);
             translated = true;
@@ -259,19 +259,18 @@ tryagain:
         return NULL;
     }
 
-    mapcache->last_address_index = address_index;
-    mapcache->last_address_vaddr = entry->vaddr_base;
+    mapcache->last_entry = entry;
     if (lock) {
         MapCacheRev *reventry = g_malloc0(sizeof(MapCacheRev));
         entry->lock++;
-        reventry->vaddr_req = mapcache->last_address_vaddr + address_offset;
-        reventry->paddr_index = mapcache->last_address_index;
+        reventry->vaddr_req = mapcache->last_entry->vaddr_base + address_offset;
+        reventry->paddr_index = mapcache->last_entry->paddr_index;
         reventry->size = entry->size;
         QTAILQ_INSERT_HEAD(&mapcache->locked_entries, reventry, next);
     }
 
-    trace_xen_map_cache_return(mapcache->last_address_vaddr + address_offset);
-    return mapcache->last_address_vaddr + address_offset;
+    trace_xen_map_cache_return(mapcache->last_entry->vaddr_base + address_offset);
+    return mapcache->last_entry->vaddr_base + address_offset;
 }
 
 ram_addr_t xen_ram_addr_from_mapcache(void *ptr)
@@ -338,9 +337,9 @@ void xen_invalidate_map_cache_entry(uint8_t *buffer)
     QTAILQ_REMOVE(&mapcache->locked_entries, reventry, next);
     g_free(reventry);
 
-    if (mapcache->last_address_index == paddr_index) {
-        mapcache->last_address_index = -1;
-        mapcache->last_address_vaddr = NULL;
+    if (mapcache->last_entry != NULL &&
+        mapcache->last_entry->paddr_index == paddr_index) {
+        mapcache->last_entry = NULL;
     }
 
     entry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
@@ -404,8 +403,7 @@ void xen_invalidate_map_cache(void)
         entry->valid_mapping = NULL;
     }
 
-    mapcache->last_address_index = -1;
-    mapcache->last_address_vaddr = NULL;
+    mapcache->last_entry = NULL;
 
     mapcache_unlock();
 }
commit 162cbbd1736de2bca43fdefa7e98c54a361ee60d
Merge: 9d4563c 9b938c7
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 2 14:07:35 2013 -0500

    Merge remote-tracking branch 'luiz/queue/qmp' into staging
    
    # By Stefan Hajnoczi
    # Via Luiz Capitulino
    * luiz/queue/qmp:
      chardev: clear O_NONBLOCK on SCM_RIGHTS file descriptors
      qemu-socket: set passed fd non-blocking in socket_connect()
      net: ensure "socket" backend uses non-blocking fds
      oslib-posix: rename socket_set_nonblock() to qemu_set_nonblock()

commit 9d4563c415683e4d06c84a46e8d178a680fdcb7b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Apr 2 17:57:56 2013 +0200

    configure: remove unset variables
    
    These variables have not been set for a long time.  Do not
    include them in config-host.mak.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1364918276-11866-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index fbea75e..d685275 100755
--- a/configure
+++ b/configure
@@ -3899,8 +3899,6 @@ else
   echo "AUTOCONF_HOST := "                             >> $config_host_mak
 fi
 echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
-echo "ARLIBS_BEGIN=$arlibs_begin" >> $config_host_mak
-echo "ARLIBS_END=$arlibs_end" >> $config_host_mak
 echo "LIBS+=$LIBS" >> $config_host_mak
 echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
 echo "EXESUF=$EXESUF" >> $config_host_mak
commit 9b938c7262e403f5467110609cb20ef1ae6e9df2
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 27 10:10:46 2013 +0100

    chardev: clear O_NONBLOCK on SCM_RIGHTS file descriptors
    
    When we receive a file descriptor over a UNIX domain socket the
    O_NONBLOCK flag is preserved.  Clear the O_NONBLOCK flag and rely on
    QEMU file descriptor users like migration, SPICE, VNC, block layer, and
    others to set non-blocking only when necessary.
    
    This change ensures we don't accidentally expose O_NONBLOCK in the QMP
    API.  QMP clients should not need to get the non-blocking state
    "correct".
    
    A recent real-world example was when libvirt passed a non-blocking TCP
    socket for migration where we expected a blocking socket.  The source
    QEMU produced a corrupted migration stream since its code did not cope
    with non-blocking sockets.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qemu-char.c b/qemu-char.c
index 4d8c6ca..d825b60 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2440,6 +2440,9 @@ static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg)
         if (fd < 0)
             continue;
 
+        /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
+        qemu_set_block(fd);
+
 #ifndef MSG_CMSG_CLOEXEC
         qemu_set_cloexec(fd);
 #endif
commit 1a751ebfbb2d7a696b889d8208cb5ffc83c090b1
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 27 10:10:45 2013 +0100

    qemu-socket: set passed fd non-blocking in socket_connect()
    
    socket_connect() sets non-blocking on TCP or UNIX domain sockets if a
    callback function is passed.  Do the same for file descriptor passing,
    otherwise we could unexpectedly be using a blocking file descriptor.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index b632a74..94581aa 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -910,6 +910,7 @@ int socket_connect(SocketAddress *addr, Error **errp,
     case SOCKET_ADDRESS_KIND_FD:
         fd = monitor_get_fd(cur_mon, addr->fd->str, errp);
         if (callback) {
+            qemu_set_nonblock(fd);
             callback(fd, opaque);
         }
         break;
commit fc13fa00eaff6797c67abc9b0f748b346f238986
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 27 10:10:44 2013 +0100

    net: ensure "socket" backend uses non-blocking fds
    
    There are several code paths in net_init_socket() depending on how the
    socket is created: file descriptor passing, UDP multicast, TCP, or UDP.
    Some of these support both listen and connect.
    
    Not all code paths set the socket to non-blocking.  This patch addresses
    the file descriptor passing and UDP cases which were missing
    socket_set_nonblock(fd) calls.
    
    I considered moving socket_set_nonblock(fd) to a central location but it
    turns out the code paths are different enough to require non-blocking at
    different places.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/net/socket.c b/net/socket.c
index b5c8e65..87af1d3 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -674,6 +674,7 @@ static int net_socket_udp_init(NetClientState *peer,
         closesocket(fd);
         return -1;
     }
+    qemu_set_nonblock(fd);
 
     s = net_socket_fd_init(peer, model, name, fd, 0);
     if (!s) {
@@ -712,7 +713,11 @@ int net_init_socket(const NetClientOptions *opts, const char *name,
         int fd;
 
         fd = monitor_handle_fd_param(cur_mon, sock->fd);
-        if (fd == -1 || !net_socket_fd_init(peer, "socket", name, fd, 1)) {
+        if (fd == -1) {
+            return -1;
+        }
+        qemu_set_nonblock(fd);
+        if (!net_socket_fd_init(peer, "socket", name, fd, 1)) {
             return -1;
         }
         return 0;
commit f9e8cacc5557e4372401da74141f833fcacda038
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Wed Mar 27 10:10:43 2013 +0100

    oslib-posix: rename socket_set_nonblock() to qemu_set_nonblock()
    
    The fcntl(fd, F_SETFL, O_NONBLOCK) flag is not specific to sockets.
    Rename to qemu_set_nonblock() just like qemu_set_cloexec().
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/block/nbd.c b/block/nbd.c
index 3d711b2..eff683c 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -415,7 +415,7 @@ static int nbd_establish_connection(BlockDriverState *bs)
 
     /* Now that we're connected, set the socket to be non-blocking and
      * kick the reply mechanism.  */
-    socket_set_nonblock(sock);
+    qemu_set_nonblock(sock);
     qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL,
                             nbd_have_request, s);
 
diff --git a/block/sheepdog.c b/block/sheepdog.c
index bb67c4c..987018e 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -471,7 +471,7 @@ static int connect_to_sdog(BDRVSheepdogState *s)
         qerror_report_err(err);
         error_free(err);
     } else {
-        socket_set_nonblock(fd);
+        qemu_set_nonblock(fd);
     }
 
     return fd;
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index d225f6d..c5174d7 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -37,8 +37,8 @@ int qemu_socket(int domain, int type, int protocol);
 int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
 int socket_set_cork(int fd, int v);
 int socket_set_nodelay(int fd);
-void socket_set_block(int fd);
-void socket_set_nonblock(int fd);
+void qemu_set_block(int fd);
+void qemu_set_nonblock(int fd);
 int send_all(int fd, const void *buf, int len1);
 int recv_all(int fd, void *buf, int len1, bool single_read);
 
diff --git a/migration.c b/migration.c
index 7fb2147..3b4b467 100644
--- a/migration.c
+++ b/migration.c
@@ -121,7 +121,7 @@ void process_incoming_migration(QEMUFile *f)
     int fd = qemu_get_fd(f);
 
     assert(fd != -1);
-    socket_set_nonblock(fd);
+    qemu_set_nonblock(fd);
     qemu_coroutine_enter(co, f);
 }
 
diff --git a/nbd.c b/nbd.c
index d1a67ee..85187ff 100644
--- a/nbd.c
+++ b/nbd.c
@@ -386,7 +386,7 @@ static int nbd_send_negotiate(NBDClient *client)
         [28 .. 151]   reserved     (0)
      */
 
-    socket_set_block(csock);
+    qemu_set_block(csock);
     rc = -EINVAL;
 
     TRACE("Beginning negotiation.");
@@ -429,7 +429,7 @@ static int nbd_send_negotiate(NBDClient *client)
     TRACE("Negotiation succeeded.");
     rc = 0;
 fail:
-    socket_set_nonblock(csock);
+    qemu_set_nonblock(csock);
     return rc;
 }
 
@@ -443,7 +443,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
 
     TRACE("Receiving negotiation.");
 
-    socket_set_block(csock);
+    qemu_set_block(csock);
     rc = -EINVAL;
 
     if (read_sync(csock, buf, 8) != 8) {
@@ -558,7 +558,7 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
     rc = 0;
 
 fail:
-    socket_set_nonblock(csock);
+    qemu_set_nonblock(csock);
     return rc;
 }
 
diff --git a/net/socket.c b/net/socket.c
index 6c3752b..b5c8e65 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -308,7 +308,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr
         }
     }
 
-    socket_set_nonblock(fd);
+    qemu_set_nonblock(fd);
     return fd;
 fail:
     if (fd >= 0)
@@ -519,7 +519,7 @@ static int net_socket_listen_init(NetClientState *peer,
         perror("socket");
         return -1;
     }
-    socket_set_nonblock(fd);
+    qemu_set_nonblock(fd);
 
     /* allow fast reuse */
     val = 1;
@@ -565,7 +565,7 @@ static int net_socket_connect_init(NetClientState *peer,
         perror("socket");
         return -1;
     }
-    socket_set_nonblock(fd);
+    qemu_set_nonblock(fd);
 
     connected = 0;
     for(;;) {
diff --git a/qemu-char.c b/qemu-char.c
index dee623e..4d8c6ca 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2570,7 +2570,7 @@ static int tcp_chr_add_client(CharDriverState *chr, int fd)
     if (s->fd != -1)
 	return -1;
 
-    socket_set_nonblock(fd);
+    qemu_set_nonblock(fd);
     if (s->do_nodelay)
         socket_set_nodelay(fd);
     s->fd = fd;
@@ -2722,7 +2722,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay,
         printf("QEMU waiting for connection on: %s\n",
                chr->filename);
         tcp_chr_accept(s->listen_chan, G_IO_IN, chr);
-        socket_set_nonblock(s->listen_fd);
+        qemu_set_nonblock(s->listen_fd);
     }
     return chr;
 }
@@ -2764,7 +2764,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     }
 
     if (!is_waitconnect)
-        socket_set_nonblock(fd);
+        qemu_set_nonblock(fd);
 
     chr = qemu_chr_open_socket_fd(fd, do_nodelay, is_listen, is_telnet,
                                   is_waitconnect, &local_err);
@@ -3653,7 +3653,7 @@ static CharDriverState *qmp_chardev_open_serial(ChardevHostdev *serial,
     if (error_is_set(errp)) {
         return NULL;
     }
-    socket_set_nonblock(fd);
+    qemu_set_nonblock(fd);
     return qemu_chr_open_tty_fd(fd);
 #else
     error_setg(errp, "character device backend type 'serial' not supported");
diff --git a/savevm.c b/savevm.c
index 406caa9..b1d8988 100644
--- a/savevm.c
+++ b/savevm.c
@@ -422,7 +422,7 @@ QEMUFile *qemu_fopen_socket(int fd, const char *mode)
 
     s->fd = fd;
     if (mode[0] == 'w') {
-        socket_set_block(s->fd);
+        qemu_set_block(s->fd);
         s->file = qemu_fopen_ops(s, &socket_write_ops);
     } else {
         s->file = qemu_fopen_ops(s, &socket_read_ops);
diff --git a/slirp/misc.c b/slirp/misc.c
index 6b9c2c4..8ecced5 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -215,7 +215,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
                 qemu_setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
                 opt = 1;
                 qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
-		socket_set_nonblock(so->s);
+		qemu_set_nonblock(so->s);
 
 		/* Append the telnet options now */
                 if (so->so_m != NULL && do_pty == 1)  {
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 84a6bb5..e98ce1a 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -336,7 +336,7 @@ int tcp_fconnect(struct socket *so)
     int opt, s=so->s;
     struct sockaddr_in addr;
 
-    socket_set_nonblock(s);
+    qemu_set_nonblock(s);
     opt = 1;
     qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
     opt = 1;
@@ -425,7 +425,7 @@ void tcp_connect(struct socket *inso)
         tcp_close(sototcpcb(so)); /* This will sofree() as well */
         return;
     }
-    socket_set_nonblock(s);
+    qemu_set_nonblock(s);
     opt = 1;
     qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
     opt = 1;
diff --git a/ui/vnc.c b/ui/vnc.c
index bbe1e0f..5ddb696 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2732,7 +2732,7 @@ static void vnc_connect(VncDisplay *vd, int csock, int skipauth, bool websocket)
 
     VNC_DEBUG("New client on socket %d\n", csock);
     vd->dcl.idle = 0;
-    socket_set_nonblock(vs->csock);
+    qemu_set_nonblock(vs->csock);
 #ifdef CONFIG_VNC_WS
     if (websocket) {
         vs->websocket = 1;
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 433dd68..4e4b819 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -134,14 +134,14 @@ void qemu_vfree(void *ptr)
     free(ptr);
 }
 
-void socket_set_block(int fd)
+void qemu_set_block(int fd)
 {
     int f;
     f = fcntl(fd, F_GETFL);
     fcntl(fd, F_SETFL, f & ~O_NONBLOCK);
 }
 
-void socket_set_nonblock(int fd)
+void qemu_set_nonblock(int fd)
 {
     int f;
     f = fcntl(fd, F_GETFL);
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 640194c..dcfa0c2 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -100,14 +100,14 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
     return p;
 }
 
-void socket_set_block(int fd)
+void qemu_set_block(int fd)
 {
     unsigned long opt = 0;
     WSAEventSelect(fd, NULL, 0);
     ioctlsocket(fd, FIONBIO, &opt);
 }
 
-void socket_set_nonblock(int fd)
+void qemu_set_nonblock(int fd)
 {
     unsigned long opt = 1;
     ioctlsocket(fd, FIONBIO, &opt);
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index b6b78f5..b632a74 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -277,7 +277,7 @@ static int inet_connect_addr(struct addrinfo *addr, bool *in_progress,
     }
     qemu_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
     if (connect_state != NULL) {
-        socket_set_nonblock(sock);
+        qemu_set_nonblock(sock);
     }
     /* connect to peer */
     do {
@@ -737,7 +737,7 @@ int unix_connect_opts(QemuOpts *opts, Error **errp,
         connect_state = g_malloc0(sizeof(*connect_state));
         connect_state->callback = callback;
         connect_state->opaque = opaque;
-        socket_set_nonblock(sock);
+        qemu_set_nonblock(sock);
     }
 
     memset(&un, 0, sizeof(un));
commit c707582b78d01d81fe4e470fd812334be145882d
Author: Wenchao Xia <xiawenc at linux.vnet.ibm.com>
Date:   Tue Mar 26 10:24:06 2013 +0800

    VMXNET3: initialize rx_ridx to eliminate compile warning
    
      Gcc report "hw/vmxnet3.c:972: error: ‘rx_ridx’ may be used
    uninitialized in this function", so fix it.
    
    Signed-off-by: Wenchao Xia <xiawenc at linux.vnet.ibm.com>
    Message-id: 1364264646-27542-1-git-send-email-xiawenc at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/vmxnet3.c b/hw/vmxnet3.c
index 925be80..bdd256e 100644
--- a/hw/vmxnet3.c
+++ b/hw/vmxnet3.c
@@ -969,7 +969,7 @@ vmxnet3_indicate_packet(VMXNET3State *s)
     struct Vmxnet3_RxDesc rxd;
     bool is_head = true;
     uint32_t rxd_idx;
-    uint32_t rx_ridx;
+    uint32_t rx_ridx = 0;
 
     struct Vmxnet3_RxCompDesc rxcd;
     uint32_t new_rxcd_gen = VMXNET3_INIT_GEN;
commit b1ee58290d7cc2c6b1231fd701987c1753ad9ae3
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Mar 27 11:36:14 2013 -0500

    qdev: only send deleted event if device was realized
    
    Reported-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364402174-16580-1-git-send-email-aliguori at us.ibm.com

diff --git a/hw/qdev.c b/hw/qdev.c
index 9b0f652..e2bb37d 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -767,7 +767,7 @@ static void device_unparent(Object *obj)
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
     BusState *bus;
     QObject *event_data;
-    gchar *path = object_get_canonical_path(obj);
+    bool have_realized = dev->realized;
 
     while (dev->num_child_bus) {
         bus = QLIST_FIRST(&dev->child_bus);
@@ -787,15 +787,20 @@ static void device_unparent(Object *obj)
         dev->parent_bus = NULL;
     }
 
-    if (dev->id) {
-        event_data = qobject_from_jsonf("{ 'device': %s, 'path': %s }",
-                                        dev->id, path);
-    } else {
-        event_data = qobject_from_jsonf("{ 'path': %s }", path);
+    /* Only send event if the device had been completely realized */
+    if (have_realized) {
+        gchar *path = object_get_canonical_path(OBJECT(dev));
+
+        if (dev->id) {
+            event_data = qobject_from_jsonf("{ 'device': %s, 'path': %s }",
+                                            dev->id, path);
+        } else {
+            event_data = qobject_from_jsonf("{ 'path': %s }", path);
+        }
+        monitor_protocol_event(QEVENT_DEVICE_DELETED, event_data);
+        qobject_decref(event_data);
+        g_free(path);
     }
-    monitor_protocol_event(QEVENT_DEVICE_DELETED, event_data);
-    qobject_decref(event_data);
-    g_free(path);
 }
 
 static void device_class_init(ObjectClass *class, void *data)
commit 8f0605cc9caacbcc647a6df9ae541ed2da4b9bb0
Author: Stefan Berger <stefanb at linux.vnet.ibm.com>
Date:   Thu Mar 28 07:26:21 2013 -0400

    QOM-ify the TPM support
    
    QOM-ified the TPM support with much code borrowed from the rng implementation.
    
    All other TPM related code moves will be provided in a subsequent patch.
    
    Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
    Message-id: 1364469981.24703.1.camel at d941e-10
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 464bc3e..42557d5 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -4,3 +4,5 @@ common-obj-$(CONFIG_POSIX) += rng-random.o
 common-obj-y += msmouse.o
 common-obj-$(CONFIG_BRLAPI) += baum.o
 $(obj)/baum.o: QEMU_CFLAGS += $(SDL_CFLAGS) 
+
+common-obj-$(CONFIG_TPM) += tpm.o
diff --git a/backends/tpm.c b/backends/tpm.c
new file mode 100644
index 0000000..28148c2
--- /dev/null
+++ b/backends/tpm.c
@@ -0,0 +1,154 @@
+/*
+ * QEMU TPM Backend
+ *
+ * Copyright IBM, Corp. 2013
+ *
+ * Authors:
+ *  Stefan Berger   <stefanb at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * Based on backends/rng.c by Anthony Liguori
+ */
+
+#include "backends/tpm.h"
+#include "tpm/tpm_int.h"
+#include "qapi/qmp/qerror.h"
+
+enum TpmType tpm_backend_get_type(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->type;
+}
+
+const char *tpm_backend_get_desc(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->desc();
+}
+
+void tpm_backend_destroy(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->destroy(s);
+}
+
+int tpm_backend_init(TPMBackend *s, TPMState *state,
+                     TPMRecvDataCB *datacb)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->init(s, state, datacb);
+}
+
+int tpm_backend_startup_tpm(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->startup_tpm(s);
+}
+
+bool tpm_backend_had_startup_error(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->had_startup_error(s);
+}
+
+size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->realloc_buffer(sb);
+}
+
+void tpm_backend_deliver_request(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    k->ops->deliver_request(s);
+}
+
+void tpm_backend_reset(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    k->ops->reset(s);
+}
+
+void tpm_backend_cancel_cmd(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    k->ops->cancel_cmd(s);
+}
+
+bool tpm_backend_get_tpm_established_flag(TPMBackend *s)
+{
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    return k->ops->get_tpm_established_flag(s);
+}
+
+static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
+{
+    TPMBackend *s = TPM_BACKEND(obj);
+
+    return s->opened;
+}
+
+void tpm_backend_open(TPMBackend *s, Error **errp)
+{
+    object_property_set_bool(OBJECT(s), true, "opened", errp);
+}
+
+static void tpm_backend_prop_set_opened(Object *obj, bool value, Error **errp)
+{
+    TPMBackend *s = TPM_BACKEND(obj);
+    TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+    if (value == s->opened) {
+        return;
+    }
+
+    if (!value && s->opened) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    if (k->opened) {
+        k->opened(s, errp);
+    }
+
+    if (!error_is_set(errp)) {
+        s->opened = value;
+    }
+}
+
+static void tpm_backend_instance_init(Object *obj)
+{
+    object_property_add_bool(obj, "opened",
+                             tpm_backend_prop_get_opened,
+                             tpm_backend_prop_set_opened,
+                             NULL);
+}
+
+static const TypeInfo tpm_backend_info = {
+    .name = TYPE_TPM_BACKEND,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(TPMBackend),
+    .instance_init = tpm_backend_instance_init,
+    .class_size = sizeof(TPMBackendClass),
+    .abstract = true,
+};
+
+static void register_types(void)
+{
+    type_register_static(&tpm_backend_info);
+}
+
+type_init(register_types);
diff --git a/include/backends/tpm.h b/include/backends/tpm.h
new file mode 100644
index 0000000..9e93cc5
--- /dev/null
+++ b/include/backends/tpm.h
@@ -0,0 +1,170 @@
+/*
+ * QEMU TPM Backend
+ *
+ * Copyright IBM, Corp. 2013
+ *
+ * Authors:
+ *  Stefan Berger  <stefanb at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef _QEMU_TPM_H
+#define _QEMU_TPM_H
+
+#include "qom/object.h"
+#include "qemu-common.h"
+#include "qapi/error.h"
+#include "qapi-types.h"
+#include "qemu/option.h"
+#include "tpm/tpm.h"
+
+#define TYPE_TPM_BACKEND "tpm-backend"
+#define TPM_BACKEND(obj) \
+    OBJECT_CHECK(TPMBackend, (obj), TYPE_TPM_BACKEND)
+#define TPM_BACKEND_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(TPMBackendClass, (obj), TYPE_TPM_BACKEND)
+#define TPM_BACKEND_CLASS(klass) \
+    OBJECT_CLASS_CHECK(TPMBackendClass, (klass), TYPE_TPM_BACKEND)
+
+typedef struct TPMBackendClass TPMBackendClass;
+typedef struct TPMBackend TPMBackend;
+
+typedef struct TPMDriverOps TPMDriverOps;
+
+struct TPMBackendClass {
+    ObjectClass parent_class;
+
+    const TPMDriverOps *ops;
+
+    void (*opened)(TPMBackend *s, Error **errp);
+};
+
+struct TPMBackend {
+    Object parent;
+
+    /*< protected >*/
+    bool opened;
+
+    char *id;
+    enum TpmModel fe_model;
+    char *path;
+    char *cancel_path;
+    const TPMDriverOps *ops;
+
+    QLIST_ENTRY(TPMBackend) list;
+};
+
+
+/**
+ * tpm_backend_get_type:
+ * @s: the backend
+ *
+ * Returns the TpmType of the backend.
+ */
+enum TpmType tpm_backend_get_type(TPMBackend *s);
+
+/**
+ * tpm_backend_get_desc:
+ * @s: the backend
+ *
+ * Returns a human readable description of the backend.
+ */
+const char *tpm_backend_get_desc(TPMBackend *s);
+
+/**
+ * tpm_backend_destroy:
+ * @s: the backend to destroy
+ */
+void tpm_backend_destroy(TPMBackend *s);
+
+/**
+ * tpm_backend_init:
+ * @s: the backend to initialized
+ * @state: TPMState
+ * @datacb: callback for sending data to frontend
+ *
+ * Initialize the backend with the given variables.
+ *
+ * Returns 0 on success.
+ */
+int tpm_backend_init(TPMBackend *s, TPMState *state,
+                     TPMRecvDataCB *datacb);
+
+/**
+ * tpm_backend_startup_tpm:
+ * @s: the backend whose TPM support is to be started
+ *
+ * Returns 0 on success.
+ */
+int tpm_backend_startup_tpm(TPMBackend *s);
+
+/**
+ * tpm_backend_had_startup_error:
+ * @s: the backend to query for a statup error
+ *
+ * Check whether the backend had an error during startup. Returns
+ * false if no error occurred and the backend can be used, true
+ * otherwise.
+ */
+bool tpm_backend_had_startup_error(TPMBackend *s);
+
+/**
+ * tpm_backend_realloc_buffer:
+ * @s: the backend
+ * @sb: the TPMSizedBuffer to re-allocated to the size suitable for the
+ *      backend.
+ *
+ * This function returns the size of the allocated buffer
+ */
+size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb);
+
+/**
+ * tpm_backend_deliver_request:
+ * @s: the backend to send the request to
+ *
+ * Send a request to the backend. The backend will then send the request
+ * to the TPM implementation.
+ */
+void tpm_backend_deliver_request(TPMBackend *s);
+
+/**
+ * tpm_backend_reset:
+ * @s: the backend to reset
+ *
+ * Reset the backend into a well defined state with all previous errors
+ * reset.
+ */
+void tpm_backend_reset(TPMBackend *s);
+
+/**
+ * tpm_backend_cancel_cmd:
+ * @s: the backend
+ *
+ * Cancel any ongoing command being processed by the TPM implementation
+ * on behalf of the QEMU guest.
+ */
+void tpm_backend_cancel_cmd(TPMBackend *s);
+
+/**
+ * tpm_backend_get_tpm_established_flag:
+ * @s: the backend
+ *
+ * Get the TPM establishment flag. This function may be called very
+ * frequently by the frontend since for example in the TIS implementation
+ * this flag is part of a register.
+ */
+bool tpm_backend_get_tpm_established_flag(TPMBackend *s);
+
+/**
+ * tpm_backend_open:
+ * @s: the backend to open
+ * @errp: a pointer to return the #Error object if an error occurs.
+ *
+ * This function will open the backend if it is not already open.  Calling this
+ * function on an already opened backend will not result in an error.
+ */
+void tpm_backend_open(TPMBackend *s, Error **errp);
+
+#endif
diff --git a/include/tpm/tpm.h b/include/tpm/tpm.h
index cc8f20e..2d457c4 100644
--- a/include/tpm/tpm.h
+++ b/include/tpm/tpm.h
@@ -14,6 +14,10 @@
 
 #include "qemu/option.h"
 
+typedef struct TPMState TPMState;
+typedef struct TPMSizedBuffer TPMSizedBuffer;
+typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty);
+
 int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
 int tpm_init(void);
 void tpm_cleanup(void);
diff --git a/tpm/tpm.c b/tpm/tpm.c
index ae00eae..1f4ac8d 100644
--- a/tpm/tpm.c
+++ b/tpm/tpm.c
@@ -15,6 +15,7 @@
 
 #include "monitor/monitor.h"
 #include "qapi/qmp/qerror.h"
+#include "backends/tpm.h"
 #include "tpm_int.h"
 #include "tpm/tpm.h"
 #include "qemu/config-file.h"
@@ -145,6 +146,7 @@ static int configure_tpm(QemuOpts *opts)
     const char *id;
     const TPMDriverOps *be;
     TPMBackend *drv;
+    Error *local_err = NULL;
 
     if (!QLIST_EMPTY(&tpm_backends)) {
         error_report("Only one TPM is allowed.\n");
@@ -177,6 +179,13 @@ static int configure_tpm(QemuOpts *opts)
         return 1;
     }
 
+    tpm_backend_open(drv, &local_err);
+    if (local_err) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return 1;
+    }
+
     QLIST_INSERT_HEAD(&tpm_backends, drv, list);
 
     return 0;
@@ -197,7 +206,7 @@ void tpm_cleanup(void)
 
     QLIST_FOREACH_SAFE(drv, &tpm_backends, list, next) {
         QLIST_REMOVE(drv, list);
-        drv->ops->destroy(drv);
+        tpm_backend_destroy(drv);
     }
 }
 
diff --git a/tpm/tpm_int.h b/tpm/tpm_int.h
index f705643..b4787ad 100644
--- a/tpm/tpm_int.h
+++ b/tpm/tpm_int.h
@@ -18,22 +18,6 @@
 struct TPMDriverOps;
 typedef struct TPMDriverOps TPMDriverOps;
 
-typedef struct TPMPassthruState TPMPassthruState;
-
-typedef struct TPMBackend {
-    char *id;
-    enum TpmModel fe_model;
-    char *path;
-    char *cancel_path;
-    const TPMDriverOps *ops;
-
-    union {
-        TPMPassthruState *tpm_pt;
-    } s;
-
-    QLIST_ENTRY(TPMBackend) list;
-} TPMBackend;
-
 /* overall state of the TPM interface */
 typedef struct TPMState {
     ISADevice busdev;
diff --git a/tpm/tpm_passthrough.c b/tpm/tpm_passthrough.c
index 24aff4d..80a48d6 100644
--- a/tpm/tpm_passthrough.c
+++ b/tpm/tpm_passthrough.c
@@ -27,6 +27,7 @@
 #include "qemu-common.h"
 #include "qapi/error.h"
 #include "qemu/sockets.h"
+#include "backends/tpm.h"
 #include "tpm_int.h"
 #include "hw/hw.h"
 #include "hw/pc.h"
@@ -43,8 +44,11 @@
     do { } while (0)
 #endif
 
-/* data structures */
+#define TYPE_TPM_PASSTHROUGH "tpm-passthrough"
+#define TPM_PASSTHROUGH(obj) \
+    OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH)
 
+/* data structures */
 typedef struct TPMPassthruThreadParams {
     TPMState *tpm_state;
 
@@ -53,6 +57,8 @@ typedef struct TPMPassthruThreadParams {
 } TPMPassthruThreadParams;
 
 struct TPMPassthruState {
+    TPMBackend parent;
+
     TPMBackendThread tbt;
 
     TPMPassthruThreadParams tpm_thread_params;
@@ -65,6 +71,8 @@ struct TPMPassthruState {
     bool had_startup_error;
 };
 
+typedef struct TPMPassthruState TPMPassthruState;
+
 #define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0"
 
 /* functions */
@@ -149,7 +157,7 @@ static void tpm_passthrough_worker_thread(gpointer data,
                                           gpointer user_data)
 {
     TPMPassthruThreadParams *thr_parms = user_data;
-    TPMPassthruState *tpm_pt = thr_parms->tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(thr_parms->tb);
     TPMBackendCmd cmd = (TPMBackendCmd)data;
 
     DPRINTF("tpm_passthrough: processing command type %d\n", cmd);
@@ -176,21 +184,21 @@ static void tpm_passthrough_worker_thread(gpointer data,
  */
 static int tpm_passthrough_startup_tpm(TPMBackend *tb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
     /* terminate a running TPM */
     tpm_backend_thread_end(&tpm_pt->tbt);
 
     tpm_backend_thread_create(&tpm_pt->tbt,
                               tpm_passthrough_worker_thread,
-                              &tb->s.tpm_pt->tpm_thread_params);
+                              &tpm_pt->tpm_thread_params);
 
     return 0;
 }
 
 static void tpm_passthrough_reset(TPMBackend *tb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
     DPRINTF("tpm_passthrough: CALL TO TPM_RESET!\n");
 
@@ -204,7 +212,7 @@ static void tpm_passthrough_reset(TPMBackend *tb)
 static int tpm_passthrough_init(TPMBackend *tb, TPMState *s,
                                 TPMRecvDataCB *recv_data_cb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
     tpm_pt->tpm_thread_params.tpm_state = s;
     tpm_pt->tpm_thread_params.recv_data_callback = recv_data_cb;
@@ -220,7 +228,7 @@ static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb)
 
 static bool tpm_passthrough_get_startup_error(TPMBackend *tb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
     return tpm_pt->had_startup_error;
 }
@@ -238,14 +246,14 @@ static size_t tpm_passthrough_realloc_buffer(TPMSizedBuffer *sb)
 
 static void tpm_passthrough_deliver_request(TPMBackend *tb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
     tpm_backend_thread_deliver_request(&tpm_pt->tbt);
 }
 
 static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
     int n;
 
     /*
@@ -412,6 +420,7 @@ static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
 
 static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
 {
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
     const char *value;
 
     value = qemu_opt_get(opts, "cancel-path");
@@ -424,45 +433,45 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
         value = TPM_PASSTHROUGH_DEFAULT_DEVICE;
     }
 
-    tb->s.tpm_pt->tpm_dev = g_strdup(value);
+    tpm_pt->tpm_dev = g_strdup(value);
 
-    tb->path = g_strdup(tb->s.tpm_pt->tpm_dev);
+    tb->path = g_strdup(tpm_pt->tpm_dev);
 
-    tb->s.tpm_pt->tpm_fd = qemu_open(tb->s.tpm_pt->tpm_dev, O_RDWR);
-    if (tb->s.tpm_pt->tpm_fd < 0) {
+    tpm_pt->tpm_fd = qemu_open(tpm_pt->tpm_dev, O_RDWR);
+    if (tpm_pt->tpm_fd < 0) {
         error_report("Cannot access TPM device using '%s': %s\n",
-                     tb->s.tpm_pt->tpm_dev, strerror(errno));
+                     tpm_pt->tpm_dev, strerror(errno));
         goto err_free_parameters;
     }
 
-    if (tpm_passthrough_test_tpmdev(tb->s.tpm_pt->tpm_fd)) {
+    if (tpm_passthrough_test_tpmdev(tpm_pt->tpm_fd)) {
         error_report("'%s' is not a TPM device.\n",
-                     tb->s.tpm_pt->tpm_dev);
+                     tpm_pt->tpm_dev);
         goto err_close_tpmdev;
     }
 
     return 0;
 
  err_close_tpmdev:
-    qemu_close(tb->s.tpm_pt->tpm_fd);
-    tb->s.tpm_pt->tpm_fd = -1;
+    qemu_close(tpm_pt->tpm_fd);
+    tpm_pt->tpm_fd = -1;
 
  err_free_parameters:
     g_free(tb->path);
     tb->path = NULL;
 
-    g_free(tb->s.tpm_pt->tpm_dev);
-    tb->s.tpm_pt->tpm_dev = NULL;
+    g_free(tpm_pt->tpm_dev);
+    tpm_pt->tpm_dev = NULL;
 
     return 1;
 }
 
 static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
 {
-    TPMBackend *tb;
+    Object *obj = object_new(TYPE_TPM_PASSTHROUGH);
+    TPMBackend *tb = TPM_BACKEND(obj);
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
-    tb = g_new0(TPMBackend, 1);
-    tb->s.tpm_pt = g_new0(TPMPassthruState, 1);
     tb->id = g_strdup(id);
     /* let frontend set the fe_model to proper value */
     tb->fe_model = -1;
@@ -473,8 +482,8 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
         goto err_exit;
     }
 
-    tb->s.tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb);
-    if (tb->s.tpm_pt->cancel_fd < 0) {
+    tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb);
+    if (tpm_pt->cancel_fd < 0) {
         goto err_exit;
     }
 
@@ -482,29 +491,25 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
 
 err_exit:
     g_free(tb->id);
-    g_free(tb->s.tpm_pt);
-    g_free(tb);
 
     return NULL;
 }
 
 static void tpm_passthrough_destroy(TPMBackend *tb)
 {
-    TPMPassthruState *tpm_pt = tb->s.tpm_pt;
+    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
     tpm_passthrough_cancel_cmd(tb);
 
     tpm_backend_thread_end(&tpm_pt->tbt);
 
     qemu_close(tpm_pt->tpm_fd);
-    qemu_close(tb->s.tpm_pt->cancel_fd);
+    qemu_close(tpm_pt->cancel_fd);
 
     g_free(tb->id);
     g_free(tb->path);
     g_free(tb->cancel_path);
-    g_free(tb->s.tpm_pt->tpm_dev);
-    g_free(tb->s.tpm_pt);
-    g_free(tb);
+    g_free(tpm_pt->tpm_dev);
 }
 
 const TPMDriverOps tpm_passthrough_driver = {
@@ -522,8 +527,33 @@ const TPMDriverOps tpm_passthrough_driver = {
     .get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
 };
 
+static void tpm_passthrough_inst_init(Object *obj)
+{
+}
+
+static void tpm_passthrough_inst_finalize(Object *obj)
+{
+}
+
+static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
+{
+    TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
+
+    tbc->ops = &tpm_passthrough_driver;
+}
+
+static const TypeInfo tpm_passthrough_info = {
+    .name = TYPE_TPM_PASSTHROUGH,
+    .parent = TYPE_TPM_BACKEND,
+    .instance_size = sizeof(TPMPassthruState),
+    .class_init = tpm_passthrough_class_init,
+    .instance_init = tpm_passthrough_inst_init,
+    .instance_finalize = tpm_passthrough_inst_finalize,
+};
+
 static void tpm_passthrough_register(void)
 {
+    type_register_static(&tpm_passthrough_info);
     tpm_register_driver(&tpm_passthrough_driver);
 }
 
diff --git a/tpm/tpm_tis.c b/tpm/tpm_tis.c
index e93825e..367f734 100644
--- a/tpm/tpm_tis.c
+++ b/tpm/tpm_tis.c
@@ -19,6 +19,7 @@
  * specification.
  */
 
+#include "backends/tpm.h"
 #include "tpm_int.h"
 #include "block/block.h"
 #include "exec/address-spaces.h"
@@ -160,7 +161,7 @@ static void tpm_tis_tpm_send(TPMState *s, uint8_t locty)
      */
     tis->loc[locty].state = TPM_TIS_STATE_EXECUTION;
 
-    s->be_driver->ops->deliver_request(s->be_driver);
+    tpm_backend_deliver_request(s->be_driver);
 }
 
 /* raise an interrupt if allowed */
@@ -284,7 +285,7 @@ static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
              * request the backend to cancel. Some backends may not
              * support it
              */
-            s->be_driver->ops->cancel_cmd(s->be_driver);
+            tpm_backend_cancel_cmd(s->be_driver);
             return;
         }
     }
@@ -426,7 +427,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
     uint8_t locty = tpm_tis_locality_from_addr(addr);
     uint32_t avail;
 
-    if (s->be_driver->ops->had_startup_error(s->be_driver)) {
+    if (tpm_backend_had_startup_error(s->be_driver)) {
         return val;
     }
 
@@ -438,7 +439,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
         if (tpm_tis_check_request_use_except(s, locty)) {
             val |= TPM_TIS_ACCESS_PENDING_REQUEST;
         }
-        val |= !s->be_driver->ops->get_tpm_established_flag(s->be_driver);
+        val |= !tpm_backend_get_tpm_established_flag(s->be_driver);
         break;
     case TPM_TIS_REG_INT_ENABLE:
         val = tis->loc[locty].inte;
@@ -529,7 +530,7 @@ static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
         return;
     }
 
-    if (s->be_driver->ops->had_startup_error(s->be_driver)) {
+    if (tpm_backend_had_startup_error(s->be_driver)) {
         return;
     }
 
@@ -804,7 +805,7 @@ static const MemoryRegionOps tpm_tis_memory_ops = {
 
 static int tpm_tis_do_startup_tpm(TPMState *s)
 {
-    return s->be_driver->ops->startup_tpm(s->be_driver);
+    return tpm_backend_startup_tpm(s->be_driver);
 }
 
 /*
@@ -817,7 +818,7 @@ static void tpm_tis_reset(DeviceState *dev)
     TPMTISEmuState *tis = &s->s.tis;
     int c;
 
-    s->be_driver->ops->reset(s->be_driver);
+    tpm_backend_reset(s->be_driver);
 
     tis->active_locty = TPM_TIS_NO_LOCALITY;
     tis->next_locty = TPM_TIS_NO_LOCALITY;
@@ -831,9 +832,9 @@ static void tpm_tis_reset(DeviceState *dev)
         tis->loc[c].state = TPM_TIS_STATE_IDLE;
 
         tis->loc[c].w_offset = 0;
-        s->be_driver->ops->realloc_buffer(&tis->loc[c].w_buffer);
+        tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].w_buffer);
         tis->loc[c].r_offset = 0;
-        s->be_driver->ops->realloc_buffer(&tis->loc[c].r_buffer);
+        tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].r_buffer);
     }
 
     tpm_tis_do_startup_tpm(s);
@@ -865,7 +866,7 @@ static void tpm_tis_realizefn(DeviceState *dev, Error **errp)
 
     s->be_driver->fe_model = TPM_MODEL_TPM_TIS;
 
-    if (s->be_driver->ops->init(s->be_driver, s, tpm_tis_receive_cb)) {
+    if (tpm_backend_init(s->be_driver, s, tpm_tis_receive_cb)) {
         error_setg(errp, "tpm_tis: backend driver with id %s could not be "
                    "initialized", s->backend);
         return;
commit 684a096eafbe37ab6c9a1fdb5e0185f04098b166
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Fri Mar 29 11:39:50 2013 -0500

    qemu-char: rewrite io_channel_send_all and drop the '_all' suffix
    
    The current code is oddly written and have equally odd semantics.
    Despite the '_all' suffix, upon EAGAIN the result will be a partial
    write but instead of returning the partial write, we return EAGAIN.
    
    Change the behavior to write as much as we can until we get an EAGAIN
    returning a partial write if we do.
    
    Reported-by: Amit Shah <amit.shah at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364575190-731-1-git-send-email-aliguori at us.ibm.com

diff --git a/qemu-char.c b/qemu-char.c
index dee623e..7acbf53 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -727,33 +727,37 @@ static GIOChannel *io_channel_from_socket(int fd)
     return chan;
 }
 
-static int io_channel_send_all(GIOChannel *fd, const void *_buf, int len1)
+static int io_channel_send(GIOChannel *fd, const void *buf, size_t len)
 {
     GIOStatus status;
-    gsize bytes_written;
-    int len;
-    const uint8_t *buf = _buf;
+    size_t offset;
 
-    len = len1;
-    while (len > 0) {
-        status = g_io_channel_write_chars(fd, (const gchar *)buf, len,
+    offset = 0;
+    while (offset < len) {
+        gsize bytes_written;
+
+        status = g_io_channel_write_chars(fd, buf + offset, len - offset,
                                           &bytes_written, NULL);
         if (status != G_IO_STATUS_NORMAL) {
             if (status == G_IO_STATUS_AGAIN) {
+                /* If we've written any data, return a partial write. */
+                if (offset) {
+                    break;
+                }
                 errno = EAGAIN;
-                return -1;
             } else {
                 errno = EINVAL;
-                return -1;
             }
+
+            return -1;
         } else if (status == G_IO_STATUS_EOF) {
             break;
-        } else {
-            buf += bytes_written;
-            len -= bytes_written;
         }
+
+        offset += bytes_written;
     }
-    return len1 - len;
+
+    return offset;
 }
 
 #ifndef _WIN32
@@ -770,7 +774,7 @@ static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     FDCharDriver *s = chr->opaque;
     
-    return io_channel_send_all(s->fd_out, buf, len);
+    return io_channel_send(s->fd_out, buf, len);
 }
 
 static gboolean fd_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque)
@@ -1088,7 +1092,7 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
         pty_chr_update_read_handler(chr);
         return 0;
     }
-    return io_channel_send_all(s->fd, buf, len);
+    return io_channel_send(s->fd, buf, len);
 }
 
 static GSource *pty_chr_add_watch(CharDriverState *chr, GIOCondition cond)
@@ -2347,7 +2351,7 @@ static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     TCPCharDriver *s = chr->opaque;
     if (s->connected) {
-        return io_channel_send_all(s->chan, buf, len);
+        return io_channel_send(s->chan, buf, len);
     } else {
         /* XXX: indicate an error ? */
         return len;
commit d819cdccffe08f6e12b4c2dec8f4aa381f0cd687
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sat Mar 30 15:21:40 2013 +0100

    ui/gtk: Set QEMU window icon
    
    The QEMU icon which is already used for SDL
    is now also loaded by GTK.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Message-id: 1364653300-26813-1-git-send-email-sw at weilnetz.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/gtk.c b/ui/gtk.c
index 9692c56..1a6bee6 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1363,6 +1363,7 @@ static const DisplayChangeListenerOps dcl_ops = {
 void gtk_display_init(DisplayState *ds)
 {
     GtkDisplayState *s = g_malloc0(sizeof(*s));
+    char *filename;
 
     gtk_init(NULL, NULL);
 
@@ -1394,6 +1395,18 @@ void gtk_display_init(DisplayState *ds)
 
     gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook), s->drawing_area, gtk_label_new("VGA"));
 
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "qemu-icon.bmp");
+    if (filename) {
+        GError *error = NULL;
+        GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(filename, &error);
+        if (pixbuf) {
+            gtk_window_set_icon(GTK_WINDOW(s->window), pixbuf);
+        } else {
+            g_error_free(error);
+        }
+        g_free(filename);
+    }
+
     gd_create_menus(s);
 
     gd_connect_signals(s);
commit 77cfd14c9f5742136e7968aee5c305e50b8891ac
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Apr 1 19:12:06 2013 +0200

    po: add French translation
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364836326-8707-6-git-send-email-aurelien at aurel32.net
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/po/fr_FR.po b/po/fr_FR.po
new file mode 100644
index 0000000..27d8636
--- /dev/null
+++ b/po/fr_FR.po
@@ -0,0 +1,62 @@
+# French translation for QEMU.
+# This file is put in the public domain.
+#
+# Aurelien Jarno <aurelien at aurel32.net>, 2013.
+msgid ""
+msgstr ""
+"Project-Id-Version: QEMU 1.4.50\n"
+"Report-Msgid-Bugs-To: qemu-devel at nongnu.org\n"
+"POT-Creation-Date: 2013-03-31 20:42+0200\n"
+"PO-Revision-Date: 2013-03-31 19:39+0200\n"
+"Last-Translator: Aurelien Jarno <aurelien at aurel32.net>\n"
+"Language-Team: French <FR at li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 1.4\n"
+
+#: ../ui/gtk.c:213
+msgid " - Press Ctrl+Alt+G to release grab"
+msgstr "- Appuyer sur Ctrl+Alt+G pour arrêter la capture"
+
+#: ../ui/gtk.c:217
+msgid " [Paused]"
+msgstr " [En pause]"
+
+#: ../ui/gtk.c:1250
+msgid "_Machine"
+msgstr "_Machine"
+
+#: ../ui/gtk.c:1252
+msgid "_Pause"
+msgstr "_Pause"
+
+#: ../ui/gtk.c:1258
+msgid "_Reset"
+msgstr "_Réinitialiser"
+
+#: ../ui/gtk.c:1261
+msgid "Power _Down"
+msgstr "_Éteindre"
+
+#: ../ui/gtk.c:1276
+msgid "_View"
+msgstr "_Vue"
+
+#: ../ui/gtk.c:1306
+msgid "Zoom To _Fit"
+msgstr "Zoomer pour _ajuster"
+
+#: ../ui/gtk.c:1312
+msgid "Grab On _Hover"
+msgstr "Capturer en _survolant"
+
+#: ../ui/gtk.c:1315
+msgid "_Grab Input"
+msgstr "_Capturer les entrées"
+
+#: ../ui/gtk.c:1341
+msgid "Show _Tabs"
+msgstr "Montrer les _onglets"
commit 9b6926e4e3cc102fb434fd16917a1044119eadd3
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Apr 1 19:12:05 2013 +0200

    po: update existing translation files
    
    Cc: Paolo Bonzini <pbonzini at redhat.com>
    Cc: Kevin Wolf <kwolf at redhat.com>
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364836326-8707-5-git-send-email-aurelien at aurel32.net
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/po/de_DE.po b/po/de_DE.po
index 8755783..2566674 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: QEMU 1.4.50\n"
 "Report-Msgid-Bugs-To: qemu-devel at nongnu.org\n"
-"POT-Creation-Date: 2013-02-08 09:21-0600\n"
+"POT-Creation-Date: 2013-03-31 20:42+0200\n"
 "PO-Revision-Date: 2012-02-28 16:00+0100\n"
 "Last-Translator: Kevin Wolf <kwolf at redhat.com>\n"
 "Language-Team: Deutsch <de at li.org>\n"
@@ -16,26 +16,49 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n!=1);\n"
 
-#: ../ui/gtk.c:990
-msgid "_File"
-msgstr "_Datei"
+#: ../ui/gtk.c:213
+msgid " - Press Ctrl+Alt+G to release grab"
+msgstr ""
+
+#: ../ui/gtk.c:217
+msgid " [Paused]"
+msgstr ""
+
+#: ../ui/gtk.c:1250
+msgid "_Machine"
+msgstr ""
+
+#: ../ui/gtk.c:1252
+msgid "_Pause"
+msgstr ""
+
+#: ../ui/gtk.c:1258
+msgid "_Reset"
+msgstr ""
 
-#: ../ui/gtk.c:1000
+#: ../ui/gtk.c:1261
+msgid "Power _Down"
+msgstr ""
+
+#: ../ui/gtk.c:1276
 msgid "_View"
 msgstr "_Ansicht"
 
-#: ../ui/gtk.c:1029
+#: ../ui/gtk.c:1306
 msgid "Zoom To _Fit"
 msgstr "Auf _Fenstergröße skalieren"
 
-#: ../ui/gtk.c:1035
+#: ../ui/gtk.c:1312
 msgid "Grab On _Hover"
 msgstr "Tastatur _automatisch einfangen"
 
-#: ../ui/gtk.c:1038
+#: ../ui/gtk.c:1315
 msgid "_Grab Input"
 msgstr "_Eingabegeräte einfangen"
 
-#: ../ui/gtk.c:1064
+#: ../ui/gtk.c:1341
 msgid "Show _Tabs"
 msgstr "_Tableiste anzeigen"
+
+#~ msgid "_File"
+#~ msgstr "_Datei"
diff --git a/po/it.po b/po/it.po
index 7d77fff..2ace3b0 100644
--- a/po/it.po
+++ b/po/it.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: QEMU 1.4.50\n"
 "Report-Msgid-Bugs-To: qemu-devel at nongnu.org\n"
-"POT-Creation-Date: 2013-02-08 09:21-0600\n"
+"POT-Creation-Date: 2013-03-31 20:42+0200\n"
 "PO-Revision-Date: 2012-02-27 08:23+0100\n"
 "Last-Translator: Paolo Bonzini <pbonzini at redhat.com>\n"
 "Language-Team: Italian <it at li.org>\n"
@@ -16,26 +16,49 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
 
-#: ../ui/gtk.c:990
-msgid "_File"
-msgstr "_File"
+#: ../ui/gtk.c:213
+msgid " - Press Ctrl+Alt+G to release grab"
+msgstr ""
+
+#: ../ui/gtk.c:217
+msgid " [Paused]"
+msgstr ""
+
+#: ../ui/gtk.c:1250
+msgid "_Machine"
+msgstr ""
+
+#: ../ui/gtk.c:1252
+msgid "_Pause"
+msgstr ""
+
+#: ../ui/gtk.c:1258
+msgid "_Reset"
+msgstr ""
 
-#: ../ui/gtk.c:1000
+#: ../ui/gtk.c:1261
+msgid "Power _Down"
+msgstr ""
+
+#: ../ui/gtk.c:1276
 msgid "_View"
 msgstr "_Visualizza"
 
-#: ../ui/gtk.c:1029
+#: ../ui/gtk.c:1306
 msgid "Zoom To _Fit"
 msgstr "Adatta alla _finestra"
 
-#: ../ui/gtk.c:1035
+#: ../ui/gtk.c:1312
 msgid "Grab On _Hover"
 msgstr "Cattura _automatica input"
 
-#: ../ui/gtk.c:1038
+#: ../ui/gtk.c:1315
 msgid "_Grab Input"
 msgstr "_Cattura input"
 
-#: ../ui/gtk.c:1064
+#: ../ui/gtk.c:1341
 msgid "Show _Tabs"
 msgstr "Mostra _tab"
+
+#~ msgid "_File"
+#~ msgstr "_File"
diff --git a/po/messages.po b/po/messages.po
index 191e81c..42a3eac 100644
--- a/po/messages.po
+++ b/po/messages.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: QEMU 1.4.50\n"
 "Report-Msgid-Bugs-To: qemu-devel at nongnu.org\n"
-"POT-Creation-Date: 2013-02-08 09:21-0600\n"
+"POT-Creation-Date: 2013-03-31 20:42+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
 "Language-Team: LANGUAGE <LL at li.org>\n"
@@ -16,26 +16,46 @@ msgstr ""
 "Content-Type: text/plain; charset=CHARSET\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../ui/gtk.c:990
-msgid "_File"
+#: ../ui/gtk.c:213
+msgid " - Press Ctrl+Alt+G to release grab"
 msgstr ""
 
-#: ../ui/gtk.c:1000
+#: ../ui/gtk.c:217
+msgid " [Paused]"
+msgstr ""
+
+#: ../ui/gtk.c:1250
+msgid "_Machine"
+msgstr ""
+
+#: ../ui/gtk.c:1252
+msgid "_Pause"
+msgstr ""
+
+#: ../ui/gtk.c:1258
+msgid "_Reset"
+msgstr ""
+
+#: ../ui/gtk.c:1261
+msgid "Power _Down"
+msgstr ""
+
+#: ../ui/gtk.c:1276
 msgid "_View"
 msgstr ""
 
-#: ../ui/gtk.c:1029
+#: ../ui/gtk.c:1306
 msgid "Zoom To _Fit"
 msgstr ""
 
-#: ../ui/gtk.c:1035
+#: ../ui/gtk.c:1312
 msgid "Grab On _Hover"
 msgstr ""
 
-#: ../ui/gtk.c:1038
+#: ../ui/gtk.c:1315
 msgid "_Grab Input"
 msgstr ""
 
-#: ../ui/gtk.c:1064
+#: ../ui/gtk.c:1341
 msgid "Show _Tabs"
 msgstr ""
commit 1b33b354b43c8a3cc176bd4d7a021a1eac423ebc
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Apr 1 19:12:04 2013 +0200

    po/Makefile: correctly pass QEMU version
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364836326-8707-4-git-send-email-aurelien at aurel32.net
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/po/Makefile b/po/Makefile
index 2c0193e..8297ab5 100644
--- a/po/Makefile
+++ b/po/Makefile
@@ -34,7 +34,7 @@ install: $(OBJS)
 	@msgfmt -o $@ $(SRC_PATH)/po/`basename $@ .mo`.po
 
 messages.po: $(SRC_PATH)/ui/gtk.c
-	@xgettext -o $@ --foreign-user --package-name=QEMU --package-version=1.0.50 --msgid-bugs-address=qemu-devel at nongnu.org -k_ -C $<
+	@xgettext -o $@ --foreign-user --package-name=QEMU --package-version=$(VERSION) --msgid-bugs-address=qemu-devel at nongnu.org -k_ -C $<
 
 %.po: messages.po
 	@msgmerge $@ $< > $@.bak && mv $@.bak $@
commit f84756554e32d97db3aa949db1dd58c7eea62375
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Apr 1 19:12:03 2013 +0200

    po/Makefile: simplify
    
    In the hope we get more translations, we should not have to modify
    po/Makefile for each of them.
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364836326-8707-3-git-send-email-aurelien at aurel32.net
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/po/Makefile b/po/Makefile
index 2b4420f..2c0193e 100644
--- a/po/Makefile
+++ b/po/Makefile
@@ -2,9 +2,8 @@
 # process and also within the source tree to update the translation files.
 
 VERSION=$(shell cat ../VERSION)
-TRANSLATIONS=de_DE it
-SRCS=$(addsuffix .po, $(TRANSLATIONS))
-OBJS=$(addsuffix .mo, $(TRANSLATIONS))
+SRCS=$(filter-out messages.po,$(wildcard *.po))
+OBJS=$(patsubst %.po,%.mo,$(SRCS))
 
 SRC_PATH=..
 
@@ -37,10 +36,7 @@ install: $(OBJS)
 messages.po: $(SRC_PATH)/ui/gtk.c
 	@xgettext -o $@ --foreign-user --package-name=QEMU --package-version=1.0.50 --msgid-bugs-address=qemu-devel at nongnu.org -k_ -C $<
 
-de_DE.po: messages.po $(SRC_PATH)/ui/gtk.c
+%.po: messages.po
 	@msgmerge $@ $< > $@.bak && mv $@.bak $@
 
-it.po: messages.po $(SRC_PATH)/ui/gtk.c
-	@msgmerge $@ $< > $@.bak && mv $@.bak $@
-
-.PHONY: $(SRCS) clean all
+.PHONY: clean all
commit d8da9ee847799b8d7de4679d4de17d66d4dedb56
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Apr 1 19:12:02 2013 +0200

    gtk: make more messages translatable
    
    Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1364836326-8707-2-git-send-email-aurelien at aurel32.net
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/gtk.c b/ui/gtk.c
index a5a8156..9692c56 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -210,11 +210,11 @@ static void gd_update_caption(GtkDisplayState *s)
     bool is_paused = !runstate_is_running();
 
     if (gd_is_grab_active(s)) {
-        grab = " - Press Ctrl+Alt+G to release grab";
+        grab = _(" - Press Ctrl+Alt+G to release grab");
     }
 
     if (is_paused) {
-        status = " [Paused]";
+        status = _(" [Paused]");
     }
     s->external_pause_update = true;
     gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->pause_item),
commit 4690579e9bafa0a2a49d7b12dae905279a552cd6
Author: Amos Kong <akong at redhat.com>
Date:   Wed Mar 20 18:16:34 2013 +0800

    append the terminating '\0' to bootorder string
    
    Problem was introduced in commit c8a6ae8b. The last terminating
    '\0' was lost, use the right length 5 ("HALT\0").
    
    Reported-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: Amos Kong <akong at redhat.com>
    Message-id: 1363774594-21001-1-git-send-email-akong at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/vl.c b/vl.c
index 52eacca..e2c9706 100644
--- a/vl.c
+++ b/vl.c
@@ -1278,9 +1278,9 @@ char *get_boot_devices_list(size_t *size)
 
     if (boot_strict && *size > 0) {
         list[total-1] = '\n';
-        list = g_realloc(list, total + 4);
-        memcpy(&list[total], "HALT", 4);
-        *size = total + 4;
+        list = g_realloc(list, total + 5);
+        memcpy(&list[total], "HALT", 5);
+        *size = total + 5;
     }
     return list;
 }
commit a130c6b2b1b9c45836a51e90c847baedcb3125d3
Merge: 5d45de9 6dcfdba
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 2 08:12:16 2013 -0500

    Merge remote-tracking branch 'awilliam/tags/vfio-pci-for-qemu-20130401.0' into staging
    
    vfio-pci pull request 20130401
    
    # gpg: Signature made Mon 01 Apr 2013 02:40:45 PM CDT using RSA key ID 3BB08B22
    # gpg: Can't check signature: public key not found
    
    # By Alex Williamson
    # Via Alex Williamson
    * awilliam/tags/vfio-pci-for-qemu-20130401.0:
      vfio: cleanup includes
      vfio: Add bootindex support
      vfio-pci: Move devices to D0 on reset
      vfio-pci: Add extra debugging
      qemu vfio-pci: Graphics device quirks
      qemu vfio-pci: Add support for VGA MMIO and I/O port access
      vfio-pci: Add PCIe capability mangling based on bus type
      vfio-pci: Generalize PCI config mangling
      linux-headers: Update to v3.9-rc2

commit 5d45de9796539f95eb6b1201588362981f8cb2d4
Author: Edgar E. Iglesias <edgar.iglesias at xilinx.com>
Date:   Thu Mar 28 22:59:03 2013 +0100

    microblaze: Add support for the sleep insn
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at xilinx.com>

diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index a74da8e..06d2346 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1317,6 +1317,23 @@ static void dec_br(DisasContext *dc)
     /* Memory barrier.  */
     mbar = (dc->ir >> 16) & 31;
     if (mbar == 2 && dc->imm == 4) {
+        /* mbar IMM & 16 decodes to sleep.  */
+        if (dc->rd & 16) {
+            TCGv_i32 tmp_hlt = tcg_const_i32(EXCP_HLT);
+            TCGv_i32 tmp_1 = tcg_const_i32(1);
+
+            LOG_DIS("sleep\n");
+
+            t_sync_flags(dc);
+            tcg_gen_st_i32(tmp_1, cpu_env,
+                           -offsetof(MicroBlazeCPU, env)
+                           +offsetof(CPUState, halted));
+            tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc + 4);
+            gen_helper_raise_exception(cpu_env, tmp_hlt);
+            tcg_temp_free_i32(tmp_hlt);
+            tcg_temp_free_i32(tmp_1);
+            return;
+        }
         LOG_DIS("mbar %d\n", dc->rd);
         /* Break the TB.  */
         dc->cpustate_changed = 1;
commit 6dcfdbad69aa510bc87b4a2585a597e028ca4eaa
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 13:35:40 2013 -0600

    vfio: cleanup includes
    
    Starting to get messy, put the back in alphabetical order.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index 0d2a445..693a9ff 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -19,26 +19,26 @@
  */
 
 #include <dirent.h>
-#include <unistd.h>
+#include <linux/vfio.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <linux/vfio.h>
+#include <unistd.h>
 
 #include "config.h"
-#include "qemu/event_notifier.h"
 #include "exec/address-spaces.h"
-#include "sysemu/kvm.h"
-#include "sysemu/sysemu.h"
 #include "exec/memory.h"
 #include "hw/pci/msi.h"
 #include "hw/pci/msix.h"
 #include "hw/pci/pci.h"
 #include "qemu-common.h"
 #include "qemu/error-report.h"
+#include "qemu/event_notifier.h"
 #include "qemu/queue.h"
 #include "qemu/range.h"
+#include "sysemu/kvm.h"
+#include "sysemu/sysemu.h"
 
 /* #define DEBUG_VFIO */
 #ifdef DEBUG_VFIO
commit c29029dd8829827ef8af3a6fb18f9df929ffc6b7
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 13:35:24 2013 -0600

    vfio: Add bootindex support
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index d310730..0d2a445 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -30,6 +30,7 @@
 #include "qemu/event_notifier.h"
 #include "exec/address-spaces.h"
 #include "sysemu/kvm.h"
+#include "sysemu/sysemu.h"
 #include "exec/memory.h"
 #include "hw/pci/msi.h"
 #include "hw/pci/msix.h"
@@ -160,6 +161,7 @@ typedef struct VFIODevice {
     uint32_t features;
 #define VFIO_FEATURE_ENABLE_VGA_BIT 0
 #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT)
+    int32_t bootindex;
     uint8_t pm_cap;
     bool reset_works;
     bool has_vga;
@@ -3070,6 +3072,8 @@ static int vfio_initfn(PCIDevice *pdev)
         }
     }
 
+    add_boot_device_path(vdev->bootindex, &pdev->qdev, NULL);
+
     return 0;
 
 out_teardown:
@@ -3157,6 +3161,7 @@ static Property vfio_pci_dev_properties[] = {
                        intx.mmap_timeout, 1100),
     DEFINE_PROP_BIT("x-vga", VFIODevice, features,
                     VFIO_FEATURE_ENABLE_VGA_BIT, false),
+    DEFINE_PROP_INT32("bootindex", VFIODevice, bootindex, -1),
     /*
      * TODO - support passed fds... is this necessary?
      * DEFINE_PROP_STRING("vfiofd", VFIODevice, vfiofd_name),
commit ba66181828a5e5b0bbc117c4e999ca559a87456e
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 13:35:08 2013 -0600

    vfio-pci: Move devices to D0 on reset
    
    Guests may leave devices in a low power state at reboot, but we expect
    devices to be woken up for the next boot.  Make this happen.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index b913ec0..d310730 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -160,6 +160,7 @@ typedef struct VFIODevice {
     uint32_t features;
 #define VFIO_FEATURE_ENABLE_VGA_BIT 0
 #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT)
+    uint8_t pm_cap;
     bool reset_works;
     bool has_vga;
 } VFIODevice;
@@ -2534,6 +2535,8 @@ static int vfio_add_std_cap(VFIODevice *vdev, uint8_t pos)
     case PCI_CAP_ID_MSIX:
         ret = vfio_setup_msix(vdev, pos);
         break;
+    case PCI_CAP_ID_PM:
+        vdev->pm_cap = pos;
     default:
         ret = pci_add_capability(pdev, cap_id, pos, size);
         break;
@@ -3108,6 +3111,26 @@ static void vfio_pci_reset(DeviceState *dev)
 
     vfio_disable_interrupts(vdev);
 
+    /* Make sure the device is in D0 */
+    if (vdev->pm_cap) {
+        uint16_t pmcsr;
+        uint8_t state;
+
+        pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2);
+        state = pmcsr & PCI_PM_CTRL_STATE_MASK;
+        if (state) {
+            pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+            vfio_pci_write_config(pdev, vdev->pm_cap + PCI_PM_CTRL, pmcsr, 2);
+            /* vfio handles the necessary delay here */
+            pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2);
+            state = pmcsr & PCI_PM_CTRL_STATE_MASK;
+            if (state) {
+                error_report("vfio: Unable to power on device, stuck in D%d\n",
+                             state);
+            }
+        }
+    }
+
     /*
      * Stop any ongoing DMA by disconecting I/O, MMIO, and bus master.
      * Also put INTx Disable in known state.
commit 82ca891283a08cddd659b534592fe00f2159bc74
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 13:34:56 2013 -0600

    vfio-pci: Add extra debugging
    
    Often when debugging it's useful to be able to disable bypass paths
    so no interactions with the device are missed.  Add some extra debug
    options to do this.  Also add device info on read/write BAR accesses,
    which is useful when debugging more than one assigned device.  A
    couple DPRINTFs also had redundant "vfio:" prefixes.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index e96f141..b913ec0 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -48,6 +48,10 @@
     do { } while (0)
 #endif
 
+/* Extra debugging, trap acceleration paths for more logging */
+#define VFIO_ALLOW_MMAP 1
+#define VFIO_ALLOW_KVM_INTX 1
+
 struct VFIODevice;
 
 typedef struct VFIOQuirk {
@@ -305,7 +309,7 @@ static void vfio_enable_intx_kvm(VFIODevice *vdev)
     int ret, argsz;
     int32_t *pfd;
 
-    if (!kvm_irqfds_enabled() ||
+    if (!VFIO_ALLOW_KVM_INTX || !kvm_irqfds_enabled() ||
         vdev->intx.route.mode != PCI_INTX_ENABLED ||
         !kvm_check_extension(kvm_state, KVM_CAP_IRQFD_RESAMPLE)) {
         return;
@@ -925,8 +929,16 @@ static void vfio_bar_write(void *opaque, hwaddr addr,
                      __func__, addr, data, size);
     }
 
-    DPRINTF("%s(BAR%d+0x%"HWADDR_PRIx", 0x%"PRIx64", %d)\n",
-            __func__, bar->nr, addr, data, size);
+#ifdef DEBUG_VFIO
+    {
+        VFIODevice *vdev = container_of(bar, VFIODevice, bars[bar->nr]);
+
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx", 0x%"PRIx64
+                ", %d)\n", __func__, vdev->host.domain, vdev->host.bus,
+                vdev->host.slot, vdev->host.function, bar->nr, addr,
+                data, size);
+    }
+#endif
 
     /*
      * A read or write to a BAR always signals an INTx EOI.  This will
@@ -972,8 +984,16 @@ static uint64_t vfio_bar_read(void *opaque,
         break;
     }
 
-    DPRINTF("%s(BAR%d+0x%"HWADDR_PRIx", %d) = 0x%"PRIx64"\n",
-            __func__, bar->nr, addr, size, data);
+#ifdef DEBUG_VFIO
+    {
+        VFIODevice *vdev = container_of(bar, VFIODevice, bars[bar->nr]);
+
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx
+                ", %d) = 0x%"PRIx64"\n", __func__, vdev->host.domain,
+                vdev->host.bus, vdev->host.slot, vdev->host.function,
+                bar->nr, addr, size, data);
+    }
+#endif
 
     /* Same as write above */
     vfio_eoi(container_of(bar, VFIODevice, bars[bar->nr]));
@@ -1917,7 +1937,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
     int ret;
 
     if (vfio_listener_skipped_section(section)) {
-        DPRINTF("vfio: SKIPPING region_add %"HWADDR_PRIx" - %"PRIx64"\n",
+        DPRINTF("SKIPPING region_add %"HWADDR_PRIx" - %"PRIx64"\n",
                 section->offset_within_address_space,
                 section->offset_within_address_space + section->size - 1);
         return;
@@ -1941,7 +1961,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
             section->offset_within_region +
             (iova - section->offset_within_address_space);
 
-    DPRINTF("vfio: region_add %"HWADDR_PRIx" - %"HWADDR_PRIx" [%p]\n",
+    DPRINTF("region_add %"HWADDR_PRIx" - %"HWADDR_PRIx" [%p]\n",
             iova, end - 1, vaddr);
 
     ret = vfio_dma_map(container, iova, end - iova, vaddr, section->readonly);
@@ -1961,7 +1981,7 @@ static void vfio_listener_region_del(MemoryListener *listener,
     int ret;
 
     if (vfio_listener_skipped_section(section)) {
-        DPRINTF("vfio: SKIPPING region_del %"HWADDR_PRIx" - %"PRIx64"\n",
+        DPRINTF("SKIPPING region_del %"HWADDR_PRIx" - %"PRIx64"\n",
                 section->offset_within_address_space,
                 section->offset_within_address_space + section->size - 1);
         return;
@@ -1981,7 +2001,7 @@ static void vfio_listener_region_del(MemoryListener *listener,
         return;
     }
 
-    DPRINTF("vfio: region_del %"HWADDR_PRIx" - %"HWADDR_PRIx"\n",
+    DPRINTF("region_del %"HWADDR_PRIx" - %"HWADDR_PRIx"\n",
             iova, end - 1);
 
     ret = vfio_dma_unmap(container, iova, end - iova);
@@ -2184,7 +2204,7 @@ static int vfio_mmap_bar(VFIOBAR *bar, MemoryRegion *mem, MemoryRegion *submem,
 {
     int ret = 0;
 
-    if (size && bar->flags & VFIO_REGION_INFO_FLAG_MMAP) {
+    if (VFIO_ALLOW_MMAP && size && bar->flags & VFIO_REGION_INFO_FLAG_MMAP) {
         int prot = 0;
 
         if (bar->flags & VFIO_REGION_INFO_FLAG_READ) {
commit 7076eabcbf38d514ecd47c8190d3d162573ceacc
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 13:34:40 2013 -0600

    qemu vfio-pci: Graphics device quirks
    
    Graphics cards have a number of different backdoors.  Some of these
    are alternative ways to get PCI BAR addresses, some of them are
    complete mirrors of PCI config space available through MMIO and
    I/O port access.  These quirks cover a number of ATI Radeon and
    Nvidia devices.  On the ATI/AMD side, this should enable HD5450
    and HD7850 and hopefully a host of devices around those generations.
    For Nvidia, my card selection is much more dated.  A 8400gs works
    well with both the Window shipped driver and the Nvidia downloaded
    driver.  A 7300le works as well, with the caveat that generating
    the Window experience index with the Nvidia driver causes the card
    to reset several times before generating a BSOD.  An NVS 290 card
    seems to run well with the shipped Windows driver, but generates
    a BSOD with the Nvidia driver.  All of the Nvidia devices work with
    the Linux Nvidia proprietary driver and nouveau, the HD5450 works
    with either radeon or fglrx, HD7850 works with vesa and fglrx (not
    supported by radeon).  Extremely limited 3D testing.
    
    Device reset is also an issue with graphics.  It's unfortunately
    very common that the devices offer no means to reset the card or
    doesn't seem effective.  Nvidia devices are pretty good about being
    able to get the device to a working state through the VGA BIOS init,
    Radeon devices less so, and often require a host reboot.  Work
    remains to be done here.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index ff415a6..e96f141 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -48,6 +48,16 @@
     do { } while (0)
 #endif
 
+struct VFIODevice;
+
+typedef struct VFIOQuirk {
+    MemoryRegion mem;
+    struct VFIODevice *vdev;
+    QLIST_ENTRY(VFIOQuirk) next;
+    uint32_t data;
+    uint32_t data2;
+} VFIOQuirk;
+
 typedef struct VFIOBAR {
     off_t fd_offset; /* offset of BAR within device fd */
     int fd; /* device fd, allows us to pass VFIOBAR as opaque data */
@@ -57,12 +67,14 @@ typedef struct VFIOBAR {
     size_t size;
     uint32_t flags; /* VFIO region flags (rd/wr/mmap) */
     uint8_t nr; /* cache the BAR number for debug */
+    QLIST_HEAD(, VFIOQuirk) quirks;
 } VFIOBAR;
 
 typedef struct VFIOVGARegion {
     MemoryRegion mem;
     off_t offset;
     int nr;
+    QLIST_HEAD(, VFIOQuirk) quirks;
 } VFIOVGARegion;
 
 typedef struct VFIOVGA {
@@ -82,8 +94,6 @@ typedef struct VFIOINTx {
     QEMUTimer *mmap_timer; /* enable mmaps after periods w/o interrupts */
 } VFIOINTx;
 
-struct VFIODevice;
-
 typedef struct VFIOMSIVector {
     EventNotifier interrupt; /* eventfd triggered on interrupt */
     struct VFIODevice *vdev; /* back pointer to device */
@@ -169,6 +179,8 @@ static QLIST_HEAD(, VFIOGroup)
 
 static void vfio_disable_interrupts(VFIODevice *vdev);
 static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);
+static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
+                                  uint32_t val, int len);
 static void vfio_mmap_set_enabled(VFIODevice *vdev, bool enabled);
 
 /*
@@ -1059,6 +1071,700 @@ static const MemoryRegionOps vfio_vga_ops = {
 };
 
 /*
+ * Device specific quirks
+ */
+
+#define PCI_VENDOR_ID_ATI               0x1002
+
+/*
+ * Device 1002:68f9 (Advanced Micro Devices [AMD] nee ATI Cedar PRO [Radeon
+ * HD 5450/6350]) reports the upper byte of the physical address of the
+ * I/O port BAR4 through VGA register 0x3c3.  The BAR is 256 bytes, so the
+ * lower byte is known to be zero.  Probing for this quirk reads 0xff from
+ * port 0x3c3 on some devices so we store the physical address and replace
+ * reads with the virtual address any time it matches.  XXX Research when
+ * to enable quirk.
+ */
+static uint64_t vfio_ati_3c3_quirk_read(void *opaque,
+                                        hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    PCIDevice *pdev = &vdev->pdev;
+    uint64_t data = vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI],
+                                  addr + 0x3, size);
+
+    if (data == quirk->data) {
+        data = pci_get_byte(pdev->config + PCI_BASE_ADDRESS_4 + 1);
+        DPRINTF("%s(0x3c3, 1) = 0x%"PRIx64"\n", __func__, data);
+    }
+
+    return data;
+}
+
+static const MemoryRegionOps vfio_ati_3c3_quirk = {
+    .read = vfio_ati_3c3_quirk_read,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_vga_probe_ati_3c3_quirk(VFIODevice *vdev)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    off_t physoffset = vdev->config_offset + PCI_BASE_ADDRESS_4;
+    uint32_t physbar;
+    VFIOQuirk *quirk;
+
+    if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI ||
+        vdev->bars[4].size < 256) {
+        return;
+    }
+
+    /* Get I/O port BAR physical address */
+    if (pread(vdev->fd, &physbar, 4, physoffset) != 4) {
+        error_report("vfio: probe failed for ATI/AMD 0x3c3 quirk on device "
+                     "%04x:%02x:%02x.%x", vdev->host.domain,
+                     vdev->host.bus, vdev->host.slot, vdev->host.function);
+        return;
+    }
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+    quirk->data = (physbar >> 8) & 0xff;
+
+    memory_region_init_io(&quirk->mem, &vfio_ati_3c3_quirk, quirk,
+                          "vfio-ati-3c3-quirk", 1);
+    memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, 3,
+                                &quirk->mem);
+
+    QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks,
+                      quirk, next);
+
+    DPRINTF("Enabled ATI/AMD quirk 0x3c3 for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+/*
+ * Device 1002:68f9 (Advanced Micro Devices [AMD] nee ATI Cedar PRO [Radeon
+ * HD 5450/6350]) reports the physical address of MMIO BAR0 through a
+ * write/read operation on I/O port BAR4.  When uint32_t 0x4010 is written
+ * to offset 0x0, the subsequent read from offset 0x4 returns the contents
+ * of BAR0.  Test for this quirk on all ATI/AMD devices.  XXX - Note that
+ * 0x10 is the offset of BAR0 in config sapce, is this a window to all of
+ * config space?
+ */
+static uint64_t vfio_ati_4010_quirk_read(void *opaque,
+                                         hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    PCIDevice *pdev = &vdev->pdev;
+    uint64_t data = vfio_bar_read(&vdev->bars[4], addr, size);
+
+    if (addr == 4 && size == 4 && quirk->data) {
+        data = pci_get_long(pdev->config + PCI_BASE_ADDRESS_0);
+        DPRINTF("%s(BAR4+0x4) = 0x%"PRIx64"\n", __func__, data);
+    }
+
+    quirk->data = 0;
+
+    return data;
+}
+
+static void vfio_ati_4010_quirk_write(void *opaque, hwaddr addr,
+                                      uint64_t data, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+
+    vfio_bar_write(&vdev->bars[4], addr, data, size);
+
+    quirk->data = (addr == 0 && size == 4 && data == 0x4010) ? 1 : 0;
+}
+
+static const MemoryRegionOps vfio_ati_4010_quirk = {
+    .read = vfio_ati_4010_quirk_read,
+    .write = vfio_ati_4010_quirk_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_probe_ati_4010_quirk(VFIODevice *vdev, int nr)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    off_t physoffset = vdev->config_offset + PCI_BASE_ADDRESS_0;
+    uint32_t physbar0;
+    uint64_t data;
+    VFIOQuirk *quirk;
+
+    if (!vdev->has_vga || nr != 4 || !vdev->bars[0].size ||
+        pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) {
+        return;
+    }
+
+    /* Get I/O port BAR physical address */
+    if (pread(vdev->fd, &physbar0, 4, physoffset) != 4) {
+        error_report("vfio: probe failed for ATI/AMD 0x4010 quirk on device "
+                     "%04x:%02x:%02x.%x", vdev->host.domain,
+                     vdev->host.bus, vdev->host.slot, vdev->host.function);
+        return;
+    }
+
+    /* Write 0x4010 to I/O port BAR offset 0 */
+    vfio_bar_write(&vdev->bars[4], 0, 0x4010, 4);
+    /* Read back result */
+    data = vfio_bar_read(&vdev->bars[4], 4, 4);
+
+    /* If the register matches the physical address of BAR0, we need a quirk */
+    if (data != physbar0) {
+        return;
+    }
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+
+    memory_region_init_io(&quirk->mem, &vfio_ati_4010_quirk, quirk,
+                          "vfio-ati-4010-quirk", 8);
+    memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1);
+
+    QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
+
+    DPRINTF("Enabled ATI/AMD quirk 0x4010 for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+/*
+ * Device 1002:5b63 (Advanced Micro Devices [AMD] nee ATI RV370 [Radeon X550])
+ * retrieves the upper half of the MMIO BAR0 physical address by writing
+ * 0xf10 to I/O port BAR1 offset 0 and reading the result from offset 6.
+ * XXX - 0x10 is the offset of BAR0 in PCI config space, this could provide
+ * full access to config space.  Config space is little endian, so the data
+ * register probably starts at 0x4.
+ */
+static uint64_t vfio_ati_f10_quirk_read(void *opaque,
+                                        hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    PCIDevice *pdev = &vdev->pdev;
+    uint64_t data = vfio_bar_read(&vdev->bars[1], addr, size);
+
+    if (addr == 6 && size == 2 && quirk->data) {
+        data = pci_get_word(pdev->config + PCI_BASE_ADDRESS_0 + 2);
+        DPRINTF("%s(BAR1+0x6) = 0x%"PRIx64"\n", __func__, data);
+    }
+
+    quirk->data = 0;
+
+    return data;
+}
+
+static void vfio_ati_f10_quirk_write(void *opaque, hwaddr addr,
+                                     uint64_t data, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+
+    vfio_bar_write(&vdev->bars[1], addr, data, size);
+
+    quirk->data = (addr == 0 && size == 4 && data == 0xf10) ? 1 : 0;
+}
+
+static const MemoryRegionOps vfio_ati_f10_quirk = {
+    .read = vfio_ati_f10_quirk_read,
+    .write = vfio_ati_f10_quirk_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_probe_ati_f10_quirk(VFIODevice *vdev, int nr)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    off_t physoffset = vdev->config_offset + PCI_BASE_ADDRESS_0;
+    uint32_t physbar0;
+    uint64_t data;
+    VFIOQuirk *quirk;
+
+    if (!vdev->has_vga || nr != 1 || !vdev->bars[0].size ||
+        pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) {
+        return;
+    }
+
+    /* Get I/O port BAR physical address */
+    if (pread(vdev->fd, &physbar0, 4, physoffset) != 4) {
+        error_report("vfio: probe failed for ATI/AMD 0xf10 quirk on device "
+                     "%04x:%02x:%02x.%x", vdev->host.domain,
+                     vdev->host.bus, vdev->host.slot, vdev->host.function);
+        return;
+    }
+
+    vfio_bar_write(&vdev->bars[1], 0, 0xf10, 4);
+    data = vfio_bar_read(&vdev->bars[1], 0x6, 2);
+
+    /* If the register matches the physical address of BAR0, we need a quirk */
+    if (data != (le32_to_cpu(physbar0) >> 16)) {
+        return;
+    }
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+
+    memory_region_init_io(&quirk->mem, &vfio_ati_f10_quirk, quirk,
+                          "vfio-ati-f10-quirk", 8);
+    memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1);
+
+    QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
+
+    DPRINTF("Enabled ATI/AMD quirk 0xf10 for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+#define PCI_VENDOR_ID_NVIDIA                    0x10de
+
+/*
+ * Nvidia has several different methods to get to config space, the
+ * nouveu project has several of these documented here:
+ * https://github.com/pathscale/envytools/tree/master/hwdocs
+ *
+ * The first quirk is actually not documented in envytools and is found
+ * on 10de:01d1 (NVIDIA Corporation G72 [GeForce 7300 LE]).  This is an
+ * NV46 chipset.  The backdoor uses the legacy VGA I/O ports to access
+ * the mirror of PCI config space found at BAR0 offset 0x1800.  The access
+ * sequence first writes 0x338 to I/O port 0x3d4.  The target offset is
+ * then written to 0x3d0.  Finally 0x538 is written for a read and 0x738
+ * is written for a write to 0x3d4.  The BAR0 offset is then accessible
+ * through 0x3d0.  This quirk doesn't seem to be necessary on newer cards
+ * that use the I/O port BAR5 window but it doesn't hurt to leave it.
+ */
+enum {
+    NV_3D0_NONE,
+    NV_3D0_SELECT,
+    NV_3D0_WINDOW,
+    NV_3D0_READ,
+    NV_3D0_WRITE,
+};
+
+static uint64_t vfio_nvidia_3d0_quirk_read(void *opaque,
+                                           hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    PCIDevice *pdev = &vdev->pdev;
+    uint64_t data = vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI],
+                                  addr + 0x10, size);
+
+    if (quirk->data == NV_3D0_READ && addr == 0) {
+        data = vfio_pci_read_config(pdev, quirk->data2, size);
+        DPRINTF("%s(0x3d0, %d) = 0x%"PRIx64"\n", __func__, size, data);
+    }
+
+    quirk->data = NV_3D0_NONE;
+
+    return data;
+}
+
+static void vfio_nvidia_3d0_quirk_write(void *opaque, hwaddr addr,
+                                        uint64_t data, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    PCIDevice *pdev = &vdev->pdev;
+
+    switch (quirk->data) {
+    case NV_3D0_NONE:
+        if (addr == 4 && data == 0x338) {
+            quirk->data = NV_3D0_SELECT;
+        }
+        break;
+    case NV_3D0_SELECT:
+        quirk->data = NV_3D0_NONE;
+        if (addr == 0 && (data & ~0xff) == 0x1800) {
+            quirk->data = NV_3D0_WINDOW;
+            quirk->data2 = data & 0xff;
+        }
+        break;
+    case NV_3D0_WINDOW:
+        quirk->data = NV_3D0_NONE;
+        if (addr == 4) {
+            if (data == 0x538) {
+                quirk->data = NV_3D0_READ;
+            } else if (data == 0x738) {
+                quirk->data = NV_3D0_WRITE;
+            }
+        }
+        break;
+    case NV_3D0_WRITE:
+        quirk->data = NV_3D0_NONE;
+        if (addr == 0) {
+            vfio_pci_write_config(pdev, quirk->data2, data, size);
+            DPRINTF("%s(0x3d0, 0x%"PRIx64", %d)\n", __func__, data, size);
+            return;
+        }
+        break;
+    default:
+        quirk->data = NV_3D0_NONE;
+    }
+
+    vfio_vga_write(&vdev->vga.region[QEMU_PCI_VGA_IO_HI],
+                   addr + 0x10, data, size);
+}
+
+static const MemoryRegionOps vfio_nvidia_3d0_quirk = {
+    .read = vfio_nvidia_3d0_quirk_read,
+    .write = vfio_nvidia_3d0_quirk_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_vga_probe_nvidia_3d0_quirk(VFIODevice *vdev)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    VFIOQuirk *quirk;
+
+    if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA ||
+        !vdev->bars[1].size) {
+        return;
+    }
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+
+    memory_region_init_io(&quirk->mem, &vfio_nvidia_3d0_quirk, quirk,
+                          "vfio-nvidia-3d0-quirk", 6);
+    memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem,
+                                0x10, &quirk->mem);
+
+    QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks,
+                      quirk, next);
+
+    DPRINTF("Enabled NVIDIA VGA 0x3d0 quirk for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+/*
+ * The second quirk is documented in envytools.  The I/O port BAR5 is just
+ * a set of address/data ports to the MMIO BARs.  The BAR we care about is
+ * again BAR0.  This backdoor is apparently a bit newer than the one above
+ * so we need to not only trap 256 bytes @0x1800, but all of PCI config
+ * space, including extended space is available at the 4k @0x88000.
+ */
+enum {
+    NV_BAR5_ADDRESS = 0x1,
+    NV_BAR5_ENABLE = 0x2,
+    NV_BAR5_MASTER = 0x4,
+    NV_BAR5_VALID = 0x7,
+};
+
+static uint64_t vfio_nvidia_bar5_window_quirk_read(void *opaque,
+                                                   hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    uint64_t data = vfio_bar_read(&vdev->bars[5], addr, size);
+
+    if (addr == 0xc && quirk->data == NV_BAR5_VALID) {
+        data = vfio_pci_read_config(&vdev->pdev, quirk->data2, size);
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR5+0x%"HWADDR_PRIx", %d) = 0x%"
+                PRIx64"\n", __func__, vdev->host.domain, vdev->host.bus,
+                vdev->host.slot, vdev->host.function, addr, size, data);
+    }
+
+    return data;
+}
+
+static void vfio_nvidia_bar5_window_quirk_write(void *opaque, hwaddr addr,
+                                                uint64_t data, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+
+    /*
+     * Use quirk->data to track enables and quirk->data2 for the offset
+     */
+    switch (addr) {
+    case 0x0:
+        if (data & 0x1) {
+            quirk->data |= NV_BAR5_MASTER;
+        } else {
+            quirk->data &= ~NV_BAR5_MASTER;
+        }
+        break;
+    case 0x4:
+        if (data & 0x1) {
+            quirk->data |= NV_BAR5_ENABLE;
+        } else {
+            quirk->data &= ~NV_BAR5_ENABLE;
+        }
+        break;
+    case 0x8:
+        if (quirk->data & NV_BAR5_MASTER) {
+            if ((data & ~0xfff) == 0x88000) {
+                quirk->data |= NV_BAR5_ADDRESS;
+                quirk->data2 = data & 0xfff;
+            } else if ((data & ~0xff) == 0x1800) {
+                quirk->data |= NV_BAR5_ADDRESS;
+                quirk->data2 = data & 0xff;
+            } else {
+                quirk->data &= ~NV_BAR5_ADDRESS;
+            }
+        }
+        break;
+    case 0xc:
+        if (quirk->data == NV_BAR5_VALID) {
+            vfio_pci_write_config(&vdev->pdev, quirk->data2, data, size);
+            DPRINTF("%s(%04x:%02x:%02x.%x:BAR5+0x%"HWADDR_PRIx", 0x%"
+                    PRIx64", %d)\n", __func__, vdev->host.domain,
+                    vdev->host.bus, vdev->host.slot, vdev->host.function,
+                    addr, data, size);
+            return;
+        }
+    }
+
+    vfio_bar_write(&vdev->bars[5], addr, data, size);
+}
+
+static const MemoryRegionOps vfio_nvidia_bar5_window_quirk = {
+    .read = vfio_nvidia_bar5_window_quirk_read,
+    .write = vfio_nvidia_bar5_window_quirk_write,
+    .valid.min_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_probe_nvidia_bar5_window_quirk(VFIODevice *vdev, int nr)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    VFIOQuirk *quirk;
+
+    if (!vdev->has_vga || nr != 5 ||
+        pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA) {
+        return;
+    }
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+
+    memory_region_init_io(&quirk->mem, &vfio_nvidia_bar5_window_quirk, quirk,
+                          "vfio-nvidia-bar5-window-quirk", 16);
+    memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1);
+
+    QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
+
+    DPRINTF("Enabled NVIDIA BAR5 window quirk for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+/*
+ * Finally, BAR0 itself.  We want to redirect any accesses to either
+ * 0x1800 or 0x88000 through the PCI config space access functions.
+ *
+ * NB - quirk at a page granularity or else they don't seem to work when
+ *      BARs are mmap'd
+ *
+ * Here's offset 0x88000...
+ */
+static uint64_t vfio_nvidia_bar0_88000_quirk_read(void *opaque,
+                                                  hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    hwaddr base = 0x88000 & TARGET_PAGE_MASK;
+    hwaddr offset = 0x88000 & ~TARGET_PAGE_MASK;
+    uint64_t data = vfio_bar_read(&vdev->bars[0], addr + base, size);
+
+    if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) {
+        data = vfio_pci_read_config(&vdev->pdev, addr - offset, size);
+
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", %d) = 0x%"
+                PRIx64"\n", __func__, vdev->host.domain, vdev->host.bus,
+                vdev->host.slot, vdev->host.function, addr + base, size, data);
+    }
+
+    return data;
+}
+
+static void vfio_nvidia_bar0_88000_quirk_write(void *opaque, hwaddr addr,
+                                               uint64_t data, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    hwaddr base = 0x88000 & TARGET_PAGE_MASK;
+    hwaddr offset = 0x88000 & ~TARGET_PAGE_MASK;
+
+    if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) {
+        vfio_pci_write_config(&vdev->pdev, addr - offset, data, size);
+
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", 0x%"
+                PRIx64", %d)\n", __func__, vdev->host.domain, vdev->host.bus,
+                vdev->host.slot, vdev->host.function, addr + base, data, size);
+    } else {
+        vfio_bar_write(&vdev->bars[0], addr + base, data, size);
+    }
+}
+
+static const MemoryRegionOps vfio_nvidia_bar0_88000_quirk = {
+    .read = vfio_nvidia_bar0_88000_quirk_read,
+    .write = vfio_nvidia_bar0_88000_quirk_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_probe_nvidia_bar0_88000_quirk(VFIODevice *vdev, int nr)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    VFIOQuirk *quirk;
+
+    if (!vdev->has_vga || nr != 0 ||
+        pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA) {
+        return;
+    }
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+
+    memory_region_init_io(&quirk->mem, &vfio_nvidia_bar0_88000_quirk, quirk,
+                          "vfio-nvidia-bar0-88000-quirk",
+                          TARGET_PAGE_ALIGN(PCIE_CONFIG_SPACE_SIZE));
+    memory_region_add_subregion_overlap(&vdev->bars[nr].mem,
+                                        0x88000 & TARGET_PAGE_MASK,
+                                        &quirk->mem, 1);
+
+    QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
+
+    DPRINTF("Enabled NVIDIA BAR0 0x88000 quirk for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+/*
+ * And here's the same for BAR0 offset 0x1800...
+ */
+static uint64_t vfio_nvidia_bar0_1800_quirk_read(void *opaque,
+                                                 hwaddr addr, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    hwaddr base = 0x1800 & TARGET_PAGE_MASK;
+    hwaddr offset = 0x1800 & ~TARGET_PAGE_MASK;
+    uint64_t data = vfio_bar_read(&vdev->bars[0], addr + base, size);
+
+    if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) {
+        data = vfio_pci_read_config(&vdev->pdev, addr - offset, size);
+
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", %d) = 0x%"
+                PRIx64"\n", __func__, vdev->host.domain, vdev->host.bus,
+                vdev->host.slot, vdev->host.function, addr + base, size, data);
+    }
+
+    return data;
+}
+
+static void vfio_nvidia_bar0_1800_quirk_write(void *opaque, hwaddr addr,
+                                              uint64_t data, unsigned size)
+{
+    VFIOQuirk *quirk = opaque;
+    VFIODevice *vdev = quirk->vdev;
+    hwaddr base = 0x1800 & TARGET_PAGE_MASK;
+    hwaddr offset = 0x1800 & ~TARGET_PAGE_MASK;
+
+    if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) {
+        vfio_pci_write_config(&vdev->pdev, addr - offset, data, size);
+
+        DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", 0x%"
+                PRIx64", %d)\n", __func__, vdev->host.domain, vdev->host.bus,
+                vdev->host.slot, vdev->host.function, addr + base, data, size);
+    } else {
+        vfio_bar_write(&vdev->bars[0], addr + base, data, size);
+    }
+}
+
+static const MemoryRegionOps vfio_nvidia_bar0_1800_quirk = {
+    .read = vfio_nvidia_bar0_1800_quirk_read,
+    .write = vfio_nvidia_bar0_1800_quirk_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void vfio_probe_nvidia_bar0_1800_quirk(VFIODevice *vdev, int nr)
+{
+    PCIDevice *pdev = &vdev->pdev;
+    VFIOQuirk *quirk;
+
+    if (!vdev->has_vga || nr != 0 ||
+        pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA) {
+        return;
+    }
+
+    /* Log the chipset ID */
+    DPRINTF("Nvidia NV%02x\n",
+            (unsigned int)(vfio_bar_read(&vdev->bars[0], 0, 4) >> 20) & 0xff);
+
+    quirk = g_malloc0(sizeof(*quirk));
+    quirk->vdev = vdev;
+
+    memory_region_init_io(&quirk->mem, &vfio_nvidia_bar0_1800_quirk, quirk,
+                          "vfio-nvidia-bar0-1800-quirk",
+                          TARGET_PAGE_ALIGN(PCI_CONFIG_SPACE_SIZE));
+    memory_region_add_subregion_overlap(&vdev->bars[nr].mem,
+                                        0x1800 & TARGET_PAGE_MASK,
+                                        &quirk->mem, 1);
+
+    QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
+
+    DPRINTF("Enabled NVIDIA BAR0 0x1800 quirk for device %04x:%02x:%02x.%x\n",
+            vdev->host.domain, vdev->host.bus, vdev->host.slot,
+            vdev->host.function);
+}
+
+/*
+ * TODO - Some Nvidia devices provide config access to their companion HDA
+ * device and even to their parent bridge via these config space mirrors.
+ * Add quirks for those regions.
+ */
+
+/*
+ * Common quirk probe entry points.
+ */
+static void vfio_vga_quirk_setup(VFIODevice *vdev)
+{
+    vfio_vga_probe_ati_3c3_quirk(vdev);
+    vfio_vga_probe_nvidia_3d0_quirk(vdev);
+}
+
+static void vfio_vga_quirk_teardown(VFIODevice *vdev)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) {
+        while (!QLIST_EMPTY(&vdev->vga.region[i].quirks)) {
+            VFIOQuirk *quirk = QLIST_FIRST(&vdev->vga.region[i].quirks);
+            memory_region_del_subregion(&vdev->vga.region[i].mem, &quirk->mem);
+            QLIST_REMOVE(quirk, next);
+            g_free(quirk);
+        }
+    }
+}
+
+static void vfio_bar_quirk_setup(VFIODevice *vdev, int nr)
+{
+    vfio_probe_ati_4010_quirk(vdev, nr);
+    vfio_probe_ati_f10_quirk(vdev, nr);
+    vfio_probe_nvidia_bar5_window_quirk(vdev, nr);
+    vfio_probe_nvidia_bar0_88000_quirk(vdev, nr);
+    vfio_probe_nvidia_bar0_1800_quirk(vdev, nr);
+}
+
+static void vfio_bar_quirk_teardown(VFIODevice *vdev, int nr)
+{
+    VFIOBAR *bar = &vdev->bars[nr];
+
+    while (!QLIST_EMPTY(&bar->quirks)) {
+        VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks);
+        memory_region_del_subregion(&bar->mem, &quirk->mem);
+        QLIST_REMOVE(quirk, next);
+        g_free(quirk);
+    }
+}
+
+/*
  * PCI config space
  */
 static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len)
@@ -1459,6 +2165,8 @@ static void vfio_unmap_bar(VFIODevice *vdev, int nr)
         return;
     }
 
+    vfio_bar_quirk_teardown(vdev, nr);
+
     memory_region_del_subregion(&bar->mem, &bar->mmap_mem);
     munmap(bar->mmap, memory_region_size(&bar->mmap_mem));
 
@@ -1569,6 +2277,8 @@ static void vfio_map_bar(VFIODevice *vdev, int nr)
             error_report("%s unsupported. Performance may be slow", name);
         }
     }
+
+    vfio_bar_quirk_setup(vdev, nr);
 }
 
 static void vfio_map_bars(VFIODevice *vdev)
@@ -1599,6 +2309,7 @@ static void vfio_map_bars(VFIODevice *vdev)
         pci_register_vga(&vdev->pdev, &vdev->vga.region[QEMU_PCI_VGA_MEM].mem,
                          &vdev->vga.region[QEMU_PCI_VGA_IO_LO].mem,
                          &vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem);
+        vfio_vga_quirk_setup(vdev);
     }
 }
 
@@ -1611,6 +2322,7 @@ static void vfio_unmap_bars(VFIODevice *vdev)
     }
 
     if (vdev->has_vga) {
+        vfio_vga_quirk_teardown(vdev);
         pci_unregister_vga(&vdev->pdev);
         memory_region_destroy(&vdev->vga.region[QEMU_PCI_VGA_MEM].mem);
         memory_region_destroy(&vdev->vga.region[QEMU_PCI_VGA_IO_LO].mem);
@@ -2104,6 +2816,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev)
         vdev->bars[i].fd_offset = reg_info.offset;
         vdev->bars[i].fd = vdev->fd;
         vdev->bars[i].nr = i;
+        QLIST_INIT(&vdev->bars[i].quirks);
     }
 
     reg_info.index = VFIO_PCI_ROM_REGION_INDEX;
@@ -2169,12 +2882,15 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev)
 
         vdev->vga.region[QEMU_PCI_VGA_MEM].offset = QEMU_PCI_VGA_MEM_BASE;
         vdev->vga.region[QEMU_PCI_VGA_MEM].nr = QEMU_PCI_VGA_MEM;
+        QLIST_INIT(&vdev->vga.region[QEMU_PCI_VGA_MEM].quirks);
 
         vdev->vga.region[QEMU_PCI_VGA_IO_LO].offset = QEMU_PCI_VGA_IO_LO_BASE;
         vdev->vga.region[QEMU_PCI_VGA_IO_LO].nr = QEMU_PCI_VGA_IO_LO;
+        QLIST_INIT(&vdev->vga.region[QEMU_PCI_VGA_IO_LO].quirks);
 
         vdev->vga.region[QEMU_PCI_VGA_IO_HI].offset = QEMU_PCI_VGA_IO_HI_BASE;
         vdev->vga.region[QEMU_PCI_VGA_IO_HI].nr = QEMU_PCI_VGA_IO_HI;
+        QLIST_INIT(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks);
 
         vdev->has_vga = true;
     }
commit f15689c7e4422d5453ae45628df5b83a53e518ed
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 13:33:44 2013 -0600

    qemu vfio-pci: Add support for VGA MMIO and I/O port access
    
    Most VGA cards need some kind of quirk to fully operate since they
    hide backdoors to get to other registers outside of PCI config space
    within the registers, but this provides the base infrastructure.  If
    we could identity map PCI resources for assigned devices we would need
    a lot fewer quirks.
    
    To enable this, use a kernel side vfio-pci driver that incorporates
    VGA support (v3.9), and use the -vga none option and add the x-vga=on
    option for the vfio-pci device.  The "x-" denotes this as an
    experimental feature.  You may also need to use a cached copy of the
    VGA BIOS for your device, passing it to vfio-pci using the romfile=
    option.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index 0f74dbb..ff415a6 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -59,6 +59,18 @@ typedef struct VFIOBAR {
     uint8_t nr; /* cache the BAR number for debug */
 } VFIOBAR;
 
+typedef struct VFIOVGARegion {
+    MemoryRegion mem;
+    off_t offset;
+    int nr;
+} VFIOVGARegion;
+
+typedef struct VFIOVGA {
+    off_t fd_offset;
+    int fd;
+    VFIOVGARegion region[QEMU_PCI_VGA_NUM_REGIONS];
+} VFIOVGA;
+
 typedef struct VFIOINTx {
     bool pending; /* interrupt pending */
     bool kvm_accel; /* set when QEMU bypass through KVM enabled */
@@ -127,10 +139,15 @@ typedef struct VFIODevice {
     int nr_vectors; /* Number of MSI/MSIX vectors currently in use */
     int interrupt; /* Current interrupt type */
     VFIOBAR bars[PCI_NUM_REGIONS - 1]; /* No ROM */
+    VFIOVGA vga; /* 0xa0000, 0x3b0, 0x3c0 */
     PCIHostDeviceAddress host;
     QLIST_ENTRY(VFIODevice) next;
     struct VFIOGroup *group;
+    uint32_t features;
+#define VFIO_FEATURE_ENABLE_VGA_BIT 0
+#define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT)
     bool reset_works;
+    bool has_vga;
 } VFIODevice;
 
 typedef struct VFIOGroup {
@@ -958,6 +975,89 @@ static const MemoryRegionOps vfio_bar_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static void vfio_vga_write(void *opaque, hwaddr addr,
+                           uint64_t data, unsigned size)
+{
+    VFIOVGARegion *region = opaque;
+    VFIOVGA *vga = container_of(region, VFIOVGA, region[region->nr]);
+    union {
+        uint8_t byte;
+        uint16_t word;
+        uint32_t dword;
+        uint64_t qword;
+    } buf;
+    off_t offset = vga->fd_offset + region->offset + addr;
+
+    switch (size) {
+    case 1:
+        buf.byte = data;
+        break;
+    case 2:
+        buf.word = cpu_to_le16(data);
+        break;
+    case 4:
+        buf.dword = cpu_to_le32(data);
+        break;
+    default:
+        hw_error("vfio: unsupported write size, %d bytes\n", size);
+        break;
+    }
+
+    if (pwrite(vga->fd, &buf, size, offset) != size) {
+        error_report("%s(,0x%"HWADDR_PRIx", 0x%"PRIx64", %d) failed: %m",
+                     __func__, region->offset + addr, data, size);
+    }
+
+    DPRINTF("%s(0x%"HWADDR_PRIx", 0x%"PRIx64", %d)\n",
+            __func__, region->offset + addr, data, size);
+}
+
+static uint64_t vfio_vga_read(void *opaque, hwaddr addr, unsigned size)
+{
+    VFIOVGARegion *region = opaque;
+    VFIOVGA *vga = container_of(region, VFIOVGA, region[region->nr]);
+    union {
+        uint8_t byte;
+        uint16_t word;
+        uint32_t dword;
+        uint64_t qword;
+    } buf;
+    uint64_t data = 0;
+    off_t offset = vga->fd_offset + region->offset + addr;
+
+    if (pread(vga->fd, &buf, size, offset) != size) {
+        error_report("%s(,0x%"HWADDR_PRIx", %d) failed: %m",
+                     __func__, region->offset + addr, size);
+        return (uint64_t)-1;
+    }
+
+    switch (size) {
+    case 1:
+        data = buf.byte;
+        break;
+    case 2:
+        data = le16_to_cpu(buf.word);
+        break;
+    case 4:
+        data = le32_to_cpu(buf.dword);
+        break;
+    default:
+        hw_error("vfio: unsupported read size, %d bytes\n", size);
+        break;
+    }
+
+    DPRINTF("%s(0x%"HWADDR_PRIx", %d) = 0x%"PRIx64"\n",
+            __func__, region->offset + addr, size, data);
+
+    return data;
+}
+
+static const MemoryRegionOps vfio_vga_ops = {
+    .read = vfio_vga_read,
+    .write = vfio_vga_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 /*
  * PCI config space
  */
@@ -1478,6 +1578,28 @@ static void vfio_map_bars(VFIODevice *vdev)
     for (i = 0; i < PCI_ROM_SLOT; i++) {
         vfio_map_bar(vdev, i);
     }
+
+    if (vdev->has_vga) {
+        memory_region_init_io(&vdev->vga.region[QEMU_PCI_VGA_MEM].mem,
+                              &vfio_vga_ops,
+                              &vdev->vga.region[QEMU_PCI_VGA_MEM],
+                              "vfio-vga-mmio at 0xa0000",
+                              QEMU_PCI_VGA_MEM_SIZE);
+        memory_region_init_io(&vdev->vga.region[QEMU_PCI_VGA_IO_LO].mem,
+                              &vfio_vga_ops,
+                              &vdev->vga.region[QEMU_PCI_VGA_IO_LO],
+                              "vfio-vga-io at 0x3b0",
+                              QEMU_PCI_VGA_IO_LO_SIZE);
+        memory_region_init_io(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem,
+                              &vfio_vga_ops,
+                              &vdev->vga.region[QEMU_PCI_VGA_IO_HI],
+                              "vfio-vga-io at 0x3c0",
+                              QEMU_PCI_VGA_IO_HI_SIZE);
+
+        pci_register_vga(&vdev->pdev, &vdev->vga.region[QEMU_PCI_VGA_MEM].mem,
+                         &vdev->vga.region[QEMU_PCI_VGA_IO_LO].mem,
+                         &vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem);
+    }
 }
 
 static void vfio_unmap_bars(VFIODevice *vdev)
@@ -1487,6 +1609,13 @@ static void vfio_unmap_bars(VFIODevice *vdev)
     for (i = 0; i < PCI_ROM_SLOT; i++) {
         vfio_unmap_bar(vdev, i);
     }
+
+    if (vdev->has_vga) {
+        pci_unregister_vga(&vdev->pdev);
+        memory_region_destroy(&vdev->vga.region[QEMU_PCI_VGA_MEM].mem);
+        memory_region_destroy(&vdev->vga.region[QEMU_PCI_VGA_IO_LO].mem);
+        memory_region_destroy(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem);
+    }
 }
 
 /*
@@ -2012,6 +2141,44 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev)
     }
     vdev->config_offset = reg_info.offset;
 
+    if ((vdev->features & VFIO_FEATURE_ENABLE_VGA) &&
+        dev_info.num_regions > VFIO_PCI_VGA_REGION_INDEX) {
+        struct vfio_region_info vga_info = {
+            .argsz = sizeof(vga_info),
+            .index = VFIO_PCI_VGA_REGION_INDEX,
+         };
+
+        ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, &vga_info);
+        if (ret) {
+            error_report(
+                "vfio: Device does not support requested feature x-vga");
+            goto error;
+        }
+
+        if (!(vga_info.flags & VFIO_REGION_INFO_FLAG_READ) ||
+            !(vga_info.flags & VFIO_REGION_INFO_FLAG_WRITE) ||
+            vga_info.size < 0xbffff + 1) {
+            error_report("vfio: Unexpected VGA info, flags 0x%lx, size 0x%lx",
+                         (unsigned long)vga_info.flags,
+                         (unsigned long)vga_info.size);
+            goto error;
+        }
+
+        vdev->vga.fd_offset = vga_info.offset;
+        vdev->vga.fd = vdev->fd;
+
+        vdev->vga.region[QEMU_PCI_VGA_MEM].offset = QEMU_PCI_VGA_MEM_BASE;
+        vdev->vga.region[QEMU_PCI_VGA_MEM].nr = QEMU_PCI_VGA_MEM;
+
+        vdev->vga.region[QEMU_PCI_VGA_IO_LO].offset = QEMU_PCI_VGA_IO_LO_BASE;
+        vdev->vga.region[QEMU_PCI_VGA_IO_LO].nr = QEMU_PCI_VGA_IO_LO;
+
+        vdev->vga.region[QEMU_PCI_VGA_IO_HI].offset = QEMU_PCI_VGA_IO_HI_BASE;
+        vdev->vga.region[QEMU_PCI_VGA_IO_HI].nr = QEMU_PCI_VGA_IO_HI;
+
+        vdev->has_vga = true;
+    }
+
 error:
     if (ret) {
         QLIST_REMOVE(vdev, next);
@@ -2229,6 +2396,8 @@ static Property vfio_pci_dev_properties[] = {
     DEFINE_PROP_PCI_HOST_DEVADDR("host", VFIODevice, host),
     DEFINE_PROP_UINT32("x-intx-mmap-timeout-ms", VFIODevice,
                        intx.mmap_timeout, 1100),
+    DEFINE_PROP_BIT("x-vga", VFIODevice, features,
+                    VFIO_FEATURE_ENABLE_VGA_BIT, false),
     /*
      * TODO - support passed fds... is this necessary?
      * DEFINE_PROP_STRING("vfiofd", VFIODevice, vfiofd_name),
commit 96adc5c7c2178d02f0db2db368ba3e4aacef931a
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 11:50:04 2013 -0600

    vfio-pci: Add PCIe capability mangling based on bus type
    
    Windows seems to pay particular interest to the PCIe header type of
    devices and will fail to load drivers if we attach Endpoint devices or
    Legacy Endpoint devices to the Root Complex.  We can use
    pci_bus_is_express and pci_bus_is_root to determine the bus type and
    mangle the type appropriately:
    
    * Legacy PCI
      * No change, capability is unmodified for compatibility.
    * PCI Express
      * Integrated Root Complex Endpoint -> Endpoint
    * PCI Express Root Complex
      * Endpoint -> Integrated Root Complex Endpoint
      * Legacy Endpoint -> none, capability hidden
    
    We also take this opportunity to explicitly limit supported devices
    to Endpoints, Legacy Endpoints, and Root Complex Integrated Endpoints.
    We don't currently have support for other types and users often cause
    themselves problems by assigning them.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index a3bae7b..0f74dbb 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -1506,6 +1506,124 @@ static uint8_t vfio_std_cap_max_size(PCIDevice *pdev, uint8_t pos)
     return next - pos;
 }
 
+static void vfio_set_word_bits(uint8_t *buf, uint16_t val, uint16_t mask)
+{
+    pci_set_word(buf, (pci_get_word(buf) & ~mask) | val);
+}
+
+static void vfio_add_emulated_word(VFIODevice *vdev, int pos,
+                                   uint16_t val, uint16_t mask)
+{
+    vfio_set_word_bits(vdev->pdev.config + pos, val, mask);
+    vfio_set_word_bits(vdev->pdev.wmask + pos, ~mask, mask);
+    vfio_set_word_bits(vdev->emulated_config_bits + pos, mask, mask);
+}
+
+static void vfio_set_long_bits(uint8_t *buf, uint32_t val, uint32_t mask)
+{
+    pci_set_long(buf, (pci_get_long(buf) & ~mask) | val);
+}
+
+static void vfio_add_emulated_long(VFIODevice *vdev, int pos,
+                                   uint32_t val, uint32_t mask)
+{
+    vfio_set_long_bits(vdev->pdev.config + pos, val, mask);
+    vfio_set_long_bits(vdev->pdev.wmask + pos, ~mask, mask);
+    vfio_set_long_bits(vdev->emulated_config_bits + pos, mask, mask);
+}
+
+static int vfio_setup_pcie_cap(VFIODevice *vdev, int pos, uint8_t size)
+{
+    uint16_t flags;
+    uint8_t type;
+
+    flags = pci_get_word(vdev->pdev.config + pos + PCI_CAP_FLAGS);
+    type = (flags & PCI_EXP_FLAGS_TYPE) >> 4;
+
+    if (type != PCI_EXP_TYPE_ENDPOINT &&
+        type != PCI_EXP_TYPE_LEG_END &&
+        type != PCI_EXP_TYPE_RC_END) {
+
+        error_report("vfio: Assignment of PCIe type 0x%x "
+                     "devices is not currently supported", type);
+        return -EINVAL;
+    }
+
+    if (!pci_bus_is_express(vdev->pdev.bus)) {
+        /*
+         * Use express capability as-is on PCI bus.  It doesn't make much
+         * sense to even expose, but some drivers (ex. tg3) depend on it
+         * and guests don't seem to be particular about it.  We'll need
+         * to revist this or force express devices to express buses if we
+         * ever expose an IOMMU to the guest.
+         */
+    } else if (pci_bus_is_root(vdev->pdev.bus)) {
+        /*
+         * On a Root Complex bus Endpoints become Root Complex Integrated
+         * Endpoints, which changes the type and clears the LNK & LNK2 fields.
+         */
+        if (type == PCI_EXP_TYPE_ENDPOINT) {
+            vfio_add_emulated_word(vdev, pos + PCI_CAP_FLAGS,
+                                   PCI_EXP_TYPE_RC_END << 4,
+                                   PCI_EXP_FLAGS_TYPE);
+
+            /* Link Capabilities, Status, and Control goes away */
+            if (size > PCI_EXP_LNKCTL) {
+                vfio_add_emulated_long(vdev, pos + PCI_EXP_LNKCAP, 0, ~0);
+                vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKCTL, 0, ~0);
+                vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKSTA, 0, ~0);
+
+#ifndef PCI_EXP_LNKCAP2
+#define PCI_EXP_LNKCAP2 44
+#endif
+#ifndef PCI_EXP_LNKSTA2
+#define PCI_EXP_LNKSTA2 50
+#endif
+                /* Link 2 Capabilities, Status, and Control goes away */
+                if (size > PCI_EXP_LNKCAP2) {
+                    vfio_add_emulated_long(vdev, pos + PCI_EXP_LNKCAP2, 0, ~0);
+                    vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKCTL2, 0, ~0);
+                    vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKSTA2, 0, ~0);
+                }
+            }
+
+        } else if (type == PCI_EXP_TYPE_LEG_END) {
+            /*
+             * Legacy endpoints don't belong on the root complex.  Windows
+             * seems to be happier with devices if we skip the capability.
+             */
+            return 0;
+        }
+
+    } else {
+        /*
+         * Convert Root Complex Integrated Endpoints to regular endpoints.
+         * These devices don't support LNK/LNK2 capabilities, so make them up.
+         */
+        if (type == PCI_EXP_TYPE_RC_END) {
+            vfio_add_emulated_word(vdev, pos + PCI_CAP_FLAGS,
+                                   PCI_EXP_TYPE_ENDPOINT << 4,
+                                   PCI_EXP_FLAGS_TYPE);
+            vfio_add_emulated_long(vdev, pos + PCI_EXP_LNKCAP,
+                                   PCI_EXP_LNK_MLW_1 | PCI_EXP_LNK_LS_25, ~0);
+            vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKCTL, 0, ~0);
+        }
+
+        /* Mark the Link Status bits as emulated to allow virtual negotiation */
+        vfio_add_emulated_word(vdev, pos + PCI_EXP_LNKSTA,
+                               pci_get_word(vdev->pdev.config + pos +
+                                            PCI_EXP_LNKSTA),
+                               PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS);
+    }
+
+    pos = pci_add_capability(&vdev->pdev, PCI_CAP_ID_EXP, pos, size);
+    if (pos >= 0) {
+        vdev->pdev.exp.exp_cap = pos;
+    }
+
+    return pos;
+}
+
 static int vfio_add_std_cap(VFIODevice *vdev, uint8_t pos)
 {
     PCIDevice *pdev = &vdev->pdev;
@@ -1536,13 +1654,22 @@ static int vfio_add_std_cap(VFIODevice *vdev, uint8_t pos)
             return ret;
         }
     } else {
-        pdev->config[PCI_CAPABILITY_LIST] = 0; /* Begin the rebuild */
+        /* Begin the rebuild, use QEMU emulated list bits */
+        pdev->config[PCI_CAPABILITY_LIST] = 0;
+        vdev->emulated_config_bits[PCI_CAPABILITY_LIST] = 0xff;
+        vdev->emulated_config_bits[PCI_STATUS] |= PCI_STATUS_CAP_LIST;
     }
 
+    /* Use emulated next pointer to allow dropping caps */
+    pci_set_byte(vdev->emulated_config_bits + pos + 1, 0xff);
+
     switch (cap_id) {
     case PCI_CAP_ID_MSI:
         ret = vfio_setup_msi(vdev, pos);
         break;
+    case PCI_CAP_ID_EXP:
+        ret = vfio_setup_pcie_cap(vdev, pos, size);
+        break;
     case PCI_CAP_ID_MSIX:
         ret = vfio_setup_msix(vdev, pos);
         break;
commit 4b5d5e87c7ab2e979a2cad6c8e01bcae55b85f1c
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 11:50:04 2013 -0600

    vfio-pci: Generalize PCI config mangling
    
    Kernel-side vfio virtualizes all of config space, but some parts are
    unique to Qemu.  For instance we may or may not expose the ROM BAR,
    Qemu manages MSI/MSIX, and Qemu manages the multi-function bit so that
    single function devices can appear as multi-function and vica versa.
    Generalize this into a bitmap of Qemu emulated bits.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index 288361d..a3bae7b 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -117,6 +117,7 @@ typedef struct VFIODevice {
     int fd;
     VFIOINTx intx;
     unsigned int config_size;
+    uint8_t *emulated_config_bits; /* QEMU emulated bits, little-endian */
     off_t config_offset; /* Offset of config space region within device fd */
     unsigned int rom_size;
     off_t rom_offset; /* Offset of ROM region within device fd */
@@ -963,44 +964,29 @@ static const MemoryRegionOps vfio_bar_ops = {
 static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len)
 {
     VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev);
-    uint32_t val = 0;
+    uint32_t emu_bits = 0, emu_val = 0, phys_val = 0, val;
 
-    /*
-     * We only need QEMU PCI config support for the ROM BAR, the MSI and MSIX
-     * capabilities, and the multifunction bit below.  We let VFIO handle
-     * virtualizing everything else.  Performance is not a concern here.
-     */
-    if (ranges_overlap(addr, len, PCI_ROM_ADDRESS, 4) ||
-        (pdev->cap_present & QEMU_PCI_CAP_MSIX &&
-         ranges_overlap(addr, len, pdev->msix_cap, MSIX_CAP_LENGTH)) ||
-        (pdev->cap_present & QEMU_PCI_CAP_MSI &&
-         ranges_overlap(addr, len, pdev->msi_cap, vdev->msi_cap_size))) {
+    memcpy(&emu_bits, vdev->emulated_config_bits + addr, len);
+    emu_bits = le32_to_cpu(emu_bits);
 
-        val = pci_default_read_config(pdev, addr, len);
-    } else {
-        if (pread(vdev->fd, &val, len, vdev->config_offset + addr) != len) {
+    if (emu_bits) {
+        emu_val = pci_default_read_config(pdev, addr, len);
+    }
+
+    if (~emu_bits & (0xffffffffU >> (32 - len * 8))) {
+        ssize_t ret;
+
+        ret = pread(vdev->fd, &phys_val, len, vdev->config_offset + addr);
+        if (ret != len) {
             error_report("%s(%04x:%02x:%02x.%x, 0x%x, 0x%x) failed: %m",
                          __func__, vdev->host.domain, vdev->host.bus,
                          vdev->host.slot, vdev->host.function, addr, len);
             return -errno;
         }
-        val = le32_to_cpu(val);
+        phys_val = le32_to_cpu(phys_val);
     }
 
-    /* Multifunction bit is virualized in QEMU */
-    if (unlikely(ranges_overlap(addr, len, PCI_HEADER_TYPE, 1))) {
-        uint32_t mask = PCI_HEADER_TYPE_MULTI_FUNCTION;
-
-        if (len == 4) {
-            mask <<= 16;
-        }
-
-        if (pdev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
-            val |= mask;
-        } else {
-            val &= ~mask;
-        }
-    }
+    val = (emu_val & emu_bits) | (phys_val & ~emu_bits);
 
     DPRINTF("%s(%04x:%02x:%02x.%x, @0x%x, len=0x%x) %x\n", __func__,
             vdev->host.domain, vdev->host.bus, vdev->host.slot,
@@ -1026,12 +1012,6 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
                      vdev->host.slot, vdev->host.function, addr, val, len);
     }
 
-    /* Write standard header bits to emulation */
-    if (addr < PCI_CONFIG_HEADER_SIZE) {
-        pci_default_write_config(pdev, addr, val, len);
-        return;
-    }
-
     /* MSI/MSI-X Enabling/Disabling */
     if (pdev->cap_present & QEMU_PCI_CAP_MSI &&
         ranges_overlap(addr, len, pdev->msi_cap, vdev->msi_cap_size)) {
@@ -1046,9 +1026,7 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
         } else if (was_enabled && !is_enabled) {
             vfio_disable_msi(vdev);
         }
-    }
-
-    if (pdev->cap_present & QEMU_PCI_CAP_MSIX &&
+    } else if (pdev->cap_present & QEMU_PCI_CAP_MSIX &&
         ranges_overlap(addr, len, pdev->msix_cap, MSIX_CAP_LENGTH)) {
         int is_enabled, was_enabled = msix_enabled(pdev);
 
@@ -1061,6 +1039,9 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
         } else if (was_enabled && !is_enabled) {
             vfio_disable_msix(vdev);
         }
+    } else {
+        /* Write everything to QEMU to keep emulated bits correct */
+        pci_default_write_config(pdev, addr, val, len);
     }
 }
 
@@ -2003,6 +1984,16 @@ static int vfio_initfn(PCIDevice *pdev)
         goto out_put;
     }
 
+    /* vfio emulates a lot for us, but some bits need extra love */
+    vdev->emulated_config_bits = g_malloc0(vdev->config_size);
+
+    /* QEMU can choose to expose the ROM or not */
+    memset(vdev->emulated_config_bits + PCI_ROM_ADDRESS, 0xff, 4);
+
+    /* QEMU can change multi-function devices to single function, or reverse */
+    vdev->emulated_config_bits[PCI_HEADER_TYPE] =
+                                              PCI_HEADER_TYPE_MULTI_FUNCTION;
+
     /*
      * Clear host resource mapping info.  If we choose not to register a
      * BAR, such as might be the case with the option ROM, we can get
@@ -2025,6 +2016,17 @@ static int vfio_initfn(PCIDevice *pdev)
         goto out_teardown;
     }
 
+    /* QEMU emulates all of MSI & MSIX */
+    if (pdev->cap_present & QEMU_PCI_CAP_MSIX) {
+        memset(vdev->emulated_config_bits + pdev->msix_cap, 0xff,
+               MSIX_CAP_LENGTH);
+    }
+
+    if (pdev->cap_present & QEMU_PCI_CAP_MSI) {
+        memset(vdev->emulated_config_bits + pdev->msi_cap, 0xff,
+               vdev->msi_cap_size);
+    }
+
     if (vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1)) {
         vdev->intx.mmap_timer = qemu_new_timer_ms(vm_clock,
                                                   vfio_intx_mmap_enable, vdev);
@@ -2042,6 +2044,7 @@ out_teardown:
     vfio_teardown_msi(vdev);
     vfio_unmap_bars(vdev);
 out_put:
+    g_free(vdev->emulated_config_bits);
     vfio_put_device(vdev);
     vfio_put_group(group);
     return ret;
@@ -2059,6 +2062,7 @@ static void vfio_exitfn(PCIDevice *pdev)
     }
     vfio_teardown_msi(vdev);
     vfio_unmap_bars(vdev);
+    g_free(vdev->emulated_config_bits);
     vfio_put_device(vdev);
     vfio_put_group(group);
 }
commit 010ca0b3fb9bebd6ad53c1db0266dd7b39f700c7
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Mon Apr 1 11:50:04 2013 -0600

    linux-headers: Update to v3.9-rc2
    
    Unedited scripts/update-linux-headers.sh run against v3.9-rc2 tag
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>

diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index f787b72..e094121 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -303,6 +303,15 @@ enum {
 	VFIO_PCI_BAR5_REGION_INDEX,
 	VFIO_PCI_ROM_REGION_INDEX,
 	VFIO_PCI_CONFIG_REGION_INDEX,
+	/*
+	 * Expose VGA regions defined for PCI base class 03, subclass 00.
+	 * This includes I/O port ranges 0x3b0 to 0x3bb and 0x3c0 to 0x3df
+	 * as well as the MMIO range 0xa0000 to 0xbffff.  Each implemented
+	 * range is found at it's identity mapped offset from the region
+	 * offset, for example 0x3b0 is region_info.offset + 0x3b0.  Areas
+	 * between described ranges are unimplemented.
+	 */
+	VFIO_PCI_VGA_REGION_INDEX,
 	VFIO_PCI_NUM_REGIONS
 };
 
commit 174d4d215fb49b4d43196e62f22c2533431b260e
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sun Mar 24 01:52:07 2013 +0100

    tcg/mips: Implement muls2_i32
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index bd8c858..373c364 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -1413,6 +1413,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
 #endif
         break;
+    case INDEX_op_muls2_i32:
+        tcg_out_opc_reg(s, OPC_MULT, 0, args[2], args[3]);
+        tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
+        tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
+        break;
     case INDEX_op_mulu2_i32:
         tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
@@ -1595,6 +1600,7 @@ static const TCGTargetOpDef mips_op_defs[] = {
 
     { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
     { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
+    { INDEX_op_muls2_i32, { "r", "r", "rZ", "rZ" } },
     { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
     { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
     { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 0384bd3..6155327 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -87,7 +87,7 @@ typedef enum {
 #define TCG_TARGET_HAS_orc_i32          0
 #define TCG_TARGET_HAS_eqv_i32          0
 #define TCG_TARGET_HAS_nand_i32         0
-#define TCG_TARGET_HAS_muls2_i32        0
+#define TCG_TARGET_HAS_muls2_i32        1
 
 /* optional instructions only implemented on MIPS4, MIPS32 and Loongson 2 */
 #if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \
commit c334a3880c02d1d8299ed54057e3fffd99ad2048
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:02 2013 +0100

    target-i386: SSE4.2: use clz32/ctz32 instead of reinventing the wheel
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c
index 44f3d27..29a8fb6 100644
--- a/target-i386/fpu_helper.c
+++ b/target-i386/fpu_helper.c
@@ -20,6 +20,7 @@
 #include <math.h>
 #include "cpu.h"
 #include "helper.h"
+#include "qemu/host-utils.h"
 
 #if !defined(CONFIG_USER_ONLY)
 #include "exec/softmmu_exec.h"
diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index a0bac07..a11dba1 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2064,34 +2064,6 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s,
     return res;
 }
 
-static inline int rffs1(unsigned int val)
-{
-    int ret = 1, hi;
-
-    for (hi = sizeof(val) * 4; hi; hi /= 2) {
-        if (val >> hi) {
-            val >>= hi;
-            ret += hi;
-        }
-    }
-
-    return ret;
-}
-
-static inline int ffs1(unsigned int val)
-{
-    int ret = 1, hi;
-
-    for (hi = sizeof(val) * 4; hi; hi /= 2) {
-        if (val << hi) {
-            val <<= hi;
-            ret += hi;
-        }
-    }
-
-    return ret;
-}
-
 void glue(helper_pcmpestri, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
                                     uint32_t ctrl)
 {
@@ -2100,7 +2072,7 @@ void glue(helper_pcmpestri, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
                                  pcmp_elen(env, R_EAX, ctrl));
 
     if (res) {
-        env->regs[R_ECX] = (ctrl & (1 << 6)) ? rffs1(res) - 1 : 32 - ffs1(res);
+        env->regs[R_ECX] = (ctrl & (1 << 6)) ? 31 - clz32(res) : ctz32(res);
     } else {
         env->regs[R_ECX] = 16 >> (ctrl & (1 << 0));
     }
@@ -2138,7 +2110,7 @@ void glue(helper_pcmpistri, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
                                  pcmp_ilen(d, ctrl));
 
     if (res) {
-        env->regs[R_ECX] = (ctrl & (1 << 6)) ? rffs1(res) - 1 : 32 - ffs1(res);
+        env->regs[R_ECX] = (ctrl & (1 << 6)) ? 31 - clz32(res) : ctz32(res);
     } else {
         env->regs[R_ECX] = 16 >> (ctrl & (1 << 0));
     }
commit 83f7dc28ca7cb422f88caf3923bf078abb4e4dea
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:02 2013 +0100

    target-i386: enable SSE4.1 and SSE4.2 in TCG mode
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index a0640db..4b43759 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -388,16 +388,17 @@ typedef struct x86_def_t {
           /* missing:
           CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
 #define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | \
-          CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT | \
-          CPUID_EXT_MOVBE | CPUID_EXT_HYPERVISOR)
+          CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | CPUID_EXT_SSE41 | \
+          CPUID_EXT_SSE42 | CPUID_EXT_POPCNT | CPUID_EXT_MOVBE | \
+          CPUID_EXT_HYPERVISOR)
           /* missing:
           CPUID_EXT_PCLMULQDQ, CPUID_EXT_DTES64, CPUID_EXT_DSCPL,
           CPUID_EXT_VMX, CPUID_EXT_SMX, CPUID_EXT_EST, CPUID_EXT_TM2,
           CPUID_EXT_CID, CPUID_EXT_FMA, CPUID_EXT_XTPR, CPUID_EXT_PDCM,
-          CPUID_EXT_PCID, CPUID_EXT_DCA, CPUID_EXT_SSE41, CPUID_EXT_SSE42,
-          CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER, CPUID_EXT_AES,
-          CPUID_EXT_XSAVE, CPUID_EXT_OSXSAVE, CPUID_EXT_AVX,
-          CPUID_EXT_F16C, CPUID_EXT_RDRAND */
+          CPUID_EXT_PCID, CPUID_EXT_DCA, CPUID_EXT_X2APIC,
+          CPUID_EXT_TSC_DEADLINE_TIMER, CPUID_EXT_AES, CPUID_EXT_XSAVE,
+          CPUID_EXT_OSXSAVE, CPUID_EXT_AVX, CPUID_EXT_F16C,
+          CPUID_EXT_RDRAND */
 #define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \
           CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
           CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT)
commit e4eba27e29114842978234a44c92b2a945a6b46d
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:02 2013 +0100

    target-i386: SSE4.2: fix pcmpXstrX instructions with "Masked(-)" polarity
    
    valids can equals to -1 if the reg/mem string is empty. Change the
    expression to have an empty xor mask in that case.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 77ab410..a0bac07 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2050,7 +2050,7 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s,
         res ^= (2 << upper) - 1;
         break;
     case 3:
-        res ^= (2 << valids) - 1;
+        res ^= (1 << (valids + 1)) - 1;
         break;
     }
 
commit 75c9527e190231fbc2fd8470e132f360e70206be
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:02 2013 +0100

    target-i386: SSE4.2: fix pcmpXstrX instructions in "Equal ordered" mode
    
    The inner loop should only change the current bit of the result, instead
    of the whole result.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 2fc5fdd..77ab410 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2036,10 +2036,11 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s,
     case 3:
         for (j = valids - validd; j >= 0; j--) {
             res <<= 1;
-            res |= 1;
+            v = 1;
             for (i = MIN(upper - j, validd); i >= 0; i--) {
-                res &= (pcmp_val(s, ctrl, i + j) == pcmp_val(d, ctrl, i));
+                v &= (pcmp_val(s, ctrl, i + j) == pcmp_val(d, ctrl, i));
             }
+            res |= v;
         }
         break;
     }
commit b27a6cacb73ca006c6995ca5c3db7347333ba7f4
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:01 2013 +0100

    target-i386: SSE4.2: fix pcmpXstrX instructions in "Equal each" mode
    
    pcmpXstrX instructions in "Equal each" mode force both invalid element
    pair to true. It means (upper - MAX(valids, validd)) bits should be set
    to 1, not (upper - MAX(valids, validd) + 1).
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 51c5fc9..2fc5fdd 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2025,7 +2025,7 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s,
         }
         break;
     case 2:
-        res = (2 << (upper - MAX(valids, validd))) - 1;
+        res = (1 << (upper - MAX(valids, validd))) - 1;
         res <<= MAX(valids, validd) - MIN(valids, validd);
         for (i = MIN(valids, validd); i >= 0; i--) {
             res <<= 1;
commit 649ad05ed4133d3a48d43881aa9351c024d9cdc1
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:01 2013 +0100

    target-i386: SSE4.2: fix pcmpXstrX instructions in "Ranges" mode
    
    Fix the order of the of the comparisons to match the "Intel 64 and
    IA-32 Architectures Software Developer's Manual".
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 4a95f41..51c5fc9 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2019,8 +2019,8 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s,
             res <<= 1;
             v = pcmp_val(s, ctrl, j);
             for (i = ((validd - 1) | 1); i >= 0; i -= 2) {
-                res |= (pcmp_val(d, ctrl, i - 0) <= v &&
-                        pcmp_val(d, ctrl, i - 1) >= v);
+                res |= (pcmp_val(d, ctrl, i - 0) >= v &&
+                        pcmp_val(d, ctrl, i - 1) <= v);
             }
         }
         break;
commit 2b8d7e9d728fe2b7c8ffb9859368fb2b5c0bf833
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:01 2013 +0100

    target-i386: SSE4.2: fix pcmpXstrm instructions
    
    pcmpXstrm instructions returns their result in the XMM0 register and
    not in the first operand.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 0667c87..4a95f41 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2116,16 +2116,16 @@ void glue(helper_pcmpestrm, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
     if ((ctrl >> 6) & 1) {
         if (ctrl & 1) {
             for (i = 0; i < 8; i++, res >>= 1) {
-                d->W(i) = (res & 1) ? ~0 : 0;
+                env->xmm_regs[0].W(i) = (res & 1) ? ~0 : 0;
             }
         } else {
             for (i = 0; i < 16; i++, res >>= 1) {
-                d->B(i) = (res & 1) ? ~0 : 0;
+                env->xmm_regs[0].B(i) = (res & 1) ? ~0 : 0;
             }
         }
     } else {
-        d->Q(1) = 0;
-        d->Q(0) = res;
+        env->xmm_regs[0].Q(1) = 0;
+        env->xmm_regs[0].Q(0) = res;
     }
 }
 
@@ -2154,16 +2154,16 @@ void glue(helper_pcmpistrm, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
     if ((ctrl >> 6) & 1) {
         if (ctrl & 1) {
             for (i = 0; i < 8; i++, res >>= 1) {
-                d->W(i) = (res & 1) ? ~0 : 0;
+                env->xmm_regs[0].W(i) = (res & 1) ? ~0 : 0;
             }
         } else {
             for (i = 0; i < 16; i++, res >>= 1) {
-                d->B(i) = (res & 1) ? ~0 : 0;
+                env->xmm_regs[0].B(i) = (res & 1) ? ~0 : 0;
             }
         }
     } else {
-        d->Q(1) = 0;
-        d->Q(0) = res;
+        env->xmm_regs[0].Q(1) = 0;
+        env->xmm_regs[0].Q(0) = res;
     }
 }
 
commit 93e3c0ae69ae73d7f04ac378c5df6e98c7faa6dd
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:01 2013 +0100

    target-i386: SSE4.2: fix pcmpXstri instructions
    
    ffs1 returns the first bit set to one starting counting from the most
    significant bit.
    
    pcmpXstri returns the most significant bit set to one, starting counting
    from the least significant bit.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index 0136df9..0667c87 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -2099,7 +2099,7 @@ void glue(helper_pcmpestri, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
                                  pcmp_elen(env, R_EAX, ctrl));
 
     if (res) {
-        env->regs[R_ECX] = ((ctrl & (1 << 6)) ? rffs1 : ffs1)(res) - 1;
+        env->regs[R_ECX] = (ctrl & (1 << 6)) ? rffs1(res) - 1 : 32 - ffs1(res);
     } else {
         env->regs[R_ECX] = 16 >> (ctrl & (1 << 0));
     }
@@ -2137,7 +2137,7 @@ void glue(helper_pcmpistri, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
                                  pcmp_ilen(d, ctrl));
 
     if (res) {
-        env->regs[R_ECX] = ((ctrl & (1 << 6)) ? rffs1 : ffs1)(res) - 1;
+        env->regs[R_ECX] = (ctrl & (1 << 6)) ? rffs1(res) - 1 : 32 - ffs1(res);
     } else {
         env->regs[R_ECX] = 16 >> (ctrl & (1 << 0));
     }
commit da5156cd9a62274839d6fa685cc52614886cc722
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:01 2013 +0100

    target-i386: SSE4.2: fix pcmpgtq instruction
    
    The "Intel 64 and IA-32 Architectures Software Developer's Manual" (at
    least recent versions) clearly says that the comparison is signed.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index cad9d75..0136df9 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -1933,8 +1933,7 @@ void glue(helper_mpsadbw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
 }
 
 /* SSE4.2 op helpers */
-/* it's unclear whether signed or unsigned */
-#define FCMPGTQ(d, s) (d > s ? -1 : 0)
+#define FCMPGTQ(d, s) ((int64_t)d > (int64_t)s ? -1 : 0)
 SSE_HELPER_Q(helper_pcmpgtq, FCMPGTQ)
 
 static inline int pcmp_elen(CPUX86State *env, int reg, uint32_t ctrl)
commit 34c6addd4b22583e7b408c0d1452eab753cbfb62
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Mar 26 19:56:01 2013 +0100

    target-i386: SSE4.1: fix pinsrb instruction
    
    gen_op_mov_TN_reg() loads the value in cpu_T[0], so this temporary should
    be used instead of cpu_tmp0.
    
    Reviewed-by: Richard Henderson <rth at twiddle.net>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 7239696..7596a90 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4404,9 +4404,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
                     if (mod == 3)
                         gen_op_mov_TN_reg(OT_LONG, 0, rm);
                     else
-                        tcg_gen_qemu_ld8u(cpu_tmp0, cpu_A0,
+                        tcg_gen_qemu_ld8u(cpu_T[0], cpu_A0,
                                         (s->mem_index >> 2) - 1);
-                    tcg_gen_st8_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State,
+                    tcg_gen_st8_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
                                             xmm_regs[reg].XMM_B(val & 15)));
                     break;
                 case 0x21: /* insertps */
commit c7b4c36714a442ae5abd26de293cb5e967be6e12
Merge: e63d28d b0d62a3
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Apr 1 10:36:09 2013 -0500

    Merge remote-tracking branch 'stefanha/trivial-patches' into staging
    
    # By Dunrong Huang (1) and others
    # Via Stefan Hajnoczi
    * stefanha/trivial-patches:
      hw/tcx: Remove unused 'addr' field and the property that sets it
      hw/i386/pc: format load_linux function
      configure: show debug-info option in --help output

commit e63d28d7dbfcec81214aecc9ff0aaee46e87aa44
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 14:34:23 2013 +0000

    sysbus: Remove sysbus_add_memory and sysbus_del_memory
    
    Remove the sysbus_add_memory and sysbus_del_memory functions. These
    are trivial wrappers for mapping a memory region into the system
    memory space, and have no users now.  Sysbus devices should never map
    their own memory regions anyway; the correct API for mapping an mmio
    region is for the creator of the device to use sysbus_mmio_map.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1363358063-23973-6-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/sysbus.c b/hw/sysbus.c
index 9a19468..9004d8c 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -236,24 +236,6 @@ static char *sysbus_get_fw_dev_path(DeviceState *dev)
     return g_strdup(path);
 }
 
-void sysbus_add_memory(SysBusDevice *dev, hwaddr addr,
-                       MemoryRegion *mem)
-{
-    memory_region_add_subregion(get_system_memory(), addr, mem);
-}
-
-void sysbus_add_memory_overlap(SysBusDevice *dev, hwaddr addr,
-                               MemoryRegion *mem, unsigned priority)
-{
-    memory_region_add_subregion_overlap(get_system_memory(), addr, mem,
-                                        priority);
-}
-
-void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem)
-{
-    memory_region_del_subregion(get_system_memory(), mem);
-}
-
 void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
                        MemoryRegion *mem)
 {
diff --git a/hw/sysbus.h b/hw/sysbus.h
index 5d90a52..7c2e316 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -58,11 +58,6 @@ void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq);
 void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr);
 void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
                              unsigned priority);
-void sysbus_add_memory(SysBusDevice *dev, hwaddr addr,
-                       MemoryRegion *mem);
-void sysbus_add_memory_overlap(SysBusDevice *dev, hwaddr addr,
-                               MemoryRegion *mem, unsigned priority);
-void sysbus_del_memory(SysBusDevice *dev, MemoryRegion *mem);
 void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
                    MemoryRegion *mem);
 void sysbus_del_io(SysBusDevice *dev, MemoryRegion *mem);
commit c31bc98e3bcf52fe1cd4b9b7a70869330eae80ea
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Mar 28 18:43:04 2013 +0000

    hw/milkymist-softusb: set buffer in softusb_read_{dmem, pmem} error path
    
    Make sure we set the buffer to something in the softusb_read_{dmem,pmem}
    error paths, since the caller will use the buffer unconditionally.
    (Newer gcc is smart enough to spot this and complain about 'may be
    used uninitialized'.)
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1364496184-11994-1-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index b279d4e..90a0ae5 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -132,6 +132,7 @@ static inline void softusb_read_dmem(MilkymistSoftUsbState *s,
     if (offset + len >= s->dmem_size) {
         error_report("milkymist_softusb: read dmem out of bounds "
                 "at offset 0x%x, len %d", offset, len);
+        memset(buf, 0, len);
         return;
     }
 
@@ -156,6 +157,7 @@ static inline void softusb_read_pmem(MilkymistSoftUsbState *s,
     if (offset + len >= s->pmem_size) {
         error_report("milkymist_softusb: read pmem out of bounds "
                 "at offset 0x%x, len %d", offset, len);
+        memset(buf, 0, len);
         return;
     }
 
commit c34e120554c31d45bdfbac08a5c1d9ef92a62020
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 14:34:22 2013 +0000

    milkymist-softusb: Don't map RAM memory regions in the device itself
    
    Don't map the pmem and dmem RAM memory regions in the milkymist-softusb
    device itself. Instead just expose them as sysbus mmio regions which
    the device creator can map appropriately. This allows us to drop the
    pmem_base and dmem_base properties. Instead of going via
    cpu_physical_memory_read/_write when the device wants to access the
    RAMs, we just keep a host pointer to the memory and use that.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Michael Walle <michael at walle.cc>
    Message-id: 1363358063-23973-5-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h
index 8e6c01e..4e86c4e 100644
--- a/hw/milkymist-hw.h
+++ b/hw/milkymist-hw.h
@@ -194,12 +194,12 @@ static inline DeviceState *milkymist_softusb_create(hwaddr base,
     DeviceState *dev;
 
     dev = qdev_create(NULL, "milkymist-softusb");
-    qdev_prop_set_uint32(dev, "pmem_base", pmem_base);
     qdev_prop_set_uint32(dev, "pmem_size", pmem_size);
-    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(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, pmem_base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, dmem_base);
     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
 
     return dev;
diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index d911686..b279d4e 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -54,10 +54,11 @@ struct MilkymistSoftUsbState {
     MemoryRegion dmem;
     qemu_irq irq;
 
+    void *pmem_ptr;
+    void *dmem_ptr;
+
     /* device properties */
-    uint32_t pmem_base;
     uint32_t pmem_size;
-    uint32_t dmem_base;
     uint32_t dmem_size;
 
     /* device registers */
@@ -134,7 +135,7 @@ static inline void softusb_read_dmem(MilkymistSoftUsbState *s,
         return;
     }
 
-    cpu_physical_memory_read(s->dmem_base + offset, buf, len);
+    memcpy(buf, s->dmem_ptr + offset, len);
 }
 
 static inline void softusb_write_dmem(MilkymistSoftUsbState *s,
@@ -146,7 +147,7 @@ static inline void softusb_write_dmem(MilkymistSoftUsbState *s,
         return;
     }
 
-    cpu_physical_memory_write(s->dmem_base + offset, buf, len);
+    memcpy(s->dmem_ptr + offset, buf, len);
 }
 
 static inline void softusb_read_pmem(MilkymistSoftUsbState *s,
@@ -158,7 +159,7 @@ static inline void softusb_read_pmem(MilkymistSoftUsbState *s,
         return;
     }
 
-    cpu_physical_memory_read(s->pmem_base + offset, buf, len);
+    memcpy(buf, s->pmem_ptr + offset, len);
 }
 
 static inline void softusb_write_pmem(MilkymistSoftUsbState *s,
@@ -170,7 +171,7 @@ static inline void softusb_write_pmem(MilkymistSoftUsbState *s,
         return;
     }
 
-    cpu_physical_memory_write(s->pmem_base + offset, buf, len);
+    memcpy(s->pmem_ptr + offset, buf, len);
 }
 
 static void softusb_mouse_changed(MilkymistSoftUsbState *s)
@@ -270,11 +271,13 @@ static int milkymist_softusb_init(SysBusDevice *dev)
     memory_region_init_ram(&s->pmem, "milkymist-softusb.pmem",
                            s->pmem_size);
     vmstate_register_ram_global(&s->pmem);
-    sysbus_add_memory(dev, s->pmem_base, &s->pmem);
+    s->pmem_ptr = memory_region_get_ram_ptr(&s->pmem);
+    sysbus_init_mmio(dev, &s->pmem);
     memory_region_init_ram(&s->dmem, "milkymist-softusb.dmem",
                            s->dmem_size);
     vmstate_register_ram_global(&s->dmem);
-    sysbus_add_memory(dev, s->dmem_base, &s->dmem);
+    s->dmem_ptr = memory_region_get_ram_ptr(&s->dmem);
+    sysbus_init_mmio(dev, &s->dmem);
 
     hid_init(&s->hid_kbd, HID_KEYBOARD, softusb_kbd_hid_datain);
     hid_init(&s->hid_mouse, HID_MOUSE, softusb_mouse_hid_datain);
@@ -298,9 +301,7 @@ static const VMStateDescription vmstate_milkymist_softusb = {
 };
 
 static Property milkymist_softusb_properties[] = {
-    DEFINE_PROP_UINT32("pmem_base", MilkymistSoftUsbState, pmem_base, 0xa0000000),
     DEFINE_PROP_UINT32("pmem_size", MilkymistSoftUsbState, pmem_size, 0x00001000),
-    DEFINE_PROP_UINT32("dmem_base", MilkymistSoftUsbState, dmem_base, 0xa0020000),
     DEFINE_PROP_UINT32("dmem_size", MilkymistSoftUsbState, dmem_size, 0x00002000),
     DEFINE_PROP_END_OF_LIST(),
 };
commit 20cf850c6ac5bf1ef13de1da93a5c8b5ea28b304
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 14:34:21 2013 +0000

    milkymist-minimac2: Just expose buffers as a sysbus mmio region
    
    Just expose the register buffers memory as a standard sysbus mmio
    region which the creator of the device can map, rather than
    providing a qdev property which the creator has to set to the
    base address and then doing the mapping in the device's own
    init function.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Acked-by: Michael Walle <michael at walle.cc>
    Message-id: 1363358063-23973-4-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/milkymist-hw.h b/hw/milkymist-hw.h
index c047a70..8e6c01e 100644
--- a/hw/milkymist-hw.h
+++ b/hw/milkymist-hw.h
@@ -177,10 +177,10 @@ static inline DeviceState *milkymist_minimac2_create(hwaddr base,
 
     qemu_check_nic_model(&nd_table[0], "minimac2");
     dev = qdev_create(NULL, "milkymist-minimac2");
-    qdev_prop_set_taddr(dev, "buffers_base", buffers_base);
     qdev_set_nic_properties(dev, &nd_table[0]);
     qdev_init_nofail(dev);
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, buffers_base);
     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, rx_irq);
     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 1, tx_irq);
 
diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c
index c20ff90..29618e8 100644
--- a/hw/milkymist-minimac2.c
+++ b/hw/milkymist-minimac2.c
@@ -96,7 +96,6 @@ struct MilkymistMinimac2State {
     NICState *nic;
     NICConf conf;
     char *phy_model;
-    hwaddr buffers_base;
     MemoryRegion buffers;
     MemoryRegion regs_region;
 
@@ -475,7 +474,7 @@ static int milkymist_minimac2_init(SysBusDevice *dev)
     s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE;
     s->tx_buf = s->rx1_buf + MINIMAC2_BUFFER_SIZE;
 
-    sysbus_add_memory(dev, s->buffers_base, &s->buffers);
+    sysbus_init_mmio(dev, &s->buffers);
 
     qemu_macaddr_default_if_unset(&s->conf.macaddr);
     s->nic = qemu_new_nic(&net_milkymist_minimac2_info, &s->conf,
@@ -517,8 +516,6 @@ static const VMStateDescription vmstate_milkymist_minimac2 = {
 };
 
 static Property milkymist_minimac2_properties[] = {
-    DEFINE_PROP_TADDR("buffers_base", MilkymistMinimac2State,
-    buffers_base, 0),
     DEFINE_NIC_PROPERTIES(MilkymistMinimac2State, conf),
     DEFINE_PROP_STRING("phy_model", MilkymistMinimac2State, phy_model),
     DEFINE_PROP_END_OF_LIST(),
commit a86f200aeb66a4f402b22241a5d8360f02bfc090
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 14:34:20 2013 +0000

    musicpal: qdevify musicpal-misc
    
    Make musicpal-misc into its own (trivial) qdev device, so we
    can get rid of the abuse of sysbus_add_memory().
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Message-id: 1363358063-23973-3-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index edd5282..ea8473d 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -1033,6 +1033,15 @@ static const TypeInfo mv88w8618_flashcfg_info = {
 
 #define MP_BOARD_REVISION       0x31
 
+typedef struct {
+    SysBusDevice parent_obj;
+    MemoryRegion iomem;
+} MusicPalMiscState;
+
+#define TYPE_MUSICPAL_MISC "musicpal-misc"
+#define MUSICPAL_MISC(obj) \
+     OBJECT_CHECK(MusicPalMiscState, (obj), TYPE_MUSICPAL_MISC)
+
 static uint64_t musicpal_misc_read(void *opaque, hwaddr offset,
                                    unsigned size)
 {
@@ -1056,15 +1065,23 @@ static const MemoryRegionOps musicpal_misc_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void musicpal_misc_init(SysBusDevice *dev)
+static void musicpal_misc_init(Object *obj)
 {
-    MemoryRegion *iomem = g_new(MemoryRegion, 1);
+    SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+    MusicPalMiscState *s = MUSICPAL_MISC(obj);
 
-    memory_region_init_io(iomem, &musicpal_misc_ops, NULL,
+    memory_region_init_io(&s->iomem, &musicpal_misc_ops, NULL,
                           "musicpal-misc", MP_MISC_SIZE);
-    sysbus_add_memory(dev, MP_MISC_BASE, iomem);
+    sysbus_init_mmio(sd, &s->iomem);
 }
 
+static const TypeInfo musicpal_misc_info = {
+    .name = TYPE_MUSICPAL_MISC,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_init = musicpal_misc_init,
+    .instance_size = sizeof(MusicPalMiscState),
+};
+
 /* WLAN register offsets */
 #define MP_WLAN_MAGIC1          0x11c
 #define MP_WLAN_MAGIC2          0x124
@@ -1614,7 +1631,7 @@ static void musicpal_init(QEMUMachineInitArgs *args)
 
     sysbus_create_simple("mv88w8618_wlan", MP_WLAN_BASE, NULL);
 
-    musicpal_misc_init(SYS_BUS_DEVICE(dev));
+    sysbus_create_simple(TYPE_MUSICPAL_MISC, MP_MISC_BASE, NULL);
 
     dev = sysbus_create_simple("musicpal_gpio", MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
     i2c_dev = sysbus_create_simple("gpio_i2c", -1, NULL);
@@ -1694,6 +1711,7 @@ static void musicpal_register_types(void)
     type_register_static(&musicpal_lcd_info);
     type_register_static(&musicpal_gpio_info);
     type_register_static(&musicpal_key_info);
+    type_register_static(&musicpal_misc_info);
 }
 
 type_init(musicpal_register_types)
commit 4ce5dae88ecf2bafa0cd663de7e923728b1b3672
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Fri Mar 15 14:34:19 2013 +0000

    sysbus: make SysBusDeviceClass::init optional
    
    Make the SysBusDeviceClass::init optional, for devices which
    genuinely don't need to do anything here. In particular, simple
    devices which can do all their initialization in their
    instance_init method don't need either a DeviceClass::realize
    or SysBusDeviceClass::init method.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Acked-by: Andreas Färber <afaerber at suse.de>
    Reviewed-by: Peter Crosthwaite <peter.crosthwaite at xilinx.com>
    Message-id: 1363358063-23973-2-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/sysbus.c b/hw/sysbus.c
index 702fc72..9a19468 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -137,6 +137,9 @@ static int sysbus_device_init(DeviceState *dev)
     SysBusDevice *sd = SYS_BUS_DEVICE(dev);
     SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(sd);
 
+    if (!sbc->init) {
+        return 0;
+    }
     return sbc->init(sd);
 }
 
commit 5357406415571b3f03d05b60a143afdea2b9b1b9
Author: Dunrong Huang <huangdr at cloud-times.com>
Date:   Sun Mar 31 09:35:53 2013 +0800

    target-moxie: set do_interrupt to a target-specific helper function
    
    The value of "do_interrupt" member of CPUClass shoule be set to a
    target-specific function, or it will lead to a segfault like below:
    
    $ moxie-softmmu/qemu-system-moxie -M moxiesim
    Segmentation fault
    
    Cc: Anthony Green <green at moxielogic.com>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Cc: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Dunrong Huang <huangdr at cloud-times.com>
    Signed-of-by: Anthony Green <green at moxielogic.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
index c17d3f0..c0855f0 100644
--- a/target-moxie/cpu.c
+++ b/target-moxie/cpu.c
@@ -98,6 +98,7 @@ static void moxie_cpu_class_init(ObjectClass *oc, void *data)
     cc->class_by_name = moxie_cpu_class_by_name;
 
     dc->vmsd = &vmstate_moxie_cpu;
+    cc->do_interrupt = moxie_cpu_do_interrupt;
 }
 
 static void moxielite_initfn(Object *obj)
diff --git a/target-moxie/cpu.h b/target-moxie/cpu.h
index b96236f..988729a 100644
--- a/target-moxie/cpu.h
+++ b/target-moxie/cpu.h
@@ -117,7 +117,7 @@ static inline MoxieCPU *moxie_env_get_cpu(CPUMoxieState *env)
 
 MoxieCPU *cpu_moxie_init(const char *cpu_model);
 int cpu_moxie_exec(CPUMoxieState *s);
-void do_interrupt(CPUMoxieState *env);
+void moxie_cpu_do_interrupt(CPUState *cs);
 void moxie_translate_init(void);
 int cpu_moxie_signal_handler(int host_signum, void *pinfo,
                              void *puc);
diff --git a/target-moxie/helper.c b/target-moxie/helper.c
index 8604ce8..6e0ac2a 100644
--- a/target-moxie/helper.c
+++ b/target-moxie/helper.c
@@ -102,7 +102,7 @@ void helper_debug(CPUMoxieState *env)
 
 #if defined(CONFIG_USER_ONLY)
 
-void do_interrupt(CPUState *env)
+void moxie_cpu_do_interrupt(CPUState *env)
 {
     env->exception_index = -1;
 }
@@ -147,8 +147,11 @@ int cpu_moxie_handle_mmu_fault(CPUMoxieState *env, target_ulong address,
 }
 
 
-void do_interrupt(CPUMoxieState *env)
+void moxie_cpu_do_interrupt(CPUState *cs)
 {
+    MoxieCPU *cpu = MOXIE_CPU(cs);
+    CPUMoxieState *env = &cpu->env;
+
     switch (env->exception_index) {
     case MOXIE_EX_BREAK:
         break;
commit 5e3a0f418c4d57399778cee0b55aebfb663b6425
Author: Stefan Weil <sw at weilnetz.de>
Date:   Fri Mar 29 18:20:20 2013 +0100

    w32: Fix build with older gcc (unresolved symbol)
    
    The cross i586-mingw32msvc-gcc 4.4.4 from Debian Squeeze does not support
    __sync_val_compare_and_swap by default.
    
    Using -march=i686 fixes that and should also result in better code.
    
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index f2af714..70c2219 100755
--- a/configure
+++ b/configure
@@ -562,6 +562,11 @@ if test "$mingw32" = "yes" ; then
   QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS"
   # enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later)
   QEMU_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $QEMU_CFLAGS"
+  if test "$cpu" = "i386"; then
+    # We need something better than i386 for __sync_val_compare_and_swap
+    # and can expect that QEMU will only run on i686 or later.
+    QEMU_CFLAGS="-march=i686 $QEMU_CFLAGS"
+  fi
   LIBS="-lwinmm -lws2_32 -liphlpapi $LIBS"
 cat > $TMPC << EOF
 int main(void) { return 0; }
commit e06335b9515f0508f33846e58b2028dfa4fc9983
Author: Stefan Weil <sw at weilnetz.de>
Date:   Sun Mar 24 09:04:48 2013 +0100

    target-moxie: Fix pointer-to-integer conversion (MinGW-w64)
    
    The type cast must use tcg_target_long instead of long.
    This makes a difference for hosts where sizeof(long) != sizeof(void *).
    
    Cc: Anthony Green <green at moxielogic.com>
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Stefan Weil <sw at weilnetz.de>
    Signed-off-by: Anthony Green <green at moxielogic.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-moxie/translate.c b/target-moxie/translate.c
index 34f166e..cc02bd3 100644
--- a/target-moxie/translate.c
+++ b/target-moxie/translate.c
@@ -133,7 +133,7 @@ static inline void gen_goto_tb(CPUMoxieState *env, DisasContext *ctx,
         !ctx->singlestep_enabled) {
         tcg_gen_goto_tb(n);
         tcg_gen_movi_i32(cpu_pc, dest);
-        tcg_gen_exit_tb((long) tb + n);
+        tcg_gen_exit_tb((tcg_target_long)tb + n);
     } else {
         tcg_gen_movi_i32(cpu_pc, dest);
         if (ctx->singlestep_enabled) {
commit c9721215126a8ef46abd2e762efd6aa5ff6b92b9
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Sat Feb 23 00:40:39 2013 +0000

    piix_pci: Fix C99 comments
    
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Tested-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Message-id: 1361580039-4459-4-git-send-email-dwmw2 at infradead.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 1e05d49..83fcfa4 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -425,10 +425,10 @@ static void piix3_reset(void *opaque)
     PIIX3State *d = opaque;
     uint8_t *pci_conf = d->dev.config;
 
-    pci_conf[0x04] = 0x07; // master, memory and I/O
+    pci_conf[0x04] = 0x07; /* master, memory and I/O */
     pci_conf[0x05] = 0x00;
     pci_conf[0x06] = 0x00;
-    pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+    pci_conf[0x07] = 0x02; /* PCI_status_devsel_medium */
     pci_conf[0x4c] = 0x4d;
     pci_conf[0x4e] = 0x03;
     pci_conf[0x4f] = 0x00;
@@ -569,7 +569,8 @@ static void piix3_class_init(ObjectClass *klass, void *data)
     k->init         = piix3_initfn;
     k->config_write = piix3_write_config;
     k->vendor_id    = PCI_VENDOR_ID_INTEL;
-    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+    /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
+    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0;
     k->class_id     = PCI_CLASS_BRIDGE_ISA;
 }
 
@@ -592,7 +593,8 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data)
     k->init         = piix3_initfn;
     k->config_write = piix3_write_config_xen;
     k->vendor_id    = PCI_VENDOR_ID_INTEL;
-    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+    /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
+    k->device_id    = PCI_DEVICE_ID_INTEL_82371SB_0;
     k->class_id     = PCI_CLASS_BRIDGE_ISA;
 };
 
commit d93a8a435cbd7f874ef71d4da5677c5f88d8435a
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Sat Feb 23 00:40:38 2013 +0000

    piix_pci: Use DEVICE() and ISA_BUS()
    
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Tested-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Message-id: 1361580039-4459-3-git-send-email-dwmw2 at infradead.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index c29eee0..1e05d49 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -300,8 +300,7 @@ static PCIBus *i440fx_common_init(const char *device_name,
         pci_bus_set_route_irq_fn(b, piix3_route_intx_pin_to_irq);
     }
     piix3->pic = pic;
-    *isa_bus = DO_UPCAST(ISABus, qbus,
-                         qdev_get_child_bus(&piix3->dev.qdev, "isa.0"));
+    *isa_bus = ISA_BUS(qdev_get_child_bus(DEVICE(piix3), "isa.0"));
 
     *piix3_devfn = piix3->dev.devfn;
 
@@ -548,7 +547,7 @@ static int piix3_initfn(PCIDevice *dev)
 {
     PIIX3State *d = DO_UPCAST(PIIX3State, dev, dev);
 
-    isa_bus_new(&d->dev.qdev, pci_address_space_io(dev));
+    isa_bus_new(DEVICE(d), pci_address_space_io(dev));
 
     memory_region_init_io(&d->rcr_mem, &rcr_ops, d, "piix3-reset-control", 1);
     memory_region_add_subregion_overlap(pci_address_space_io(dev), RCR_IOPORT,
commit 57a0f0c651a63d3e1e02d74e5c59d2648037b087
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Sat Feb 23 00:40:37 2013 +0000

    piix_pci: Clean up i440FX object handling
    
    Define and use I440FX_PCI_DEVICE() instead of using DO_UPCAST().
    
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
    Reviewed-by: Andreas Färber <afaerber at suse.de>
    Tested-by: Laszlo Ersek <lersek at redhat.com>
    Reviewed-by: Laszlo Ersek <lersek at redhat.com>
    Message-id: 1361580039-4459-2-git-send-email-dwmw2 at infradead.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index ce39779..c29eee0 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -82,6 +82,10 @@ typedef struct PIIX3State {
     MemoryRegion rcr_mem;
 } PIIX3State;
 
+#define TYPE_I440FX_PCI_DEVICE "i440FX"
+#define I440FX_PCI_DEVICE(obj) \
+    OBJECT_CHECK(PCII440FXState, (obj), TYPE_I440FX_PCI_DEVICE)
+
 struct PCII440FXState {
     PCIDevice dev;
     MemoryRegion *system_memory;
@@ -141,7 +145,7 @@ static void i440fx_set_smm(int val, void *arg)
 static void i440fx_write_config(PCIDevice *dev,
                                 uint32_t address, uint32_t val, int len)
 {
-    PCII440FXState *d = DO_UPCAST(PCII440FXState, dev, dev);
+    PCII440FXState *d = I440FX_PCI_DEVICE(dev);
 
     /* XXX: implement SMRAM.D_LOCK */
     pci_default_write_config(dev, address, val, len);
@@ -212,7 +216,7 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev)
 
 static int i440fx_initfn(PCIDevice *dev)
 {
-    PCII440FXState *d = DO_UPCAST(PCII440FXState, dev, dev);
+    PCII440FXState *d = I440FX_PCI_DEVICE(dev);
 
     d->dev.config[I440FX_SMRAM] = 0x02;
 
@@ -251,7 +255,7 @@ static PCIBus *i440fx_common_init(const char *device_name,
     qdev_init_nofail(dev);
 
     d = pci_create_simple(b, 0, device_name);
-    *pi440fx_state = DO_UPCAST(PCII440FXState, dev, d);
+    *pi440fx_state = I440FX_PCI_DEVICE(d);
     f = *pi440fx_state;
     f->system_memory = address_space_mem;
     f->pci_address_space = pci_address_space;
@@ -325,7 +329,8 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
 {
     PCIBus *b;
 
-    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, isa_bus, pic,
+    b = i440fx_common_init(TYPE_I440FX_PCI_DEVICE, pi440fx_state,
+                           piix3_devfn, isa_bus, pic,
                            address_space_mem, address_space_io, ram_size,
                            pci_hole_start, pci_hole_size,
                            pci_hole64_start, pci_hole64_size,
@@ -617,7 +622,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo i440fx_info = {
-    .name          = "i440FX",
+    .name          = TYPE_I440FX_PCI_DEVICE,
     .parent        = TYPE_PCI_DEVICE,
     .instance_size = sizeof(PCII440FXState),
     .class_init    = i440fx_class_init,
commit 226ecabfbd410c7b2041385ea4b6f083a09ce8a2
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Fri Mar 22 17:57:48 2013 +0100

    qemu-bridge-helper: force usage of a very high MAC address for the bridge
    
    Linux uses the lowest enslaved MAC address as the MAC address of
    the bridge.  Set MAC address to a high value so that it does not
    affect the MAC address of the bridge.
    
    Changing the MAC address of the bridge could cause a few seconds
    of network downtime.
    
    Cc: qemu-stable at nongnu.org
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1363971468-21154-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c
index 287bfd5..6a0974e 100644
--- a/qemu-bridge-helper.c
+++ b/qemu-bridge-helper.c
@@ -367,6 +367,24 @@ int main(int argc, char **argv)
         goto cleanup;
     }
 
+    /* Linux uses the lowest enslaved MAC address as the MAC address of
+     * the bridge.  Set MAC address to a high value so that it doesn't
+     * affect the MAC address of the bridge.
+     */
+    if (ioctl(ctlfd, SIOCGIFHWADDR, &ifr) < 0) {
+        fprintf(stderr, "failed to get MAC address of device `%s': %s\n",
+                iface, strerror(errno));
+        ret = EXIT_FAILURE;
+        goto cleanup;
+    }
+    ifr.ifr_hwaddr.sa_data[0] = 0xFE;
+    if (ioctl(ctlfd, SIOCSIFHWADDR, &ifr) < 0) {
+        fprintf(stderr, "failed to set MAC address of device `%s': %s\n",
+                iface, strerror(errno));
+        ret = EXIT_FAILURE;
+        goto cleanup;
+    }
+
     /* add the interface to the bridge */
     prep_ifreq(&ifr, bridge);
     ifindex = if_nametoindex(iface);
commit 2900af5969c8d54d48872cd707a4a0e71e6fa57e
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Mar 27 10:49:15 2013 +0100

    virtio-balloon: cleanup: remove qdev field.
    
    The qdev field is no longer needed, just drop it.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1364377755-15508-7-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 38d2ee3..b382bd4 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -360,7 +360,6 @@ static int virtio_balloon_device_init(VirtIODevice *vdev)
     s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
     s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats);
 
-    s->qdev = qdev;
     register_savevm(qdev, "virtio-balloon", -1, 1,
                     virtio_balloon_save, virtio_balloon_load, s);
 
diff --git a/hw/virtio-balloon.h b/hw/virtio-balloon.h
index 5f8fe02..d898315 100644
--- a/hw/virtio-balloon.h
+++ b/hw/virtio-balloon.h
@@ -67,7 +67,6 @@ typedef struct VirtIOBalloon {
     QEMUTimer *stats_timer;
     int64_t stats_last_update;
     int64_t stats_poll_interval;
-    DeviceState *qdev;
 } VirtIOBalloon;
 
 #endif
commit c96caced3ffd9e5a078f3f5b5d373a40faf7dc3a
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Mar 27 10:49:14 2013 +0100

    virtio-balloon: cleanup: QOM casts.
    
    As the virtio-balloon-pci is switched to the new API, we can use QOM
    casts.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1364377755-15508-6-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 87278f5..38d2ee3 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -31,14 +31,6 @@
 
 #include "hw/virtio-bus.h"
 
-/*
- * Will be modified later in the serie.
- */
-static VirtIOBalloon *to_virtio_balloon(VirtIODevice *vdev)
-{
-    return (VirtIOBalloon *)vdev;
-}
-
 static void balloon_page(void *addr, int deflate)
 {
 #if defined(__linux__)
@@ -74,7 +66,8 @@ static inline void reset_stats(VirtIOBalloon *dev)
 
 static bool balloon_stats_supported(const VirtIOBalloon *s)
 {
-    return s->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ);
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
+    return vdev->guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ);
 }
 
 static bool balloon_stats_enabled(const VirtIOBalloon *s)
@@ -100,6 +93,7 @@ static void balloon_stats_change_timer(VirtIOBalloon *s, int secs)
 static void balloon_stats_poll_cb(void *opaque)
 {
     VirtIOBalloon *s = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
     if (!balloon_stats_supported(s)) {
         /* re-schedule */
@@ -108,7 +102,7 @@ static void balloon_stats_poll_cb(void *opaque)
     }
 
     virtqueue_push(s->svq, &s->stats_vq_elem, s->stats_vq_offset);
-    virtio_notify(&s->vdev, s->svq);
+    virtio_notify(vdev, s->svq);
 }
 
 static void balloon_stats_get_all(Object *obj, struct Visitor *v,
@@ -186,7 +180,7 @@ static void balloon_stats_set_poll_interval(Object *obj, struct Visitor *v,
 
 static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIOBalloon *s = to_virtio_balloon(vdev);
+    VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
     VirtQueueElement elem;
     MemoryRegionSection section;
 
@@ -220,7 +214,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
 
 static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev);
+    VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
     VirtQueueElement *elem = &s->stats_vq_elem;
     VirtIOBalloonStat stat;
     size_t offset = 0;
@@ -262,7 +256,7 @@ out:
 
 static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
 {
-    VirtIOBalloon *dev = to_virtio_balloon(vdev);
+    VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
     struct virtio_balloon_config config;
 
     config.num_pages = cpu_to_le32(dev->num_pages);
@@ -274,7 +268,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
 static void virtio_balloon_set_config(VirtIODevice *vdev,
                                       const uint8_t *config_data)
 {
-    VirtIOBalloon *dev = to_virtio_balloon(vdev);
+    VirtIOBalloon *dev = VIRTIO_BALLOON(vdev);
     struct virtio_balloon_config config;
     uint32_t oldactual = dev->actual;
     memcpy(&config, config_data, 8);
@@ -300,22 +294,24 @@ static void virtio_balloon_stat(void *opaque, BalloonInfo *info)
 
 static void virtio_balloon_to_target(void *opaque, ram_addr_t target)
 {
-    VirtIOBalloon *dev = opaque;
+    VirtIOBalloon *dev = VIRTIO_BALLOON(opaque);
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
 
     if (target > ram_size) {
         target = ram_size;
     }
     if (target) {
         dev->num_pages = (ram_size - target) >> VIRTIO_BALLOON_PFN_SHIFT;
-        virtio_notify_config(&dev->vdev);
+        virtio_notify_config(vdev);
     }
 }
 
 static void virtio_balloon_save(QEMUFile *f, void *opaque)
 {
-    VirtIOBalloon *s = opaque;
+    VirtIOBalloon *s = VIRTIO_BALLOON(opaque);
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
-    virtio_save(&s->vdev, f);
+    virtio_save(vdev, f);
 
     qemu_put_be32(f, s->num_pages);
     qemu_put_be32(f, s->actual);
@@ -323,13 +319,14 @@ static void virtio_balloon_save(QEMUFile *f, void *opaque)
 
 static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
 {
-    VirtIOBalloon *s = opaque;
+    VirtIOBalloon *s = VIRTIO_BALLOON(opaque);
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
     int ret;
 
     if (version_id != 1)
         return -EINVAL;
 
-    ret = virtio_load(&s->vdev, f);
+    ret = virtio_load(vdev, f);
     if (ret) {
         return ret;
     }
@@ -347,9 +344,9 @@ static int virtio_balloon_device_init(VirtIODevice *vdev)
 
     virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON, 8);
 
-    s->vdev.get_config = virtio_balloon_get_config;
-    s->vdev.set_config = virtio_balloon_set_config;
-    s->vdev.get_features = virtio_balloon_get_features;
+    vdev->get_config = virtio_balloon_get_config;
+    vdev->set_config = virtio_balloon_set_config;
+    vdev->get_features = virtio_balloon_get_features;
 
     ret = qemu_add_balloon_handler(virtio_balloon_to_target,
                                    virtio_balloon_stat, s);
diff --git a/hw/virtio-balloon.h b/hw/virtio-balloon.h
index 139eac3..5f8fe02 100644
--- a/hw/virtio-balloon.h
+++ b/hw/virtio-balloon.h
@@ -57,7 +57,7 @@ typedef struct VirtIOBalloonStat {
 } QEMU_PACKED VirtIOBalloonStat;
 
 typedef struct VirtIOBalloon {
-    VirtIODevice vdev;
+    VirtIODevice parent_obj;
     VirtQueue *ivq, *dvq, *svq;
     uint32_t num_pages;
     uint32_t actual;
commit 5c7d0962f60498c3f11d402e1c857cb9d5d8568d
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Mar 27 10:49:13 2013 +0100

    virtio-balloon: cleanup: init and exit function.
    
    This remove old init and exit function as they are no longer needed.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1364377755-15508-5-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 7519971..87278f5 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -339,27 +339,13 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static VirtIODevice *virtio_balloon_common_init(DeviceState *dev,
-                                                VirtIOBalloon **ps)
+static int virtio_balloon_device_init(VirtIODevice *vdev)
 {
-    VirtIOBalloon *s = *ps;
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
     int ret;
 
-    /*
-     * We have two cases here: the old virtio-balloon-x device, and the
-     * refactored virtio-balloon.
-     * This will disappear later in the serie.
-     */
-    int old_device = (s == NULL);
-    if (s == NULL) {
-        /* old virtio-balloon-pci or virtio-balloon-s390, no memory allocated */
-        s = (VirtIOBalloon *)virtio_common_init("virtio-balloon",
-                                                VIRTIO_ID_BALLOON,
-                                                8, sizeof(VirtIOBalloon));
-    } else {
-        /* new API virtio-balloon. (memory allocated by qdev) */
-        virtio_init(VIRTIO_DEVICE(s), "virtio-balloon", VIRTIO_ID_BALLOON, 8);
-    }
+    virtio_init(vdev, "virtio-balloon", VIRTIO_ID_BALLOON, 8);
 
     s->vdev.get_config = virtio_balloon_get_config;
     s->vdev.set_config = virtio_balloon_set_config;
@@ -367,60 +353,27 @@ static VirtIODevice *virtio_balloon_common_init(DeviceState *dev,
 
     ret = qemu_add_balloon_handler(virtio_balloon_to_target,
                                    virtio_balloon_stat, s);
-    if ((ret < 0) && (old_device)) {
-        virtio_cleanup(&s->vdev);
-        return NULL;
-    }
+
     if (ret < 0) {
         virtio_common_cleanup(VIRTIO_DEVICE(s));
-        return NULL;
+        return -1;
     }
 
-    s->ivq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output);
-    s->dvq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output);
-    s->svq = virtio_add_queue(&s->vdev, 128, virtio_balloon_receive_stats);
+    s->ivq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
+    s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
+    s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats);
 
-    s->qdev = dev;
-    register_savevm(dev, "virtio-balloon", -1, 1,
+    s->qdev = qdev;
+    register_savevm(qdev, "virtio-balloon", -1, 1,
                     virtio_balloon_save, virtio_balloon_load, s);
 
-    object_property_add(OBJECT(dev), "guest-stats", "guest statistics",
+    object_property_add(OBJECT(qdev), "guest-stats", "guest statistics",
                         balloon_stats_get_all, NULL, NULL, s, NULL);
 
-    object_property_add(OBJECT(dev), "guest-stats-polling-interval", "int",
+    object_property_add(OBJECT(qdev), "guest-stats-polling-interval", "int",
                         balloon_stats_get_poll_interval,
                         balloon_stats_set_poll_interval,
                         NULL, s, NULL);
-
-    return &s->vdev;
-}
-
-/*
- * This two functions will be removed later in the serie.
- */
-VirtIODevice *virtio_balloon_init(DeviceState *dev)
-{
-    VirtIOBalloon *s = NULL;
-    return virtio_balloon_common_init(dev, &s);
-}
-
-void virtio_balloon_exit(VirtIODevice *vdev)
-{
-    VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev);
-
-    balloon_stats_destroy_timer(s);
-    qemu_remove_balloon_handler(s);
-    unregister_savevm(s->qdev, "virtio-balloon", s);
-    virtio_cleanup(vdev);
-}
-
-static int virtio_balloon_device_init(VirtIODevice *vdev)
-{
-    DeviceState *qdev = DEVICE(vdev);
-    VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
-    if (virtio_balloon_common_init(qdev, &s) == NULL) {
-        return -1;
-    }
     return 0;
 }
 
commit 30bff6a0f1d12742475a980708cfa82be56a881f
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Mar 27 10:49:12 2013 +0100

    virtio-balloon-ccw: switch to the new API.
    
    Here the virtio-balloon-ccw is modified for the new API. The device
    virtio-balloon-ccw extends virtio-ccw-device as before. It creates and
    connects a virtio-balloon during the init. The properties are not modified.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1364377755-15508-4-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 7e79c57..5dce791 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -608,22 +608,24 @@ static int virtio_ccw_serial_exit(VirtioCcwDevice *dev)
     return virtio_ccw_exit(dev);
 }
 
-static int virtio_ccw_balloon_init(VirtioCcwDevice *dev)
+static int virtio_ccw_balloon_init(VirtioCcwDevice *ccw_dev)
 {
-    VirtIODevice *vdev;
+    VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(ccw_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
 
-    vdev = virtio_balloon_init((DeviceState *)dev);
-    if (!vdev) {
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    if (qdev_init(vdev) < 0) {
         return -1;
     }
 
-    return virtio_ccw_device_init(dev, vdev);
+    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
 }
 
-static int virtio_ccw_balloon_exit(VirtioCcwDevice *dev)
+static void virtio_ccw_balloon_instance_init(Object *obj)
 {
-    virtio_balloon_exit(dev->vdev);
-    return virtio_ccw_exit(dev);
+    VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BALLOON);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 }
 
 static int virtio_ccw_scsi_init(VirtioCcwDevice *ccw_dev)
@@ -820,15 +822,16 @@ static void virtio_ccw_balloon_class_init(ObjectClass *klass, void *data)
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
     k->init = virtio_ccw_balloon_init;
-    k->exit = virtio_ccw_balloon_exit;
+    k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = virtio_ccw_balloon_properties;
 }
 
 static const TypeInfo virtio_ccw_balloon = {
-    .name          = "virtio-balloon-ccw",
+    .name          = TYPE_VIRTIO_BALLOON_CCW,
     .parent        = TYPE_VIRTIO_CCW_DEVICE,
-    .instance_size = sizeof(VirtioCcwDevice),
+    .instance_size = sizeof(VirtIOBalloonCcw),
+    .instance_init = virtio_ccw_balloon_instance_init,
     .class_init    = virtio_ccw_balloon_class_init,
 };
 
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index d9f7399..d580510 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -16,6 +16,7 @@
 #include <hw/virtio-net.h>
 #include <hw/virtio-serial.h>
 #include <hw/virtio-scsi.h>
+#include "hw/virtio-balloon.h"
 #include <hw/virtio-rng.h>
 #include <hw/virtio-bus.h>
 
@@ -115,6 +116,16 @@ typedef struct VirtIOBlkCcw {
     VirtIOBlkConf blk;
 } VirtIOBlkCcw;
 
+/* virtio-balloon-ccw */
+
+#define TYPE_VIRTIO_BALLOON_CCW "virtio-balloon-ccw"
+#define VIRTIO_BALLOON_CCW(obj) \
+        OBJECT_CHECK(VirtIOBalloonCcw, (obj), TYPE_VIRTIO_BALLOON_CCW)
+
+typedef struct VirtIOBalloonCcw {
+    VirtioCcwDevice parent_obj;
+    VirtIOBalloon vdev;
+} VirtIOBalloonCcw;
 
 VirtualCssBus *virtual_css_bus_init(void);
 void virtio_ccw_device_update_status(SubchDev *sch);
commit e378e88dfc2dec2a60a856dd478a4edfbc88efd0
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Mar 27 10:49:11 2013 +0100

    virtio-balloon-pci: switch to the new API.
    
    Here the virtio-balloon-pci is modified for the new API. The device
    virtio-balloon-pci extends virtio-pci. It creates and connects a
    virtio-balloon during the init. The properties are not changed.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1364377755-15508-3-git-send-email-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 736a9bf..fb20722 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -22,6 +22,7 @@
 #include "hw/virtio-net.h"
 #include "hw/virtio-serial.h"
 #include "hw/virtio-scsi.h"
+#include "hw/virtio-balloon.h"
 #include "hw/pci/pci.h"
 #include "qemu/error-report.h"
 #include "hw/pci/msi.h"
@@ -1000,33 +1001,6 @@ static void virtio_net_exit_pci(PCIDevice *pci_dev)
     virtio_exit_pci(pci_dev);
 }
 
-static int virtio_balloon_init_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-    VirtIODevice *vdev;
-
-    if (proxy->class_code != PCI_CLASS_OTHERS &&
-        proxy->class_code != PCI_CLASS_MEMORY_RAM) { /* qemu < 1.1 */
-        proxy->class_code = PCI_CLASS_OTHERS;
-    }
-
-    vdev = virtio_balloon_init(&pci_dev->qdev);
-    if (!vdev) {
-        return -1;
-    }
-    virtio_init_pci(proxy, vdev);
-    return 0;
-}
-
-static void virtio_balloon_exit_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-
-    virtio_pci_stop_ioeventfd(proxy);
-    virtio_balloon_exit(proxy->vdev);
-    virtio_exit_pci(pci_dev);
-}
-
 static int virtio_rng_init_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -1127,34 +1101,6 @@ static const TypeInfo virtio_serial_info = {
     .class_init    = virtio_serial_class_init,
 };
 
-static Property virtio_balloon_properties[] = {
-    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
-    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void virtio_balloon_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = virtio_balloon_init_pci;
-    k->exit = virtio_balloon_exit_pci;
-    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
-    k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
-    k->revision = VIRTIO_PCI_ABI_VERSION;
-    k->class_id = PCI_CLASS_OTHERS;
-    dc->reset = virtio_pci_reset;
-    dc->props = virtio_balloon_properties;
-}
-
-static const TypeInfo virtio_balloon_info = {
-    .name          = "virtio-balloon-pci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(VirtIOPCIProxy),
-    .class_init    = virtio_balloon_class_init,
-};
-
 static void virtio_rng_initfn(Object *obj)
 {
     PCIDevice *pci_dev = PCI_DEVICE(obj);
@@ -1461,6 +1407,59 @@ static const TypeInfo virtio_scsi_pci_info = {
     .class_init    = virtio_scsi_pci_class_init,
 };
 
+/* virtio-balloon-pci */
+
+static Property virtio_balloon_pci_properties[] = {
+    DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static int virtio_balloon_pci_init(VirtIOPCIProxy *vpci_dev)
+{
+    VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
+
+    if (vpci_dev->class_code != PCI_CLASS_OTHERS &&
+        vpci_dev->class_code != PCI_CLASS_MEMORY_RAM) { /* qemu < 1.1 */
+        vpci_dev->class_code = PCI_CLASS_OTHERS;
+    }
+
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    if (qdev_init(vdev) < 0) {
+        return -1;
+    }
+    return 0;
+}
+
+static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+    k->init = virtio_balloon_pci_init;
+    dc->props = virtio_balloon_pci_properties;
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
+    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
+    pcidev_k->class_id = PCI_CLASS_OTHERS;
+}
+
+static void virtio_balloon_pci_instance_init(Object *obj)
+{
+    VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BALLOON);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+}
+
+static const TypeInfo virtio_balloon_pci_info = {
+    .name          = TYPE_VIRTIO_BALLOON_PCI,
+    .parent        = TYPE_VIRTIO_PCI,
+    .instance_size = sizeof(VirtIOBalloonPCI),
+    .instance_init = virtio_balloon_pci_instance_init,
+    .class_init    = virtio_balloon_pci_class_init,
+};
+
 /* virtio-pci-bus */
 
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
@@ -1501,7 +1500,6 @@ static void virtio_pci_register_types(void)
 {
     type_register_static(&virtio_net_info);
     type_register_static(&virtio_serial_info);
-    type_register_static(&virtio_balloon_info);
     type_register_static(&virtio_rng_info);
     type_register_static(&virtio_pci_bus_info);
     type_register_static(&virtio_pci_info);
@@ -1510,6 +1508,7 @@ static void virtio_pci_register_types(void)
 #endif
     type_register_static(&virtio_blk_pci_info);
     type_register_static(&virtio_scsi_pci_info);
+    type_register_static(&virtio_balloon_pci_info);
 }
 
 type_init(virtio_pci_register_types)
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index bfe7a8e..f99f2eb 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -21,12 +21,14 @@
 #include "hw/virtio-rng.h"
 #include "hw/virtio-serial.h"
 #include "hw/virtio-scsi.h"
+#include "hw/virtio-balloon.h"
 #include "hw/virtio-bus.h"
 #include "hw/9pfs/virtio-9p-device.h"
 
 typedef struct VirtIOPCIProxy VirtIOPCIProxy;
 typedef struct VirtIOBlkPCI VirtIOBlkPCI;
 typedef struct VirtIOSCSIPCI VirtIOSCSIPCI;
+typedef struct VirtIOBalloonPCI VirtIOBalloonPCI;
 
 /* virtio-pci-bus */
 
@@ -116,6 +118,18 @@ struct VirtIOBlkPCI {
     VirtIOBlkConf blk;
 };
 
+/*
+ * virtio-balloon-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_BALLOON_PCI "virtio-balloon-pci"
+#define VIRTIO_BALLOON_PCI(obj) \
+        OBJECT_CHECK(VirtIOBalloonPCI, (obj), TYPE_VIRTIO_BALLOON_PCI)
+
+struct VirtIOBalloonPCI {
+    VirtIOPCIProxy parent_obj;
+    VirtIOBalloon vdev;
+};
+
 void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev);
 
commit 1ab461b534b34838d1b21c056ab37413f54fefa6
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Wed Mar 27 10:49:10 2013 +0100

    virtio-balloon: add the virtio-balloon device.
    
    Create virtio-balloon which extends virtio-device, so it can be connected on
    virtio-bus.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1364377755-15508-2-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-balloon.c b/hw/virtio-balloon.c
index 54a4372..7519971 100644
--- a/hw/virtio-balloon.c
+++ b/hw/virtio-balloon.c
@@ -29,6 +29,11 @@
 #include <sys/mman.h>
 #endif
 
+#include "hw/virtio-bus.h"
+
+/*
+ * Will be modified later in the serie.
+ */
 static VirtIOBalloon *to_virtio_balloon(VirtIODevice *vdev)
 {
     return (VirtIOBalloon *)vdev;
@@ -334,14 +339,27 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-VirtIODevice *virtio_balloon_init(DeviceState *dev)
+static VirtIODevice *virtio_balloon_common_init(DeviceState *dev,
+                                                VirtIOBalloon **ps)
 {
-    VirtIOBalloon *s;
+    VirtIOBalloon *s = *ps;
     int ret;
 
-    s = (VirtIOBalloon *)virtio_common_init("virtio-balloon",
-                                            VIRTIO_ID_BALLOON,
-                                            8, sizeof(VirtIOBalloon));
+    /*
+     * We have two cases here: the old virtio-balloon-x device, and the
+     * refactored virtio-balloon.
+     * This will disappear later in the serie.
+     */
+    int old_device = (s == NULL);
+    if (s == NULL) {
+        /* old virtio-balloon-pci or virtio-balloon-s390, no memory allocated */
+        s = (VirtIOBalloon *)virtio_common_init("virtio-balloon",
+                                                VIRTIO_ID_BALLOON,
+                                                8, sizeof(VirtIOBalloon));
+    } else {
+        /* new API virtio-balloon. (memory allocated by qdev) */
+        virtio_init(VIRTIO_DEVICE(s), "virtio-balloon", VIRTIO_ID_BALLOON, 8);
+    }
 
     s->vdev.get_config = virtio_balloon_get_config;
     s->vdev.set_config = virtio_balloon_set_config;
@@ -349,10 +367,14 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev)
 
     ret = qemu_add_balloon_handler(virtio_balloon_to_target,
                                    virtio_balloon_stat, s);
-    if (ret < 0) {
+    if ((ret < 0) && (old_device)) {
         virtio_cleanup(&s->vdev);
         return NULL;
     }
+    if (ret < 0) {
+        virtio_common_cleanup(VIRTIO_DEVICE(s));
+        return NULL;
+    }
 
     s->ivq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output);
     s->dvq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output);
@@ -373,6 +395,15 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev)
     return &s->vdev;
 }
 
+/*
+ * This two functions will be removed later in the serie.
+ */
+VirtIODevice *virtio_balloon_init(DeviceState *dev)
+{
+    VirtIOBalloon *s = NULL;
+    return virtio_balloon_common_init(dev, &s);
+}
+
 void virtio_balloon_exit(VirtIODevice *vdev)
 {
     VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev);
@@ -382,3 +413,55 @@ void virtio_balloon_exit(VirtIODevice *vdev)
     unregister_savevm(s->qdev, "virtio-balloon", s);
     virtio_cleanup(vdev);
 }
+
+static int virtio_balloon_device_init(VirtIODevice *vdev)
+{
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
+    if (virtio_balloon_common_init(qdev, &s) == NULL) {
+        return -1;
+    }
+    return 0;
+}
+
+static int virtio_balloon_device_exit(DeviceState *qdev)
+{
+    VirtIOBalloon *s = VIRTIO_BALLOON(qdev);
+    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+
+    balloon_stats_destroy_timer(s);
+    qemu_remove_balloon_handler(s);
+    unregister_savevm(qdev, "virtio-balloon", s);
+    virtio_common_cleanup(vdev);
+    return 0;
+}
+
+static Property virtio_balloon_properties[] = {
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_balloon_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    dc->exit = virtio_balloon_device_exit;
+    dc->props = virtio_balloon_properties;
+    vdc->init = virtio_balloon_device_init;
+    vdc->get_config = virtio_balloon_get_config;
+    vdc->set_config = virtio_balloon_set_config;
+    vdc->get_features = virtio_balloon_get_features;
+}
+
+static const TypeInfo virtio_balloon_info = {
+    .name = TYPE_VIRTIO_BALLOON,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VirtIOBalloon),
+    .class_init = virtio_balloon_class_init,
+};
+
+static void virtio_register_types(void)
+{
+    type_register_static(&virtio_balloon_info);
+}
+
+type_init(virtio_register_types)
diff --git a/hw/virtio-balloon.h b/hw/virtio-balloon.h
index b007042..139eac3 100644
--- a/hw/virtio-balloon.h
+++ b/hw/virtio-balloon.h
@@ -18,6 +18,10 @@
 #include "hw/virtio.h"
 #include "hw/pci/pci.h"
 
+#define TYPE_VIRTIO_BALLOON "virtio-balloon"
+#define VIRTIO_BALLOON(obj) \
+        OBJECT_CHECK(VirtIOBalloon, (obj), TYPE_VIRTIO_BALLOON)
+
 /* from Linux's linux/virtio_balloon.h */
 
 /* The ID for virtio_balloon */
commit fde245ca7ea790495db370cd260259595dbdf874
Merge: 837df37 5d186eb
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 28 12:57:37 2013 -0500

    Merge remote-tracking branch 'stefanha/block' into staging
    
    # By Kevin Wolf (22) and Peter Lieven (1)
    # Via Stefan Hajnoczi
    * stefanha/block: (23 commits)
      block: Fix direct use of protocols as driver for bdrv_open()
      qcow2: Gather clusters in a looping loop
      qcow2: Move cluster gathering to a non-looping loop
      qcow2: Allow requests with multiple l2metas
      qcow2: Use byte granularity in qcow2_alloc_cluster_offset()
      qcow2: Prepare handle_alloc/copied() for byte granularity
      qcow2: handle_copied(): Implement non-zero host_offset
      qcow2: handle_copied(): Get rid of keep_clusters parameter
      qcow2: handle_copied(): Get rid of nb_clusters parameter
      qcow2: Factor out handle_copied()
      qcow2: Clean up handle_alloc()
      qcow2: Finalise interface of handle_alloc()
      qcow2: handle_alloc(): Get rid of keep_clusters parameter
      qcow2: handle_alloc(): Get rid of nb_clusters parameter
      qcow2: Factor out handle_alloc()
      qcow2: Decouple cluster allocation from cluster reuse code
      qcow2: Change handle_dependency to byte granularity
      qcow2: Improve check for overlapping allocations
      qcow2: Handle dependencies earlier
      qcow2: Remove bogus unlock of s->lock
      ...

commit 837df37e881e14ffdb05c2b912b2ad30b851c9d3
Merge: e280ff5 7e86600
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Thu Mar 28 12:57:32 2013 -0500

    Merge remote-tracking branch 'stefanha/tracing' into staging
    
    # By Lluís Vilanova (7) and others
    # Via Stefan Hajnoczi
    * stefanha/tracing:
      vl: add runstate_set tracepoint
      .gitignore: rename trace/generated-tracers.dtrace
      .gitignore: add trace/generated-events.[ch]
      trace: rebuild generated-events.o when configuration changes
      trace: [stderr] Port to generic event information and new control interface
      trace: [simple] Port to generic event information and new control interface
      trace: [default] Port to generic event information and new control interface
      trace: [monitor] Use new event control interface
      trace: Provide a detailed event control interface
      trace: Provide a generic tracing event descriptor
      trace: [tracetool] Explicitly identify public backends

commit 7e8660032cd21c1bdc4160b8fab7deec62e1aa12
Author: Kazuya Saito <saito.kazuya at jp.fujitsu.com>
Date:   Fri Mar 22 17:26:59 2013 +0900

    vl: add runstate_set tracepoint
    
    This patch enables us to know RunState transition. It will be userful
    for investigation when the trouble occured in special event such like
    live migration, shutdown, suspend, and so on.
    
    Signed-off-by: Kazuya Saito <saito.kazuya at jp.fujitsu.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/trace-events b/trace-events
index 406fe5f..85dd49c 100644
--- a/trace-events
+++ b/trace-events
@@ -474,6 +474,7 @@ scsi_request_sense(int target, int lun, int tag) "target %d lun %d tag %d"
 # vl.c
 vm_state_notify(int running, int reason) "running %d reason %d"
 load_file(const char *name, const char *path) "name %s location %s"
+runstate_set(int new_state) "new state %d"
 
 # block/qcow2.c
 qcow2_writev_start_req(void *co, int64_t sector, int nb_sectors) "co %p sector %" PRIx64 " nb_sectors %d"
diff --git a/vl.c b/vl.c
index 7643f16..770cb7f 100644
--- a/vl.c
+++ b/vl.c
@@ -642,7 +642,7 @@ void runstate_set(RunState new_state)
                 RunState_lookup[new_state]);
         abort();
     }
-
+    trace_runstate_set(new_state);
     current_run_state = new_state;
 }
 
commit a46b24fd5dfd6814bafa65e51d8da86ce8eef7f5
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Mar 8 16:10:12 2013 +0100

    .gitignore: rename trace/generated-tracers.dtrace
    
    For a while the file was called trace/generated-tracers-dtrace.dtrace
    but today it's called trace/generated-tracers.dtrace.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/.gitignore b/.gitignore
index c0238aa..487813a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,7 +6,7 @@ config-target.*
 trace/generated-tracers.h
 trace/generated-tracers.c
 trace/generated-tracers-dtrace.h
-trace/generated-tracers-dtrace.dtrace
+trace/generated-tracers.dtrace
 trace/generated-events.h
 trace/generated-events.c
 libcacard/trace/generated-tracers.c
commit 878e63e6c568d4eb147d1adde297325f3aa28c51
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Mar 8 16:10:11 2013 +0100

    .gitignore: add trace/generated-events.[ch]
    
    Don't display autogenerated files in git-status(1).
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/.gitignore b/.gitignore
index 9c234a3..c0238aa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,8 @@ trace/generated-tracers.h
 trace/generated-tracers.c
 trace/generated-tracers-dtrace.h
 trace/generated-tracers-dtrace.dtrace
+trace/generated-events.h
+trace/generated-events.c
 libcacard/trace/generated-tracers.c
 *-timestamp
 *-softmmu
commit a7373b1f61d106ef5c9710eb56e942f513dc512d
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Fri Mar 8 15:52:15 2013 +0100

    trace: rebuild generated-events.o when configuration changes
    
    Make sure to rebuild generated-events.o when ./configure options change.
    This prevents linker errors when a stale generated-events.o gets linked
    with code compiled against fresh headers.  For example, try building
    with ./configure --enable-trace-backend=stderr followed by ./configure
    --enable-trace-backend=dtrace.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index 156aa25..a043072 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -11,7 +11,7 @@ $(obj)/generated-events.h-timestamp: $(SRC_PATH)/trace-events
 		< $< > $@,"  GEN   $(patsubst %-timestamp,%,$@)")
 	@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
 
-$(obj)/generated-events.c: $(obj)/generated-events.c-timestamp
+$(obj)/generated-events.c: $(obj)/generated-events.c-timestamp $(BUILD_DIR)/config-host.mak
 $(obj)/generated-events.c-timestamp: $(SRC_PATH)/trace-events
 	$(call quiet-command,$(TRACETOOL) \
 		--format=events-c \
commit c6f18b9195b4251f32b6ac8e149b449354c1c93b
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:48:00 2013 +0100

    trace: [stderr] Port to generic event information and new control interface
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/scripts/tracetool/backend/stderr.py b/scripts/tracetool/backend/stderr.py
index a10fbb8..6f93dbd 100644
--- a/scripts/tracetool/backend/stderr.py
+++ b/scripts/tracetool/backend/stderr.py
@@ -20,40 +20,29 @@ PUBLIC = True
 
 
 def c(events):
-    out('#include "trace.h"',
-        '',
-        'TraceEvent trace_list[] = {')
-
-    for e in events:
-        out('{.tp_name = "%(name)s", .state=0},',
-            name = e.name,
-            )
-
-    out('};')
+    pass
 
 def h(events):
     out('#include <stdio.h>',
-        '#include "trace/stderr.h"',
+        '#include "trace/control.h"',
         '',
-        'extern TraceEvent trace_list[];')
+        )
 
-    for num, e in enumerate(events):
+    for e in events:
         argnames = ", ".join(e.args.names())
         if len(e.args) > 0:
             argnames = ", " + argnames
 
         out('static inline void trace_%(name)s(%(args)s)',
             '{',
-            '    if (trace_list[%(event_num)s].state != 0) {',
+            '    bool _state = trace_event_get_state(%(event_id)s);',
+            '    if (_state) {',
             '        fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s);',
             '    }',
             '}',
             name = e.name,
             args = e.args,
-            event_num = num,
-            fmt = e.fmt,
+            event_id = "TRACE_" + e.name.upper(),
+            fmt = e.fmt.rstrip("\n"),
             argnames = argnames,
             )
-
-    out('',
-        '#define NR_TRACE_EVENTS %d' % len(events))
diff --git a/trace/stderr.c b/trace/stderr.c
index 0810d6f..e212efd 100644
--- a/trace/stderr.c
+++ b/trace/stderr.c
@@ -4,40 +4,18 @@
 
 void trace_print_events(FILE *stream, fprintf_function stream_printf)
 {
-    unsigned int i;
+    TraceEventID i;
 
-    for (i = 0; i < NR_TRACE_EVENTS; i++) {
+    for (i = 0; i < trace_event_count(); i++) {
+        TraceEvent *ev = trace_event_id(i);
         stream_printf(stream, "%s [Event ID %u] : state %u\n",
-                      trace_list[i].tp_name, i, trace_list[i].state);
+                      trace_event_get_name(ev), i, trace_event_get_state_dynamic(ev));
     }
 }
 
-bool trace_event_set_state(const char *name, bool state)
+void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state)
 {
-    unsigned int i;
-    unsigned int len;
-    bool wildcard = false;
-    bool matched = false;
-
-    len = strlen(name);
-    if (len > 0 && name[len - 1] == '*') {
-        wildcard = true;
-        len -= 1;
-    }
-    for (i = 0; i < NR_TRACE_EVENTS; i++) {
-        if (wildcard) {
-            if (!strncmp(trace_list[i].tp_name, name, len)) {
-                trace_list[i].state = state;
-                matched = true;
-            }
-            continue;
-        }
-        if (!strcmp(trace_list[i].tp_name, name)) {
-            trace_list[i].state = state;
-            return true;
-        }
-    }
-    return matched;
+    ev->dstate = state;
 }
 
 bool trace_backend_init(const char *events, const char *file)
diff --git a/trace/stderr.h b/trace/stderr.h
deleted file mode 100644
index d575b61..0000000
--- a/trace/stderr.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef TRACE_STDERR_H
-#define TRACE_STDERR_H
-
-typedef uint64_t TraceEventID;
-
-typedef struct {
-    const char *tp_name;
-    bool state;
-} TraceEvent;
-
-#endif /* ! TRACE_STDERR_H */
commit 60481e210d1f5f9e97d4d5db82b9afb8d3df7acf
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:47:55 2013 +0100

    trace: [simple] Port to generic event information and new control interface
    
    The backend is forced to dump event numbers using 64 bits, as TraceEventID is
    an enum.
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py
index ac864f3..37ef599 100644
--- a/scripts/tracetool/backend/simple.py
+++ b/scripts/tracetool/backend/simple.py
@@ -28,17 +28,10 @@ def is_string(arg):
 
 def c(events):
     out('#include "trace.h"',
+        '#include "trace/control.h"',
         '#include "trace/simple.h"',
         '',
-        'TraceEvent trace_list[] = {')
-
-    for e in events:
-        out('{.tp_name = "%(name)s", .state=0},',
-            name = e.name,
-            )
-
-    out('};',
-        '')
+        )
 
     for num, event in enumerate(events):
         out('void trace_%(name)s(%(args)s)',
@@ -63,7 +56,9 @@ def c(events):
 
 
         out('',
-            '    if (!trace_list[%(event_id)s].state) {',
+            '    TraceEvent *eventp = trace_event_id(%(event_id)s);',
+            '    bool _state = trace_event_get_state_dynamic(eventp);',
+            '    if (!_state) {',
             '        return;',
             '    }',
             '',
@@ -106,6 +101,3 @@ def h(events):
             name = event.name,
             args = event.args,
             )
-    out('')
-    out('#define NR_TRACE_EVENTS %d' % len(events))
-    out('extern TraceEvent trace_list[NR_TRACE_EVENTS];')
diff --git a/trace/simple.c b/trace/simple.c
index 375d98f..1e3f691 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -218,6 +218,7 @@ int trace_record_start(TraceBufferRecord *rec, TraceEventID event, size_t datasi
 {
     unsigned int idx, rec_off, old_idx, new_idx;
     uint32_t rec_len = sizeof(TraceRecord) + datasize;
+    uint64_t event_u64 = event;
     uint64_t timestamp_ns = get_clock();
 
     do {
@@ -235,7 +236,7 @@ int trace_record_start(TraceBufferRecord *rec, TraceEventID event, size_t datasi
     idx = old_idx % TRACE_BUF_LEN;
 
     rec_off = idx;
-    rec_off = write_to_buffer(rec_off, &event, sizeof(event));
+    rec_off = write_to_buffer(rec_off, &event_u64, sizeof(event_u64));
     rec_off = write_to_buffer(rec_off, &timestamp_ns, sizeof(timestamp_ns));
     rec_off = write_to_buffer(rec_off, &rec_len, sizeof(rec_len));
 
@@ -359,38 +360,16 @@ void trace_print_events(FILE *stream, fprintf_function stream_printf)
 {
     unsigned int i;
 
-    for (i = 0; i < NR_TRACE_EVENTS; i++) {
+    for (i = 0; i < trace_event_count(); i++) {
+        TraceEvent *ev = trace_event_id(i);
         stream_printf(stream, "%s [Event ID %u] : state %u\n",
-                      trace_list[i].tp_name, i, trace_list[i].state);
+                      trace_event_get_name(ev), i, trace_event_get_state_dynamic(ev));
     }
 }
 
-bool trace_event_set_state(const char *name, bool state)
+void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state)
 {
-    unsigned int i;
-    unsigned int len;
-    bool wildcard = false;
-    bool matched = false;
-
-    len = strlen(name);
-    if (len > 0 && name[len - 1] == '*') {
-        wildcard = true;
-        len -= 1;
-    }
-    for (i = 0; i < NR_TRACE_EVENTS; i++) {
-        if (wildcard) {
-            if (!strncmp(trace_list[i].tp_name, name, len)) {
-                trace_list[i].state = state;
-                matched = true;
-            }
-            continue;
-        }
-        if (!strcmp(trace_list[i].tp_name, name)) {
-            trace_list[i].state = state;
-            return true;
-        }
-    }
-    return matched;
+    ev->dstate = state;
 }
 
 /* Helper function to create a thread with signals blocked.  Use glib's
diff --git a/trace/simple.h b/trace/simple.h
index 2ab96a8..5260d9a 100644
--- a/trace/simple.h
+++ b/trace/simple.h
@@ -15,12 +15,8 @@
 #include <stdbool.h>
 #include <stdio.h>
 
-typedef uint64_t TraceEventID;
+#include "trace/generated-events.h"
 
-typedef struct {
-    const char *tp_name;
-    bool state;
-} TraceEvent;
 
 void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf);
 void st_set_trace_file_enabled(bool enable);
commit fd068a953ccb54a00e7b1cf2d8961498c7d74bd4
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:47:49 2013 +0100

    trace: [default] Port to generic event information and new control interface
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/trace/default.c b/trace/default.c
index c9b27a2..6e07a47 100644
--- a/trace/default.c
+++ b/trace/default.c
@@ -1,7 +1,7 @@
 /*
  * Default implementation for backend initialization from commandline.
  *
- * Copyright (C) 2011 Lluís Vilanova <vilanova at ac.upc.edu>
+ * Copyright (C) 2011-2012 Lluís Vilanova <vilanova at ac.upc.edu>
  *
  * This work is licensed under the terms of the GNU GPL, version 2.  See
  * the COPYING file in the top-level directory.
@@ -18,11 +18,10 @@ void trace_print_events(FILE *stream, fprintf_function stream_printf)
                   "operation not supported with the current backend\n");
 }
 
-bool trace_event_set_state(const char *name, bool state)
+void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state)
 {
     fprintf(stderr, "warning: "
             "cannot set the state of a trace event with the current backend\n");
-    return false;
 }
 
 bool trace_backend_init(const char *events, const char *file)
commit ca285c3fca7c3d2b77b133e82f7a3592ccc7f5d3
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:47:43 2013 +0100

    trace: [monitor] Use new event control interface
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/monitor.c b/monitor.c
index 5dfae2a..4ec1db9 100644
--- a/monitor.c
+++ b/monitor.c
@@ -761,9 +761,18 @@ static void do_trace_event_set_state(Monitor *mon, const QDict *qdict)
 {
     const char *tp_name = qdict_get_str(qdict, "name");
     bool new_state = qdict_get_bool(qdict, "option");
-    int ret = trace_event_set_state(tp_name, new_state);
 
-    if (!ret) {
+    bool found = false;
+    TraceEvent *ev = NULL;
+    while ((ev = trace_event_pattern(tp_name, ev)) != NULL) {
+        found = true;
+        if (!trace_event_get_state_static(ev)) {
+            monitor_printf(mon, "event \"%s\" is not traceable\n", tp_name);
+        } else {
+            trace_event_set_state_dynamic(ev, new_state);
+        }
+    }
+    if (!trace_event_is_pattern(tp_name) && !found) {
         monitor_printf(mon, "unknown event name \"%s\"\n", tp_name);
     }
 }
commit b1bae816c4c0743e37ee9e797a503610c34e3073
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:47:38 2013 +0100

    trace: Provide a detailed event control interface
    
    This interface decouples event obtaining from interaction.
    
    Events can be obtained through three different methods:
    
    * identifier
    * name
    * simple wildcard pattern
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/docs/tracing.txt b/docs/tracing.txt
index 14db3bf..cf53c17 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -100,49 +100,37 @@ respectively.  This ensures portability between 32- and 64-bit platforms.
 
 == Generic interface and monitor commands ==
 
-You can programmatically query and control the dynamic state of trace events
-through a backend-agnostic interface:
+You can programmatically query and control the state of trace events through a
+backend-agnostic interface provided by the header "trace/control.h".
 
-* trace_print_events
+Note that some of the backends do not provide an implementation for some parts
+of this interface, in which case QEMU will just print a warning (please refer to
+header "trace/control.h" to see which routines are backend-dependent).
 
-* trace_event_set_state
-  Enables or disables trace events at runtime inside QEMU.
-  The function returns "true" if the state of the event has been successfully
-  changed, or "false" otherwise:
-
-    #include "trace/control.h"
-    
-    trace_event_set_state("virtio_irq", true); /* enable */
-    [...]
-    trace_event_set_state("virtio_irq", false); /* disable */
-
-Note that some of the backends do not provide an implementation for this
-interface, in which case QEMU will just print a warning.
-
-This functionality is also provided through monitor commands:
+The state of events can also be queried and modified through monitor commands:
 
 * info trace-events
   View available trace events and their state.  State 1 means enabled, state 0
   means disabled.
 
 * trace-event NAME on|off
-  Enable/disable a given trace event or a group of events having common prefix
-  through wildcard.
+  Enable/disable a given trace event or a group of events (using wildcards).
 
 The "-trace events=<file>" command line argument can be used to enable the
 events listed in <file> from the very beginning of the program. This file must
 contain one event name per line.
 
-A basic wildcard matching is supported in both the monitor command "trace
--event" and the events list file. That means you can enable/disable the events
-having a common prefix in a batch. For example, virtio-blk trace events could
-be enabled using:
-  trace-event virtio_blk_* on
-
 If a line in the "-trace events=<file>" file begins with a '-', the trace event
 will be disabled instead of enabled.  This is useful when a wildcard was used
 to enable an entire family of events but one noisy event needs to be disabled.
 
+Wildcard matching is supported in both the monitor command "trace-event" and the
+events list file. That means you can enable/disable the events having a common
+prefix in a batch. For example, virtio-blk trace events could be enabled using
+the following monitor command:
+
+    trace-event virtio_blk_* on
+
 == Trace backends ==
 
 The "tracetool" script automates tedious trace event code generation and also
@@ -263,3 +251,7 @@ guard such computations and avoid its compilation when the event is disabled:
         }
         return ptr;
     }
+
+You can check both if the event has been disabled and is dynamically enabled at
+the same time using the 'trace_event_get_state' routine (see header
+"trace/control.h" for more information).
diff --git a/trace/control-internal.h b/trace/control-internal.h
new file mode 100644
index 0000000..cce2da4
--- /dev/null
+++ b/trace/control-internal.h
@@ -0,0 +1,67 @@
+/*
+ * Interface for configuring and controlling the state of tracing events.
+ *
+ * Copyright (C) 2011-2012 Lluís Vilanova <vilanova at ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef TRACE__CONTROL_INTERNAL_H
+#define TRACE__CONTROL_INTERNAL_H
+
+#include <string.h>
+
+
+extern TraceEvent trace_events[];
+
+
+static inline TraceEvent *trace_event_id(TraceEventID id)
+{
+    assert(id < trace_event_count());
+    return &trace_events[id];
+}
+
+static inline TraceEventID trace_event_count(void)
+{
+    return TRACE_EVENT_COUNT;
+}
+
+static inline bool trace_event_is_pattern(const char *str)
+{
+    assert(str != NULL);
+    return strchr(str, '*') != NULL;
+}
+
+static inline TraceEventID trace_event_get_id(TraceEvent *ev)
+{
+    assert(ev != NULL);
+    return ev->id;
+}
+
+static inline const char * trace_event_get_name(TraceEvent *ev)
+{
+    assert(ev != NULL);
+    return ev->name;
+}
+
+static inline bool trace_event_get_state_static(TraceEvent *ev)
+{
+    assert(ev != NULL);
+    return ev->sstate;
+}
+
+static inline bool trace_event_get_state_dynamic(TraceEvent *ev)
+{
+    assert(ev != NULL);
+    return ev->dstate;
+}
+
+static inline void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
+{
+    assert(ev != NULL);
+    assert(trace_event_get_state_static(ev));
+    return trace_event_set_state_dynamic_backend(ev, state);
+}
+
+#endif  /* TRACE__CONTROL_INTERNAL_H */
diff --git a/trace/control.c b/trace/control.c
index be05efb..49f61e1 100644
--- a/trace/control.c
+++ b/trace/control.c
@@ -1,19 +1,86 @@
 /*
  * Interface for configuring and controlling the state of tracing events.
  *
- * Copyright (C) 2011 Lluís Vilanova <vilanova at ac.upc.edu>
+ * Copyright (C) 2011-2012 Lluís Vilanova <vilanova at ac.upc.edu>
  *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
  */
 
 #include "trace/control.h"
 
 
-void trace_backend_init_events(const char *fname)
+TraceEvent *trace_event_name(const char *name)
+{
+    assert(name != NULL);
+
+    TraceEventID i;
+    for (i = 0; i < trace_event_count(); i++) {
+        TraceEvent *ev = trace_event_id(i);
+        if (strcmp(trace_event_get_name(ev), name) == 0) {
+            return ev;
+        }
+    }
+    return NULL;
+}
+
+static bool pattern_glob(const char *pat, const char *ev)
+{
+    while (*pat != '\0' && *ev != '\0') {
+        if (*pat == *ev) {
+            pat++;
+            ev++;
+        }
+        else if (*pat == '*') {
+            if (pattern_glob(pat, ev+1)) {
+                return true;
+            } else if (pattern_glob(pat+1, ev)) {
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    while (*pat == '*') {
+        pat++;
+    }
+
+    if (*pat == '\0' && *ev == '\0') {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev)
 {
-    int ret;
+    assert(pat != NULL);
 
+    TraceEventID i;
+
+    if (ev == NULL) {
+        i = -1;
+    } else {
+        i = trace_event_get_id(ev);
+    }
+    i++;
+
+    while (i < trace_event_count()) {
+        TraceEvent *res = trace_event_id(i);
+        if (pattern_glob(pat, trace_event_get_name(res))) {
+            return res;
+        }
+        i++;
+    }
+
+    return NULL;
+}
+
+void trace_backend_init_events(const char *fname)
+{
     if (fname == NULL) {
         return;
     }
@@ -32,15 +99,28 @@ void trace_backend_init_events(const char *fname)
             if ('#' == line_buf[0]) { /* skip commented lines */
                 continue;
             }
-            if ('-' == line_buf[0]) {
-                ret = trace_event_set_state(line_buf+1, false);
+            const bool enable = ('-' != line_buf[0]);
+            char *line_ptr = enable ? line_buf : line_buf + 1;
+            if (trace_event_is_pattern(line_ptr)) {
+                TraceEvent *ev = NULL;
+                while ((ev = trace_event_pattern(line_ptr, ev)) != NULL) {
+                    if (trace_event_get_state_static(ev)) {
+                        trace_event_set_state_dynamic(ev, enable);
+                    }
+                }
             } else {
-                ret = trace_event_set_state(line_buf, true);
-            }
-            if (!ret) {
-                fprintf(stderr,
-                        "error: trace event '%s' does not exist\n", line_buf);
-                exit(1);
+                TraceEvent *ev = trace_event_name(line_ptr);
+                if (ev == NULL) {
+                    fprintf(stderr,
+                            "error: trace event '%s' does not exist\n", line_ptr);
+                    exit(1);
+                }
+                if (!trace_event_get_state_static(ev)) {
+                    fprintf(stderr,
+                            "error: trace event '%s' is not traceable\n", line_ptr);
+                    exit(1);
+                }
+                trace_event_set_state_dynamic(ev, enable);
             }
         }
     }
diff --git a/trace/control.h b/trace/control.h
index 2acaa42..cde8260 100644
--- a/trace/control.h
+++ b/trace/control.h
@@ -1,41 +1,193 @@
 /*
  * Interface for configuring and controlling the state of tracing events.
  *
- * Copyright (C) 2011 Lluís Vilanova <vilanova at ac.upc.edu>
+ * Copyright (C) 2011-2012 Lluís Vilanova <vilanova at ac.upc.edu>
  *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
  */
 
-#ifndef TRACE_CONTROL_H
-#define TRACE_CONTROL_H
+#ifndef TRACE__CONTROL_H
+#define TRACE__CONTROL_H
 
 #include "qemu-common.h"
+#include "trace/generated-events.h"
 
 
-/** Print the state of all events. */
-void trace_print_events(FILE *stream, fprintf_function stream_printf);
-/** Set the state of an event.
+/**
+ * TraceEventID:
+ *
+ * Unique tracing event identifier.
+ *
+ * These are named as 'TRACE_${EVENT_NAME}'.
+ *
+ * See also: "trace/generated-events.h"
+ */
+enum TraceEventID;
+
+/**
+ * trace_event_id:
+ * @id: Event identifier.
+ *
+ * Get an event by its identifier.
+ *
+ * This routine has a constant cost, as opposed to trace_event_name and
+ * trace_event_pattern.
+ *
+ * Pre-conditions: The identifier is valid.
+ *
+ * Returns: pointer to #TraceEvent.
+ *
+ */
+static TraceEvent *trace_event_id(TraceEventID id);
+
+/**
+ * trace_event_name:
+ * @id: Event name.
+ *
+ * Search an event by its name.
+ *
+ * Returns: pointer to #TraceEvent or NULL if not found.
+ */
+TraceEvent *trace_event_name(const char *name);
+
+/**
+ * trace_event_pattern:
+ * @pat: Event name pattern.
+ * @ev: Event to start searching from (not included).
+ *
+ * Get all events with a given name pattern.
+ *
+ * Returns: pointer to #TraceEvent or NULL if not found.
+ */
+TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev);
+
+/**
+ * trace_event_is_pattern:
+ *
+ * Whether the given string is an event name pattern.
+ */
+static bool trace_event_is_pattern(const char *str);
+
+/**
+ * trace_event_count:
+ *
+ * Return the number of events.
+ */
+static TraceEventID trace_event_count(void);
+
+
+
+/**
+ * trace_event_get_id:
+ *
+ * Get the identifier of an event.
+ */
+static TraceEventID trace_event_get_id(TraceEvent *ev);
+
+/**
+ * trace_event_get_name:
  *
- * @return Whether the state changed.
+ * Get the name of an event.
  */
-bool trace_event_set_state(const char *name, bool state);
+static const char * trace_event_get_name(TraceEvent *ev);
 
+/**
+ * trace_event_get_state:
+ * @id: Event identifier.
+ *
+ * Get the tracing state of an event (both static and dynamic).
+ *
+ * If the event has the disabled property, the check will have no performance
+ * impact.
+ *
+ * As a down side, you must always use an immediate #TraceEventID value.
+ */
+#define trace_event_get_state(id)                       \
+    ((id ##_ENABLED) && trace_event_get_state_dynamic(trace_event_id(id)))
+
+/**
+ * trace_event_get_state_static:
+ * @id: Event identifier.
+ *
+ * Get the static tracing state of an event.
+ *
+ * Use the define 'TRACE_${EVENT_NAME}_ENABLED' for compile-time checks (it will
+ * be set to 1 or 0 according to the presence of the disabled property).
+ */
+static bool trace_event_get_state_static(TraceEvent *ev);
+
+/**
+ * trace_event_get_state_dynamic:
+ *
+ * Get the dynamic tracing state of an event.
+ */
+static bool trace_event_get_state_dynamic(TraceEvent *ev);
+
+/**
+ * trace_event_set_state:
+ *
+ * Set the tracing state of an event (only if possible).
+ */
+#define trace_event_set_state(id, state)                \
+    do {                                                \
+        if ((id ##_ENABLED)) {                          \
+            TraceEvent *_e = trace_event_id(id);        \
+            trace_event_set_state_dynamic(_e, state);   \
+        }                                               \
+    } while (0)
+
+/**
+ * trace_event_set_state_dynamic:
+ *
+ * Set the dynamic tracing state of an event.
+ *
+ * Pre-condition: trace_event_get_state_static(ev) == true
+ */
+static void trace_event_set_state_dynamic(TraceEvent *ev, bool state);
+
+/**
+ * trace_event_set_state_dynamic_backend:
+ *
+ * Warning: This function must be implemented by each tracing backend.
+ */
+void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state);
+
+
+
+/**
+ * trace_print_events:
+ *
+ * Print the state of all events.
+ *
+ * Warning: This function must be implemented by each tracing backend.
+ */
+void trace_print_events(FILE *stream, fprintf_function stream_printf);
 
-/** Initialize the tracing backend.
+/**
+ * trace_backend_init:
+ * @events: Name of file with events to be enabled at startup; may be NULL.
+ *          Corresponds to commandline option "-trace events=...".
+ * @file:   Name of trace output file; may be NULL.
+ *          Corresponds to commandline option "-trace file=...".
  *
- * @events Name of file with events to be enabled at startup; may be NULL.
- *         Corresponds to commandline option "-trace events=...".
- * @file   Name of trace output file; may be NULL.
- *         Corresponds to commandline option "-trace file=...".
- * @return Whether the backend could be successfully initialized.
+ * Initialize the tracing backend.
+ *
+ * Warning: This function must be implemented by each tracing backend.
+ *
+ * Returns: Whether the backend could be successfully initialized.
  */
 bool trace_backend_init(const char *events, const char *file);
 
-/** Generic function to initialize the state of events.
+/**
+ * trace_backend_init_events:
+ * @fname: Name of file with events to enable; may be NULL.
  *
- * @fname Name of file with events to enable; may be NULL.
+ * Generic function to initialize the state of events.
  */
 void trace_backend_init_events(const char *fname);
 
-#endif  /* TRACE_CONTROL_H */
+
+#include "trace/control-internal.h"
+
+#endif  /* TRACE__CONTROL_H */
commit 45be2f5d0dcdd314cd0c70a11220e5e09a44d654
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:47:32 2013 +0100

    trace: Provide a generic tracing event descriptor
    
    Uses tracetool to generate a backend-independent tracing event description
    (struct TraceEvent).
    
    The values for such structure are generated with the non-public "events"
    backend ("events-c" frontend).
    
    The generation of the defines to check if an event is statically enabled is also
    moved to the "events" backend ("events-h" frontend).
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/Makefile b/Makefile
index 6915178..80344d9 100644
--- a/Makefile
+++ b/Makefile
@@ -35,6 +35,9 @@ GENERATED_HEADERS = config-host.h qemu-options.def
 GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
 GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
 
+GENERATED_HEADERS += trace/generated-events.h
+GENERATED_SOURCES += trace/generated-events.c
+
 GENERATED_HEADERS += trace/generated-tracers.h
 ifeq ($(TRACE_BACKEND),dtrace)
 GENERATED_HEADERS += trace/generated-tracers-dtrace.h
diff --git a/scripts/tracetool/backend/events.py b/scripts/tracetool/backend/events.py
new file mode 100644
index 0000000..5afce3e
--- /dev/null
+++ b/scripts/tracetool/backend/events.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generic event description.
+
+This is a dummy backend to establish appropriate frontend/backend compatibility
+checks.
+"""
+
+__author__     = "Lluís Vilanova <vilanova at ac.upc.edu>"
+__copyright__  = "Copyright 2012, Lluís Vilanova <vilanova at ac.upc.edu>"
+__license__    = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__      = "stefanha at linux.vnet.ibm.com"
+
+
+def events_h(events):
+    pass
+
+def events_c(events):
+    pass
diff --git a/scripts/tracetool/format/events_c.py b/scripts/tracetool/format/events_c.py
new file mode 100644
index 0000000..d670ec8
--- /dev/null
+++ b/scripts/tracetool/format/events_c.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .c for event description.
+"""
+
+__author__     = "Lluís Vilanova <vilanova at ac.upc.edu>"
+__copyright__  = "Copyright 2012, Lluís Vilanova <vilanova at ac.upc.edu>"
+__license__    = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__      = "stefanha at linux.vnet.ibm.com"
+
+
+from tracetool import out
+
+
+def begin(events):
+    out('/* This file is autogenerated by tracetool, do not edit. */',
+        '',
+        '#include "trace.h"',
+        '#include "trace/generated-events.h"',
+        '#include "trace/control.h"',
+        '',
+        )
+
+    out('TraceEvent trace_events[TRACE_EVENT_COUNT] = {')
+
+    for e in events:
+        out('    { .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0 },',
+            id = "TRACE_" + e.name.upper(),
+            name = e.name,
+            sstate = "TRACE_%s_ENABLED" % e.name.upper(),
+            )
+
+    out('};',
+        '',
+        )
diff --git a/scripts/tracetool/format/events_h.py b/scripts/tracetool/format/events_h.py
new file mode 100644
index 0000000..d30ccea
--- /dev/null
+++ b/scripts/tracetool/format/events_h.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Generate .h for event description.
+"""
+
+__author__     = "Lluís Vilanova <vilanova at ac.upc.edu>"
+__copyright__  = "Copyright 2012, Lluís Vilanova <vilanova at ac.upc.edu>"
+__license__    = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__      = "stefanha at linux.vnet.ibm.com"
+
+
+from tracetool import out
+
+
+def begin(events):
+    out('/* This file is autogenerated by tracetool, do not edit. */',
+        '',
+        '#ifndef TRACE__GENERATED_EVENTS_H',
+        '#define TRACE__GENERATED_EVENTS_H',
+        '',
+        '#include <stdbool.h>',
+        ''
+        )
+
+    # event identifiers
+    out('typedef enum {')
+
+    for e in events:
+        out('    TRACE_%s,' % e.name.upper())
+
+    out('    TRACE_EVENT_COUNT',
+        '} TraceEventID;',
+        )
+
+    # static state
+    for e in events:
+        if 'disable' in e.properties:
+            enabled = 0
+        else:
+            enabled = 1
+        out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled))
+
+    out('#include "trace/event-internal.h"',
+        '',
+        '#endif  /* TRACE__GENERATED_EVENTS_H */',
+        )
diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py
index 9a58de1..93132fc 100644
--- a/scripts/tracetool/format/h.py
+++ b/scripts/tracetool/format/h.py
@@ -25,14 +25,7 @@ def begin(events):
         '#include "qemu-common.h"')
 
 def end(events):
-    for e in events:
-        if "disable" in e.properties:
-            enabled = 0
-        else:
-            enabled = 1
-        out('#define TRACE_%s_ENABLED %d' % (e.name.upper(), enabled))
-    out('',
-        '#endif /* TRACE__GENERATED_TRACERS_H */')
+    out('#endif /* TRACE__GENERATED_TRACERS_H */')
 
 def nop(events):
     for e in events:
diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index dde9d57..156aa25 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -1,7 +1,29 @@
 # -*- mode: makefile -*-
 
 ######################################################################
-# Auto-generated header for tracing routines
+# Auto-generated event descriptions
+
+$(obj)/generated-events.h: $(obj)/generated-events.h-timestamp
+$(obj)/generated-events.h-timestamp: $(SRC_PATH)/trace-events
+	$(call quiet-command,$(TRACETOOL) \
+		--format=events-h \
+		--backend=events \
+		< $< > $@,"  GEN   $(patsubst %-timestamp,%,$@)")
+	@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+
+$(obj)/generated-events.c: $(obj)/generated-events.c-timestamp
+$(obj)/generated-events.c-timestamp: $(SRC_PATH)/trace-events
+	$(call quiet-command,$(TRACETOOL) \
+		--format=events-c \
+		--backend=events \
+		< $< > $@,"  GEN   $(patsubst %-timestamp,%,$@)")
+	@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
+
+util-obj-y += generated-events.o
+
+
+######################################################################
+# Auto-generated tracing routines
 
 $(obj)/generated-tracers.h: $(obj)/generated-tracers.h-timestamp
 	@cmp -s $< $@ || cp $< $@
diff --git a/trace/event-internal.h b/trace/event-internal.h
new file mode 100644
index 0000000..b2310d9
--- /dev/null
+++ b/trace/event-internal.h
@@ -0,0 +1,33 @@
+/*
+ * Interface for configuring and controlling the state of tracing events.
+ *
+ * Copyright (C) 2012 Lluís Vilanova <vilanova at ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef TRACE__EVENT_INTERNAL_H
+#define TRACE__EVENT_INTERNAL_H
+
+#include "trace/generated-events.h"
+
+
+/**
+ * TraceEvent:
+ * @id: Unique event identifier.
+ * @name: Event name.
+ * @sstate: Static tracing state.
+ * @dstate: Dynamic tracing state.
+ *
+ * Opaque generic description of a tracing event.
+ */
+typedef struct TraceEvent {
+    TraceEventID id;
+    const char * name;
+    const bool sstate;
+    bool dstate;
+} TraceEvent;
+
+
+#endif  /* TRACE__EVENT_INTERNAL_H */
commit 93fba1618ddbbef8bedd8d684cf356586c94bbb1
Author: Lluís Vilanova <vilanova at ac.upc.edu>
Date:   Tue Mar 5 14:47:26 2013 +0100

    trace: [tracetool] Explicitly identify public backends
    
    Public backends are those printed by "--list-backends" and thus considered valid
    by the configure script.
    
    Signed-off-by: Lluís Vilanova <vilanova at ac.upc.edu>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index c003cf6..a79ec0f 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -90,8 +90,8 @@ def main(args):
             arg_format = arg
 
         elif opt == "--list-backends":
-            backends = tracetool.backend.get_list()
-            out(", ".join([ b for b,_ in backends ]))
+            public_backends = tracetool.backend.get_list(only_public = True)
+            out(", ".join([ b for b,_ in public_backends ]))
             sys.exit(0)
         elif opt == "--check-backend":
             check_backend = True
diff --git a/scripts/tracetool/backend/__init__.py b/scripts/tracetool/backend/__init__.py
index be43472..f0314ee 100644
--- a/scripts/tracetool/backend/__init__.py
+++ b/scripts/tracetool/backend/__init__.py
@@ -17,6 +17,16 @@ considered its short description.
 All backends must generate their contents through the 'tracetool.out' routine.
 
 
+Backend attributes
+------------------
+
+========= ====================================================================
+Attribute Description
+========= ====================================================================
+PUBLIC    If exists and is set to 'True', the backend is considered "public".
+========= ====================================================================
+
+
 Backend functions
 -----------------
 
@@ -42,7 +52,7 @@ import os
 import tracetool
 
 
-def get_list():
+def get_list(only_public = False):
     """Get a list of (name, description) pairs."""
     res = [("nop", "Tracing disabled.")]
     modnames = []
@@ -57,6 +67,10 @@ def get_list():
             continue
         module = module[1]
 
+        public = getattr(module, "PUBLIC", False)
+        if only_public and not public:
+            continue
+
         doc = module.__doc__
         if doc is None:
             doc = ""
diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py
index ad5eb3b..e31bc79 100644
--- a/scripts/tracetool/backend/dtrace.py
+++ b/scripts/tracetool/backend/dtrace.py
@@ -16,6 +16,9 @@ __email__      = "stefanha at linux.vnet.ibm.com"
 from tracetool import out
 
 
+PUBLIC = True
+
+
 PROBEPREFIX = None
 
 def _probeprefix():
diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py
index e4b4a7f..ac864f3 100644
--- a/scripts/tracetool/backend/simple.py
+++ b/scripts/tracetool/backend/simple.py
@@ -15,6 +15,10 @@ __email__      = "stefanha at linux.vnet.ibm.com"
 
 from tracetool import out
 
+
+PUBLIC = True
+
+
 def is_string(arg):
     strtype = ('const char*', 'char*', 'const char *', 'char *')
     if arg.lstrip().startswith(strtype):
diff --git a/scripts/tracetool/backend/stderr.py b/scripts/tracetool/backend/stderr.py
index 917fde7..a10fbb8 100644
--- a/scripts/tracetool/backend/stderr.py
+++ b/scripts/tracetool/backend/stderr.py
@@ -16,6 +16,9 @@ __email__      = "stefanha at linux.vnet.ibm.com"
 from tracetool import out
 
 
+PUBLIC = True
+
+
 def c(events):
     out('#include "trace.h"',
         '',
diff --git a/scripts/tracetool/backend/ust.py b/scripts/tracetool/backend/ust.py
index 31a2ff0..ea36995 100644
--- a/scripts/tracetool/backend/ust.py
+++ b/scripts/tracetool/backend/ust.py
@@ -16,6 +16,9 @@ __email__      = "stefanha at linux.vnet.ibm.com"
 from tracetool import out
 
 
+PUBLIC = True
+
+
 def c(events):
     out('#include <ust/marker.h>',
         '#undef mutex_lock',
commit 5d186eb03eb37b257e29a4731ca484362d5fc4e4
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 27 17:28:18 2013 +0100

    block: Fix direct use of protocols as driver for bdrv_open()
    
    bdrv_open_common() implements direct use of protocols by copying the
    pre-opened BlockDriverStates to bs using bdrv_swap(). It did however
    first set some fields in bs, which end up in file after the swap. When
    bdrv_open() destroys file, it appears to be open, and because it isn't,
    qemu could segfault while trying to close it.
    
    Reorder the operations to return immediately in such cases so that file
    is correctly detected as closed.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block.c b/block.c
index 16a92a4..0ae2e93 100644
--- a/block.c
+++ b/block.c
@@ -680,6 +680,18 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
 
     trace_bdrv_open_common(bs, filename, flags, drv->format_name);
 
+    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
+        return -ENOTSUP;
+    }
+
+    /* bdrv_open() with directly using a protocol as drv. This layer is already
+     * opened, so assign it to bs (while file becomes a closed BlockDriverState)
+     * and return immediately. */
+    if (file != NULL && drv->bdrv_file_open) {
+        bdrv_swap(file, bs);
+        return 0;
+    }
+
     bs->open_flags = flags;
     bs->buffer_alignment = 512;
 
@@ -694,10 +706,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
         bs->filename[0] = '\0';
     }
 
-    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
-        return -ENOTSUP;
-    }
-
     bs->drv = drv;
     bs->opaque = g_malloc0(drv->instance_size);
 
@@ -708,13 +716,9 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file,
 
     /* Open the image, either directly or using a protocol */
     if (drv->bdrv_file_open) {
-        if (file != NULL) {
-            bdrv_swap(file, bs);
-            ret = 0;
-        } else {
-            assert(drv->bdrv_parse_filename || filename != NULL);
-            ret = drv->bdrv_file_open(bs, filename, options, open_flags);
-        }
+        assert(file == NULL);
+        assert(drv->bdrv_parse_filename || filename != NULL);
+        ret = drv->bdrv_file_open(bs, filename, options, open_flags);
     } else {
         assert(file != NULL);
         bs->file = file;
commit ecdd5333ab9ed3f2b848066aaaef02c027b25e36
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Mar 27 11:43:49 2013 +0100

    qcow2: Gather clusters in a looping loop
    
    Instead of just checking once in exactly this order if there are
    dependendies, non-COW clusters and new allocation, this starts looping
    around these. This way we can, for example, gather non-COW clusters after
    new allocations as long as the host cluster offsets stay contiguous.
    
    Once handle_dependencies() is extended so that COW areas of in-flight
    allocations can be overwritten, this allows to continue with gathering
    other clusters (we wouldn't be able to do that without this change
    because we would have missed a possible second dependency in one of the
    next clusters).
    
    This means that in the typical sequential write case, we can combine the
    COW overwrite of one cluster with the allocation of the next cluster as
    soon as something like Delayed COW gets actually implemented. It is only
    by avoiding splitting requests this way that Delayed COW actually starts
    improving performance noticably.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 960d446..c71470a 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -770,7 +770,7 @@ out:
  *           must start over anyway, so consider *cur_bytes undefined.
  */
 static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
-    uint64_t *cur_bytes)
+    uint64_t *cur_bytes, QCowL2Meta **m)
 {
     BDRVQcowState *s = bs->opaque;
     QCowL2Meta *old_alloc;
@@ -793,6 +793,15 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
                 bytes = 0;
             }
 
+            /* Stop if already an l2meta exists. After yielding, it wouldn't
+             * be valid any more, so we'd have to clean up the old L2Metas
+             * and deal with requests depending on them before starting to
+             * gather new ones. Not worth the trouble. */
+            if (bytes == 0 && *m) {
+                *cur_bytes = 0;
+                return 0;
+            }
+
             if (bytes == 0) {
                 /* Wait for the dependency to complete. We need to recheck
                  * the free/allocated clusters when we continue. */
@@ -1023,16 +1032,16 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
         nb_clusters = count_cow_clusters(s, nb_clusters, l2_table, l2_index);
     }
 
+    /* This function is only called when there were no non-COW clusters, so if
+     * we can't find any unallocated or COW clusters either, something is
+     * wrong with our code. */
+    assert(nb_clusters > 0);
+
     ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
     if (ret < 0) {
         return ret;
     }
 
-    if (nb_clusters == 0) {
-        *bytes = 0;
-        return 0;
-    }
-
     /* Allocate, if necessary at a given offset in the image file */
     alloc_cluster_offset = start_of_cluster(s, *host_offset);
     ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,
@@ -1146,8 +1155,27 @@ again:
     remaining = (n_end - n_start) << BDRV_SECTOR_BITS;
     cluster_offset = 0;
     *host_offset = 0;
+    cur_bytes = 0;
+    *m = NULL;
 
     while (true) {
+
+        if (!*host_offset) {
+            *host_offset = start_of_cluster(s, cluster_offset);
+        }
+
+        assert(remaining >= cur_bytes);
+
+        start           += cur_bytes;
+        remaining       -= cur_bytes;
+        cluster_offset  += cur_bytes;
+
+        if (remaining == 0) {
+            break;
+        }
+
+        cur_bytes = remaining;
+
         /*
          * Now start gathering as many contiguous clusters as possible:
          *
@@ -1166,12 +1194,17 @@ again:
          *         the right synchronisation between the in-flight request and
          *         the new one.
          */
-        cur_bytes = remaining;
-        ret = handle_dependencies(bs, start, &cur_bytes);
+        ret = handle_dependencies(bs, start, &cur_bytes, m);
         if (ret == -EAGAIN) {
+            /* Currently handle_dependencies() doesn't yield if we already had
+             * an allocation. If it did, we would have to clean up the L2Meta
+             * structs before starting over. */
+            assert(*m == NULL);
             goto again;
         } else if (ret < 0) {
             return ret;
+        } else if (cur_bytes == 0) {
+            break;
         } else {
             /* handle_dependencies() may have decreased cur_bytes (shortened
              * the allocations below) so that the next dependency is processed
@@ -1185,24 +1218,11 @@ again:
         if (ret < 0) {
             return ret;
         } else if (ret) {
-            if (!*host_offset) {
-                *host_offset = start_of_cluster(s, cluster_offset);
-            }
-
-            start           += cur_bytes;
-            remaining       -= cur_bytes;
-            cluster_offset  += cur_bytes;
-
-            cur_bytes = remaining;
+            continue;
         } else if (cur_bytes == 0) {
             break;
         }
 
-        /* If there is something left to allocate, do that now */
-        if (remaining == 0) {
-            break;
-        }
-
         /*
          * 3. If the request still hasn't completed, allocate new clusters,
          *    considering any cluster_offset of steps 1c or 2.
@@ -1211,15 +1231,7 @@ again:
         if (ret < 0) {
             return ret;
         } else if (ret) {
-            if (!*host_offset) {
-                *host_offset = start_of_cluster(s, cluster_offset);
-            }
-
-            start           += cur_bytes;
-            remaining       -= cur_bytes;
-            cluster_offset  += cur_bytes;
-
-            break;
+            continue;
         } else {
             assert(cur_bytes == 0);
             break;
diff --git a/tests/qemu-iotests/044.out b/tests/qemu-iotests/044.out
index 34c25c7..5c5aa92 100644
--- a/tests/qemu-iotests/044.out
+++ b/tests/qemu-iotests/044.out
@@ -1,6 +1,6 @@
 No errors were found on the image.
 7292415/33554432 = 21.73% allocated, 0.00% fragmented, 0.00% compressed clusters
-Image end offset: 4296447488
+Image end offset: 4296448000
 .
 ----------------------------------------------------------------------
 Ran 1 tests
commit 2c3b32d25620c26e26fd590c198ec6d9cf91da57
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:12 2013 +0100

    qcow2: Move cluster gathering to a non-looping loop
    
    This patch is mainly to separate the indentation change from the
    semantic changes. All that really changes here is that everything moves
    into a while loop, all 'goto done' become 'break' and at the end of the
    loop a new 'break is inserted.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 6dc7f7f..960d446 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1147,79 +1147,85 @@ again:
     cluster_offset = 0;
     *host_offset = 0;
 
-    /*
-     * Now start gathering as many contiguous clusters as possible:
-     *
-     * 1. Check for overlaps with in-flight allocations
-     *
-     *      a) Overlap not in the first cluster -> shorten this request and let
-     *         the caller handle the rest in its next loop iteration.
-     *
-     *      b) Real overlaps of two requests. Yield and restart the search for
-     *         contiguous clusters (the situation could have changed while we
-     *         were sleeping)
-     *
-     *      c) TODO: Request starts in the same cluster as the in-flight
-     *         allocation ends. Shorten the COW of the in-fight allocation, set
-     *         cluster_offset to write to the same cluster and set up the right
-     *         synchronisation between the in-flight request and the new one.
-     */
-    cur_bytes = remaining;
-    ret = handle_dependencies(bs, start, &cur_bytes);
-    if (ret == -EAGAIN) {
-        goto again;
-    } else if (ret < 0) {
-        return ret;
-    } else {
-        /* handle_dependencies() may have decreased cur_bytes (shortened
-         * the allocations below) so that the next dependency is processed
-         * correctly during the next loop iteration. */
-    }
-
-    /*
-     * 2. Count contiguous COPIED clusters.
-     */
-    ret = handle_copied(bs, start, &cluster_offset, &cur_bytes, m);
-    if (ret < 0) {
-        return ret;
-    } else if (ret) {
-        if (!*host_offset) {
-            *host_offset = start_of_cluster(s, cluster_offset);
+    while (true) {
+        /*
+         * Now start gathering as many contiguous clusters as possible:
+         *
+         * 1. Check for overlaps with in-flight allocations
+         *
+         *      a) Overlap not in the first cluster -> shorten this request and
+         *         let the caller handle the rest in its next loop iteration.
+         *
+         *      b) Real overlaps of two requests. Yield and restart the search
+         *         for contiguous clusters (the situation could have changed
+         *         while we were sleeping)
+         *
+         *      c) TODO: Request starts in the same cluster as the in-flight
+         *         allocation ends. Shorten the COW of the in-fight allocation,
+         *         set cluster_offset to write to the same cluster and set up
+         *         the right synchronisation between the in-flight request and
+         *         the new one.
+         */
+        cur_bytes = remaining;
+        ret = handle_dependencies(bs, start, &cur_bytes);
+        if (ret == -EAGAIN) {
+            goto again;
+        } else if (ret < 0) {
+            return ret;
+        } else {
+            /* handle_dependencies() may have decreased cur_bytes (shortened
+             * the allocations below) so that the next dependency is processed
+             * correctly during the next loop iteration. */
         }
 
-        start           += cur_bytes;
-        remaining       -= cur_bytes;
-        cluster_offset  += cur_bytes;
+        /*
+         * 2. Count contiguous COPIED clusters.
+         */
+        ret = handle_copied(bs, start, &cluster_offset, &cur_bytes, m);
+        if (ret < 0) {
+            return ret;
+        } else if (ret) {
+            if (!*host_offset) {
+                *host_offset = start_of_cluster(s, cluster_offset);
+            }
 
-        cur_bytes = remaining;
-    } else if (cur_bytes == 0) {
-        goto done;
-    }
+            start           += cur_bytes;
+            remaining       -= cur_bytes;
+            cluster_offset  += cur_bytes;
 
-    /* If there is something left to allocate, do that now */
-    if (remaining == 0) {
-        goto done;
-    }
+            cur_bytes = remaining;
+        } else if (cur_bytes == 0) {
+            break;
+        }
 
-    /*
-     * 3. If the request still hasn't completed, allocate new clusters,
-     *    considering any cluster_offset of steps 1c or 2.
-     */
-    ret = handle_alloc(bs, start, &cluster_offset, &cur_bytes, m);
-    if (ret < 0) {
-        return ret;
-    } else if (ret) {
-        if (!*host_offset) {
-            *host_offset = start_of_cluster(s, cluster_offset);
+        /* If there is something left to allocate, do that now */
+        if (remaining == 0) {
+            break;
         }
 
-        start           += cur_bytes;
-        remaining       -= cur_bytes;
-        cluster_offset  += cur_bytes;
+        /*
+         * 3. If the request still hasn't completed, allocate new clusters,
+         *    considering any cluster_offset of steps 1c or 2.
+         */
+        ret = handle_alloc(bs, start, &cluster_offset, &cur_bytes, m);
+        if (ret < 0) {
+            return ret;
+        } else if (ret) {
+            if (!*host_offset) {
+                *host_offset = start_of_cluster(s, cluster_offset);
+            }
+
+            start           += cur_bytes;
+            remaining       -= cur_bytes;
+            cluster_offset  += cur_bytes;
+
+            break;
+        } else {
+            assert(cur_bytes == 0);
+            break;
+        }
     }
 
-    /* Some cleanup work */
-done:
     *num = (n_end - n_start) - (remaining >> BDRV_SECTOR_BITS);
     assert(*num > 0);
     assert(*host_offset != 0);
commit 88c6588c5165da1526f735ed850861c5b74670bd
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:11 2013 +0100

    qcow2: Allow requests with multiple l2metas
    
    Instead of expecting a single l2meta, have a list of them. This allows
    to still have a single I/O request for the guest data, even though
    multiple l2meta may be needed in order to describe both a COW overwrite
    and a new cluster allocation (typical sequential write case).
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 78e7db9..6dc7f7f 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1069,10 +1069,13 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     int alloc_n_start = offset_into_cluster(s, guest_offset)
                         >> BDRV_SECTOR_BITS;
     int nb_sectors = MIN(requested_sectors, avail_sectors);
+    QCowL2Meta *old_m = *m;
 
     *m = g_malloc0(sizeof(**m));
 
     **m = (QCowL2Meta) {
+        .next           = old_m,
+
         .alloc_offset   = alloc_cluster_offset,
         .offset         = start_of_cluster(s, guest_offset),
         .nb_clusters    = nb_clusters,
diff --git a/block/qcow2.c b/block/qcow2.c
index 3f7edf5..7e7d775 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -858,7 +858,9 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
             goto fail;
         }
 
-        if (l2meta != NULL) {
+        while (l2meta != NULL) {
+            QCowL2Meta *next;
+
             ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
             if (ret < 0) {
                 goto fail;
@@ -871,8 +873,9 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
 
             qemu_co_queue_restart_all(&l2meta->dependent_requests);
 
+            next = l2meta->next;
             g_free(l2meta);
-            l2meta = NULL;
+            l2meta = next;
         }
 
         remaining_sectors -= cur_nr_sectors;
@@ -885,12 +888,17 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
 fail:
     qemu_co_mutex_unlock(&s->lock);
 
-    if (l2meta != NULL) {
+    while (l2meta != NULL) {
+        QCowL2Meta *next;
+
         if (l2meta->nb_clusters != 0) {
             QLIST_REMOVE(l2meta, next_in_flight);
         }
         qemu_co_queue_restart_all(&l2meta->dependent_requests);
+
+        next = l2meta->next;
         g_free(l2meta);
+        l2meta = next;
     }
 
     qemu_iovec_destroy(&hd_qiov);
diff --git a/block/qcow2.h b/block/qcow2.h
index 32806bd..bf8db2a 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -250,6 +250,9 @@ typedef struct QCowL2Meta
      */
     Qcow2COWRegion cow_end;
 
+    /** Pointer to next L2Meta of the same write request */
+    struct QCowL2Meta *next;
+
     QLIST_ENTRY(QCowL2Meta) next_in_flight;
 } QCowL2Meta;
 
commit 710c2496d8cecc92568d439a3cf9d5874b3a55e2
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:10 2013 +0100

    qcow2: Use byte granularity in qcow2_alloc_cluster_offset()
    
    This gets rid of the nb_clusters and keep_clusters and the associated
    complicated calculations. Just advance the number of bytes that have
    been processed and everything is fine.
    
    This patch advances the variables even after the last operation even
    though they aren't used any more afterwards to make things look more
    uniform. A later patch will turn the whole thing into a loop and then
    it actually starts making sense.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 4f43d41..78e7db9 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -1127,28 +1127,24 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
     int n_start, int n_end, int *num, uint64_t *host_offset, QCowL2Meta **m)
 {
     BDRVQcowState *s = bs->opaque;
-    int l2_index, ret, sectors;
-    unsigned int nb_clusters, keep_clusters;
+    uint64_t start, remaining;
     uint64_t cluster_offset;
     uint64_t cur_bytes;
+    int ret;
 
     trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset,
                                       n_start, n_end);
 
+    assert(n_start * BDRV_SECTOR_SIZE == offset_into_cluster(s, offset));
+    offset = start_of_cluster(s, offset);
+
 again:
+    start = offset + (n_start << BDRV_SECTOR_BITS);
+    remaining = (n_end - n_start) << BDRV_SECTOR_BITS;
     cluster_offset = 0;
     *host_offset = 0;
 
     /*
-     * Calculate the number of clusters to look for. We stop at L2 table
-     * boundaries to keep things simple.
-     */
-    l2_index = offset_to_l2_index(s, offset);
-    nb_clusters = MIN(size_to_clusters(s, n_end << BDRV_SECTOR_BITS),
-                      s->l2_size - l2_index);
-    n_end = MIN(n_end, nb_clusters * s->cluster_sectors);
-
-    /*
      * Now start gathering as many contiguous clusters as possible:
      *
      * 1. Check for overlaps with in-flight allocations
@@ -1165,8 +1161,8 @@ again:
      *         cluster_offset to write to the same cluster and set up the right
      *         synchronisation between the in-flight request and the new one.
      */
-    cur_bytes = (n_end - n_start) * BDRV_SECTOR_SIZE;
-    ret = handle_dependencies(bs, offset, &cur_bytes);
+    cur_bytes = remaining;
+    ret = handle_dependencies(bs, start, &cur_bytes);
     if (ret == -EAGAIN) {
         goto again;
     } else if (ret < 0) {
@@ -1177,33 +1173,28 @@ again:
          * correctly during the next loop iteration. */
     }
 
-    nb_clusters = size_to_clusters(s, offset + cur_bytes)
-                - (offset >> s->cluster_bits);
-
     /*
      * 2. Count contiguous COPIED clusters.
      */
-    uint64_t tmp_bytes = cur_bytes;
-    ret = handle_copied(bs, offset, &cluster_offset, &tmp_bytes, m);
+    ret = handle_copied(bs, start, &cluster_offset, &cur_bytes, m);
     if (ret < 0) {
         return ret;
     } else if (ret) {
-        keep_clusters =
-            size_to_clusters(s, tmp_bytes + offset_into_cluster(s, offset));
-        nb_clusters -= keep_clusters;
-
         if (!*host_offset) {
             *host_offset = start_of_cluster(s, cluster_offset);
         }
+
+        start           += cur_bytes;
+        remaining       -= cur_bytes;
+        cluster_offset  += cur_bytes;
+
+        cur_bytes = remaining;
     } else if (cur_bytes == 0) {
-        keep_clusters = 0;
         goto done;
-    } else {
-        keep_clusters = 0;
     }
 
     /* If there is something left to allocate, do that now */
-    if (nb_clusters == 0) {
+    if (remaining == 0) {
         goto done;
     }
 
@@ -1211,43 +1202,24 @@ again:
      * 3. If the request still hasn't completed, allocate new clusters,
      *    considering any cluster_offset of steps 1c or 2.
      */
-    int alloc_n_start;
-    int alloc_n_end;
-
-    if (keep_clusters != 0) {
-        offset         = start_of_cluster(s, offset
-                                             + keep_clusters * s->cluster_size);
-        cluster_offset = start_of_cluster(s, cluster_offset
-                                             + keep_clusters * s->cluster_size);
-
-        alloc_n_start = 0;
-        alloc_n_end = n_end - keep_clusters * s->cluster_sectors;
-    } else {
-        alloc_n_start = n_start;
-        alloc_n_end = n_end;
-    }
-
-    cur_bytes = MIN(cur_bytes, ((alloc_n_end - alloc_n_start) << BDRV_SECTOR_BITS));
-
-    ret = handle_alloc(bs, offset, &cluster_offset, &cur_bytes, m);
+    ret = handle_alloc(bs, start, &cluster_offset, &cur_bytes, m);
     if (ret < 0) {
         return ret;
-    }
+    } else if (ret) {
+        if (!*host_offset) {
+            *host_offset = start_of_cluster(s, cluster_offset);
+        }
 
-    if (!*host_offset) {
-        *host_offset = start_of_cluster(s, cluster_offset);
+        start           += cur_bytes;
+        remaining       -= cur_bytes;
+        cluster_offset  += cur_bytes;
     }
-    nb_clusters = size_to_clusters(s, cur_bytes + offset_into_cluster(s, offset));
 
     /* Some cleanup work */
 done:
-    sectors = (keep_clusters + nb_clusters) << (s->cluster_bits - 9);
-    if (sectors > n_end) {
-        sectors = n_end;
-    }
-
-    assert(sectors > n_start);
-    *num = sectors - n_start;
+    *num = (n_end - n_start) - (remaining >> BDRV_SECTOR_BITS);
+    assert(*num > 0);
+    assert(*host_offset != 0);
 
     return 0;
 }
commit 411d62b04b4cd2d3a6cea310689dbafa2479bc28
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:09 2013 +0100

    qcow2: Prepare handle_alloc/copied() for byte granularity
    
    This makes handle_alloc() and handle_copied() return byte-granularity
    host offsets instead of returning always the cluster start. This is
    required so that qcow2_alloc_cluster_offset() can stop aligning
    everything to cluster boundaries.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 239a997..4f43d41 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -817,7 +817,9 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
  * *host_offset is not zero, only physically contiguous clusters beginning at
  * this host offset are counted.
  *
- * Note that guest_offset may not be cluster aligned.
+ * Note that guest_offset may not be cluster aligned. In this case, the
+ * returned *host_offset points to exact byte referenced by guest_offset and
+ * therefore isn't cluster aligned as well.
  *
  * Returns:
  *   0:     if no allocated clusters are available at the given offset.
@@ -845,6 +847,9 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
     trace_qcow2_handle_copied(qemu_coroutine_self(), guest_offset, *host_offset,
                               *bytes);
 
+    assert(*host_offset == 0 ||    offset_into_cluster(s, guest_offset)
+                                == offset_into_cluster(s, *host_offset));
+
     /*
      * Calculate the number of clusters to look for. We stop at L2 table
      * boundaries to keep things simple.
@@ -903,7 +908,8 @@ out:
     /* Only return a host offset if we actually made progress. Otherwise we
      * would make requirements for handle_alloc() that it can't fulfill */
     if (ret) {
-        *host_offset = cluster_offset & L2E_OFFSET_MASK;
+        *host_offset = (cluster_offset & L2E_OFFSET_MASK)
+                     + offset_into_cluster(s, guest_offset);
     }
 
     return ret;
@@ -961,7 +967,9 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
  * copy on write. If *host_offset is non-zero, clusters are only allocated if
  * the new allocation can match the specified host offset.
  *
- * Note that guest_offset may not be cluster aligned.
+ * Note that guest_offset may not be cluster aligned. In this case, the
+ * returned *host_offset points to exact byte referenced by guest_offset and
+ * therefore isn't cluster aligned as well.
  *
  * Returns:
  *   0:     if no clusters could be allocated. *bytes is set to 0,
@@ -1026,7 +1034,7 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     }
 
     /* Allocate, if necessary at a given offset in the image file */
-    alloc_cluster_offset = *host_offset;
+    alloc_cluster_offset = start_of_cluster(s, *host_offset);
     ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,
                                   &nb_clusters);
     if (ret < 0) {
@@ -1062,12 +1070,10 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
                         >> BDRV_SECTOR_BITS;
     int nb_sectors = MIN(requested_sectors, avail_sectors);
 
-    *host_offset = alloc_cluster_offset;
-
     *m = g_malloc0(sizeof(**m));
 
     **m = (QCowL2Meta) {
-        .alloc_offset   = *host_offset,
+        .alloc_offset   = alloc_cluster_offset,
         .offset         = start_of_cluster(s, guest_offset),
         .nb_clusters    = nb_clusters,
         .nb_available   = nb_sectors,
@@ -1084,6 +1090,7 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     qemu_co_queue_init(&(*m)->dependent_requests);
     QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
 
+    *host_offset = alloc_cluster_offset + offset_into_cluster(s, guest_offset);
     *bytes = MIN(*bytes, (nb_sectors * BDRV_SECTOR_SIZE)
                          - offset_into_cluster(s, guest_offset));
     assert(*bytes != 0);
@@ -1186,7 +1193,7 @@ again:
         nb_clusters -= keep_clusters;
 
         if (!*host_offset) {
-            *host_offset = cluster_offset;
+            *host_offset = start_of_cluster(s, cluster_offset);
         }
     } else if (cur_bytes == 0) {
         keep_clusters = 0;
@@ -1228,7 +1235,7 @@ again:
     }
 
     if (!*host_offset) {
-        *host_offset = cluster_offset;
+        *host_offset = start_of_cluster(s, cluster_offset);
     }
     nb_clusters = size_to_clusters(s, cur_bytes + offset_into_cluster(s, offset));
 
commit e62daaf67958e8274547ddac87cb0a177a869216
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:08 2013 +0100

    qcow2: handle_copied(): Implement non-zero host_offset
    
    Look only for clusters that start at a given physical offset.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 5e5465d..239a997 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -830,8 +830,6 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
  *          the length of the area that can be written to.
  *
  *  -errno: in error cases
- *
- * TODO Make non-zero host_offset behave like describe above
  */
 static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
     uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
@@ -846,7 +844,6 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
 
     trace_qcow2_handle_copied(qemu_coroutine_self(), guest_offset, *host_offset,
                               *bytes);
-    assert(*host_offset == 0);
 
     /*
      * Calculate the number of clusters to look for. We stop at L2 table
@@ -870,6 +867,16 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
     if (qcow2_get_cluster_type(cluster_offset) == QCOW2_CLUSTER_NORMAL
         && (cluster_offset & QCOW_OFLAG_COPIED))
     {
+        /* If a specific host_offset is required, check it */
+        bool offset_matches =
+            (cluster_offset & L2E_OFFSET_MASK) == *host_offset;
+
+        if (*host_offset != 0 && !offset_matches) {
+            *bytes = 0;
+            ret = 0;
+            goto out;
+        }
+
         /* We keep all QCOW_OFLAG_COPIED clusters */
         keep_clusters =
             count_contiguous_clusters(nb_clusters, s->cluster_size,
@@ -883,19 +890,22 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
 
         ret = 1;
     } else {
-        cluster_offset = 0;
         ret = 0;
     }
 
-    cluster_offset &= L2E_OFFSET_MASK;
-    *host_offset = cluster_offset;
-
     /* Cleanup */
+out:
     pret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
     if (pret < 0) {
         return pret;
     }
 
+    /* Only return a host offset if we actually made progress. Otherwise we
+     * would make requirements for handle_alloc() that it can't fulfill */
+    if (ret) {
+        *host_offset = cluster_offset & L2E_OFFSET_MASK;
+    }
+
     return ret;
 }
 
@@ -1165,7 +1175,6 @@ again:
 
     /*
      * 2. Count contiguous COPIED clusters.
-     *    TODO: Consider cluster_offset if set in step 1c.
      */
     uint64_t tmp_bytes = cur_bytes;
     ret = handle_copied(bs, offset, &cluster_offset, &tmp_bytes, m);
@@ -1179,6 +1188,9 @@ again:
         if (!*host_offset) {
             *host_offset = cluster_offset;
         }
+    } else if (cur_bytes == 0) {
+        keep_clusters = 0;
+        goto done;
     } else {
         keep_clusters = 0;
     }
commit c53ede9f6d8f0de7939eea676c1398c4073ff35e
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:07 2013 +0100

    qcow2: handle_copied(): Get rid of keep_clusters parameter
    
    Now *bytes is used to return the length of the area that can be written
    to without performing an allocation or COW.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index d640328..5e5465d 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -831,19 +831,17 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
  *
  *  -errno: in error cases
  *
- * TODO Get rid of keep_clusters parameter
- * TODO Make bytes behave like described above
  * TODO Make non-zero host_offset behave like describe above
  */
 static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
-    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
-    unsigned int *keep_clusters)
+    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index;
     uint64_t cluster_offset;
     uint64_t *l2_table;
     unsigned int nb_clusters;
+    unsigned int keep_clusters;
     int ret, pret;
 
     trace_qcow2_handle_copied(qemu_coroutine_self(), guest_offset, *host_offset,
@@ -873,17 +871,19 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
         && (cluster_offset & QCOW_OFLAG_COPIED))
     {
         /* We keep all QCOW_OFLAG_COPIED clusters */
-        *keep_clusters =
+        keep_clusters =
             count_contiguous_clusters(nb_clusters, s->cluster_size,
                                       &l2_table[l2_index], 0,
                                       QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO);
-        assert(*keep_clusters <= nb_clusters);
+        assert(keep_clusters <= nb_clusters);
+
+        *bytes = MIN(*bytes,
+                 keep_clusters * s->cluster_size
+                 - offset_into_cluster(s, guest_offset));
 
         ret = 1;
     } else {
-        *keep_clusters = 0;
         cluster_offset = 0;
-
         ret = 0;
     }
 
@@ -1168,16 +1168,19 @@ again:
      *    TODO: Consider cluster_offset if set in step 1c.
      */
     uint64_t tmp_bytes = cur_bytes;
-    ret = handle_copied(bs, offset, &cluster_offset, &tmp_bytes, m,
-                        &keep_clusters);
+    ret = handle_copied(bs, offset, &cluster_offset, &tmp_bytes, m);
     if (ret < 0) {
         return ret;
     } else if (ret) {
+        keep_clusters =
+            size_to_clusters(s, tmp_bytes + offset_into_cluster(s, offset));
         nb_clusters -= keep_clusters;
 
         if (!*host_offset) {
             *host_offset = cluster_offset;
         }
+    } else {
+        keep_clusters = 0;
     }
 
     /* If there is something left to allocate, do that now */
commit acb0467f8df7e9dbc8bbcb9a2e1e8cfe17f79691
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:06 2013 +0100

    qcow2: handle_copied(): Get rid of nb_clusters parameter
    
    handle_copied() uses its bytes parameter now to determine how many
    clusters it should try to find.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 9036bd8..d640328 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -831,24 +831,35 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
  *
  *  -errno: in error cases
  *
- * TODO Get rid of keep_clusters, nb_clusters parameters
+ * TODO Get rid of keep_clusters parameter
  * TODO Make bytes behave like described above
  * TODO Make non-zero host_offset behave like describe above
  */
 static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
     uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
-    unsigned int *keep_clusters, unsigned int *nb_clusters)
+    unsigned int *keep_clusters)
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index;
     uint64_t cluster_offset;
     uint64_t *l2_table;
+    unsigned int nb_clusters;
     int ret, pret;
 
     trace_qcow2_handle_copied(qemu_coroutine_self(), guest_offset, *host_offset,
                               *bytes);
     assert(*host_offset == 0);
 
+    /*
+     * Calculate the number of clusters to look for. We stop at L2 table
+     * boundaries to keep things simple.
+     */
+    nb_clusters =
+        size_to_clusters(s, offset_into_cluster(s, guest_offset) + *bytes);
+
+    l2_index = offset_to_l2_index(s, guest_offset);
+    nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
+
     /* Find L2 entry for the first involved cluster */
     ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
     if (ret < 0) {
@@ -863,11 +874,10 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
     {
         /* We keep all QCOW_OFLAG_COPIED clusters */
         *keep_clusters =
-            count_contiguous_clusters(*nb_clusters, s->cluster_size,
+            count_contiguous_clusters(nb_clusters, s->cluster_size,
                                       &l2_table[l2_index], 0,
                                       QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO);
-        assert(*keep_clusters <= *nb_clusters);
-        *nb_clusters -= *keep_clusters;
+        assert(*keep_clusters <= nb_clusters);
 
         ret = 1;
     } else {
@@ -1159,10 +1169,12 @@ again:
      */
     uint64_t tmp_bytes = cur_bytes;
     ret = handle_copied(bs, offset, &cluster_offset, &tmp_bytes, m,
-                        &keep_clusters, &nb_clusters);
+                        &keep_clusters);
     if (ret < 0) {
         return ret;
     } else if (ret) {
+        nb_clusters -= keep_clusters;
+
         if (!*host_offset) {
             *host_offset = cluster_offset;
         }
commit 0af729ec007ea4d103a2e3f3fc5db522610a2290
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:05 2013 +0100

    qcow2: Factor out handle_copied()
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 1141483..9036bd8 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -812,6 +812,84 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
 }
 
 /*
+ * Checks how many already allocated clusters that don't require a copy on
+ * write there are at the given guest_offset (up to *bytes). If
+ * *host_offset is not zero, only physically contiguous clusters beginning at
+ * this host offset are counted.
+ *
+ * Note that guest_offset may not be cluster aligned.
+ *
+ * Returns:
+ *   0:     if no allocated clusters are available at the given offset.
+ *          *bytes is normally unchanged. It is set to 0 if the cluster
+ *          is allocated and doesn't need COW, but doesn't have the right
+ *          physical offset.
+ *
+ *   1:     if allocated clusters that don't require a COW are available at
+ *          the requested offset. *bytes may have decreased and describes
+ *          the length of the area that can be written to.
+ *
+ *  -errno: in error cases
+ *
+ * TODO Get rid of keep_clusters, nb_clusters parameters
+ * TODO Make bytes behave like described above
+ * TODO Make non-zero host_offset behave like describe above
+ */
+static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
+    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
+    unsigned int *keep_clusters, unsigned int *nb_clusters)
+{
+    BDRVQcowState *s = bs->opaque;
+    int l2_index;
+    uint64_t cluster_offset;
+    uint64_t *l2_table;
+    int ret, pret;
+
+    trace_qcow2_handle_copied(qemu_coroutine_self(), guest_offset, *host_offset,
+                              *bytes);
+    assert(*host_offset == 0);
+
+    /* Find L2 entry for the first involved cluster */
+    ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
+    if (ret < 0) {
+        return ret;
+    }
+
+    cluster_offset = be64_to_cpu(l2_table[l2_index]);
+
+    /* Check how many clusters are already allocated and don't need COW */
+    if (qcow2_get_cluster_type(cluster_offset) == QCOW2_CLUSTER_NORMAL
+        && (cluster_offset & QCOW_OFLAG_COPIED))
+    {
+        /* We keep all QCOW_OFLAG_COPIED clusters */
+        *keep_clusters =
+            count_contiguous_clusters(*nb_clusters, s->cluster_size,
+                                      &l2_table[l2_index], 0,
+                                      QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO);
+        assert(*keep_clusters <= *nb_clusters);
+        *nb_clusters -= *keep_clusters;
+
+        ret = 1;
+    } else {
+        *keep_clusters = 0;
+        cluster_offset = 0;
+
+        ret = 0;
+    }
+
+    cluster_offset &= L2E_OFFSET_MASK;
+    *host_offset = cluster_offset;
+
+    /* Cleanup */
+    pret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+    if (pret < 0) {
+        return pret;
+    }
+
+    return ret;
+}
+
+/*
  * Allocates new clusters for the given guest_offset.
  *
  * At most *nb_clusters are allocated, and on return *nb_clusters is updated to
@@ -1023,7 +1101,6 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index, ret, sectors;
-    uint64_t *l2_table;
     unsigned int nb_clusters, keep_clusters;
     uint64_t cluster_offset;
     uint64_t cur_bytes;
@@ -1032,6 +1109,9 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
                                       n_start, n_end);
 
 again:
+    cluster_offset = 0;
+    *host_offset = 0;
+
     /*
      * Calculate the number of clusters to look for. We stop at L2 table
      * boundaries to keep things simple.
@@ -1057,12 +1137,6 @@ again:
      *         allocation ends. Shorten the COW of the in-fight allocation, set
      *         cluster_offset to write to the same cluster and set up the right
      *         synchronisation between the in-flight request and the new one.
-     *
-     * 2. Count contiguous COPIED clusters.
-     *    TODO: Consider cluster_offset if set in step 1c.
-     *
-     * 3. If the request still hasn't completed, allocate new clusters,
-     *    considering any cluster_offset of steps 1c or 2.
      */
     cur_bytes = (n_end - n_start) * BDRV_SECTOR_SIZE;
     ret = handle_dependencies(bs, offset, &cur_bytes);
@@ -1079,43 +1153,19 @@ again:
     nb_clusters = size_to_clusters(s, offset + cur_bytes)
                 - (offset >> s->cluster_bits);
 
-    /* Find L2 entry for the first involved cluster */
-    ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
-    if (ret < 0) {
-        return ret;
-    }
-
-    cluster_offset = be64_to_cpu(l2_table[l2_index]);
-
-    /* Check how many clusters are already allocated and don't need COW */
-    if (qcow2_get_cluster_type(cluster_offset) == QCOW2_CLUSTER_NORMAL
-        && (cluster_offset & QCOW_OFLAG_COPIED))
-    {
-        /* We keep all QCOW_OFLAG_COPIED clusters */
-        keep_clusters =
-            count_contiguous_clusters(nb_clusters, s->cluster_size,
-                                      &l2_table[l2_index], 0,
-                                      QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO);
-        assert(keep_clusters <= nb_clusters);
-        nb_clusters -= keep_clusters;
-    } else {
-        keep_clusters = 0;
-        cluster_offset = 0;
-    }
-
-    cluster_offset &= L2E_OFFSET_MASK;
-    *host_offset = cluster_offset;
-
     /*
-     * The L2 table isn't used any more after this. As long as the cache works
-     * synchronously, it's important to release it before calling
-     * do_alloc_cluster_offset, which may yield if we need to wait for another
-     * request to complete. If we still had the reference, we could use up the
-     * whole cache with sleeping requests.
+     * 2. Count contiguous COPIED clusters.
+     *    TODO: Consider cluster_offset if set in step 1c.
      */
-    ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+    uint64_t tmp_bytes = cur_bytes;
+    ret = handle_copied(bs, offset, &cluster_offset, &tmp_bytes, m,
+                        &keep_clusters, &nb_clusters);
     if (ret < 0) {
         return ret;
+    } else if (ret) {
+        if (!*host_offset) {
+            *host_offset = cluster_offset;
+        }
     }
 
     /* If there is something left to allocate, do that now */
@@ -1123,6 +1173,10 @@ again:
         goto done;
     }
 
+    /*
+     * 3. If the request still hasn't completed, allocate new clusters,
+     *    considering any cluster_offset of steps 1c or 2.
+     */
     int alloc_n_start;
     int alloc_n_end;
 
diff --git a/trace-events b/trace-events
index 9511a28..5a6ef4b 100644
--- a/trace-events
+++ b/trace-events
@@ -483,6 +483,7 @@ qcow2_writev_done_part(void *co, int cur_nr_sectors) "co %p cur_nr_sectors %d"
 qcow2_writev_data(void *co, uint64_t offset) "co %p offset %" PRIx64
 
 qcow2_alloc_clusters_offset(void *co, uint64_t offset, int n_start, int n_end) "co %p offet %" PRIx64 " n_start %d n_end %d"
+qcow2_handle_copied(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64
 qcow2_handle_alloc(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64
 qcow2_do_alloc_clusters_offset(void *co, uint64_t guest_offset, uint64_t host_offset, int nb_clusters) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " nb_clusters %d"
 qcow2_cluster_alloc_phys(void *co) "co %p"
commit 83baa9a4719b42bc28d525fa28af643523cc2bf3
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:04 2013 +0100

    qcow2: Clean up handle_alloc()
    
    Things can be simplified a bit now. No semantic changes.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 8ed1f7d..1141483 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -886,7 +886,6 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     unsigned int nb_clusters;
     int ret;
 
-    uint64_t alloc_offset;
     uint64_t alloc_cluster_offset;
 
     trace_qcow2_handle_alloc(qemu_coroutine_self(), guest_offset, *host_offset,
@@ -928,72 +927,69 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
         return 0;
     }
 
-    /* Calculate start and size of allocation */
-    alloc_offset = guest_offset;
-    alloc_cluster_offset = *host_offset;
-
     /* Allocate, if necessary at a given offset in the image file */
-    ret = do_alloc_cluster_offset(bs, alloc_offset, &alloc_cluster_offset,
+    alloc_cluster_offset = *host_offset;
+    ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,
                                   &nb_clusters);
     if (ret < 0) {
         goto fail;
     }
 
-    /* save info needed for meta data update */
-    if (nb_clusters > 0) {
-        /*
-         * requested_sectors: Number of sectors from the start of the first
-         * newly allocated cluster to the end of the (possibly shortened
-         * before) write request.
-         *
-         * avail_sectors: Number of sectors from the start of the first
-         * newly allocated to the end of the last newly allocated cluster.
-         *
-         * nb_sectors: The number of sectors from the start of the first
-         * newly allocated cluster to the end of the aread that the write
-         * request actually writes to (excluding COW at the end)
-         */
-        int requested_sectors =
-            (*bytes + offset_into_cluster(s, guest_offset))
-            >> BDRV_SECTOR_BITS;
-        int avail_sectors = nb_clusters
-                            << (s->cluster_bits - BDRV_SECTOR_BITS);
-        int alloc_n_start = offset_into_cluster(s, guest_offset)
-                            >> BDRV_SECTOR_BITS;
-        int nb_sectors = MIN(requested_sectors, avail_sectors);
-
-        if (*host_offset == 0) {
-            *host_offset = alloc_cluster_offset;
-        }
-
-        *m = g_malloc0(sizeof(**m));
-
-        **m = (QCowL2Meta) {
-            .alloc_offset   = alloc_cluster_offset,
-            .offset         = alloc_offset & ~(s->cluster_size - 1),
-            .nb_clusters    = nb_clusters,
-            .nb_available   = nb_sectors,
-
-            .cow_start = {
-                .offset     = 0,
-                .nb_sectors = alloc_n_start,
-            },
-            .cow_end = {
-                .offset     = nb_sectors * BDRV_SECTOR_SIZE,
-                .nb_sectors = avail_sectors - nb_sectors,
-            },
-        };
-        qemu_co_queue_init(&(*m)->dependent_requests);
-        QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
-
-        *bytes = MIN(*bytes, (nb_sectors * BDRV_SECTOR_SIZE)
-                             - offset_into_cluster(s, guest_offset));
-        assert(*bytes != 0);
-    } else {
+    /* Can't extend contiguous allocation */
+    if (nb_clusters == 0) {
         *bytes = 0;
         return 0;
     }
 
+    /*
+     * Save info needed for meta data update.
+     *
+     * requested_sectors: Number of sectors from the start of the first
+     * newly allocated cluster to the end of the (possibly shortened
+     * before) write request.
+     *
+     * avail_sectors: Number of sectors from the start of the first
+     * newly allocated to the end of the last newly allocated cluster.
+     *
+     * nb_sectors: The number of sectors from the start of the first
+     * newly allocated cluster to the end of the area that the write
+     * request actually writes to (excluding COW at the end)
+     */
+    int requested_sectors =
+        (*bytes + offset_into_cluster(s, guest_offset))
+        >> BDRV_SECTOR_BITS;
+    int avail_sectors = nb_clusters
+                        << (s->cluster_bits - BDRV_SECTOR_BITS);
+    int alloc_n_start = offset_into_cluster(s, guest_offset)
+                        >> BDRV_SECTOR_BITS;
+    int nb_sectors = MIN(requested_sectors, avail_sectors);
+
+    *host_offset = alloc_cluster_offset;
+
+    *m = g_malloc0(sizeof(**m));
+
+    **m = (QCowL2Meta) {
+        .alloc_offset   = *host_offset,
+        .offset         = start_of_cluster(s, guest_offset),
+        .nb_clusters    = nb_clusters,
+        .nb_available   = nb_sectors,
+
+        .cow_start = {
+            .offset     = 0,
+            .nb_sectors = alloc_n_start,
+        },
+        .cow_end = {
+            .offset     = nb_sectors * BDRV_SECTOR_SIZE,
+            .nb_sectors = avail_sectors - nb_sectors,
+        },
+    };
+    qemu_co_queue_init(&(*m)->dependent_requests);
+    QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
+
+    *bytes = MIN(*bytes, (nb_sectors * BDRV_SECTOR_SIZE)
+                         - offset_into_cluster(s, guest_offset));
+    assert(*bytes != 0);
+
     return 1;
 
 fail:
commit c37f4cd71d99b7658d238bd8399048fc6e506958
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:03 2013 +0100

    qcow2: Finalise interface of handle_alloc()
    
    The interface works completely on a byte granularity now and duplicated
    parameters are removed.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 8f4ef0d..8ed1f7d 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -875,13 +875,9 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
  *          newly allocated cluster.
  *
  *  -errno: in error cases
- *
- * TODO Get rid of n_start, n_end
- * TODO Make *bytes actually behave as specified above
  */
 static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
-    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
-    int n_start, int n_end)
+    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index;
@@ -901,8 +897,11 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
      * Calculate the number of clusters to look for. We stop at L2 table
      * boundaries to keep things simple.
      */
+    nb_clusters =
+        size_to_clusters(s, offset_into_cluster(s, guest_offset) + *bytes);
+
     l2_index = offset_to_l2_index(s, guest_offset);
-    nb_clusters = MIN(size_to_clusters(s, *bytes), s->l2_size - l2_index);
+    nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
 
     /* Find L2 entry for the first involved cluster */
     ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
@@ -954,10 +953,13 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
          * newly allocated cluster to the end of the aread that the write
          * request actually writes to (excluding COW at the end)
          */
-        int requested_sectors = n_end;
+        int requested_sectors =
+            (*bytes + offset_into_cluster(s, guest_offset))
+            >> BDRV_SECTOR_BITS;
         int avail_sectors = nb_clusters
                             << (s->cluster_bits - BDRV_SECTOR_BITS);
-        int alloc_n_start = *host_offset == 0 ? n_start : 0;
+        int alloc_n_start = offset_into_cluster(s, guest_offset)
+                            >> BDRV_SECTOR_BITS;
         int nb_sectors = MIN(requested_sectors, avail_sectors);
 
         if (*host_offset == 0) {
@@ -984,7 +986,9 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
         qemu_co_queue_init(&(*m)->dependent_requests);
         QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
 
-        *bytes = nb_clusters * s->cluster_size;
+        *bytes = MIN(*bytes, (nb_sectors * BDRV_SECTOR_SIZE)
+                             - offset_into_cluster(s, guest_offset));
+        assert(*bytes != 0);
     } else {
         *bytes = 0;
         return 0;
@@ -1139,10 +1143,9 @@ again:
         alloc_n_end = n_end;
     }
 
-    cur_bytes = nb_clusters * s->cluster_size;
+    cur_bytes = MIN(cur_bytes, ((alloc_n_end - alloc_n_start) << BDRV_SECTOR_BITS));
 
-    ret = handle_alloc(bs, offset, &cluster_offset, &cur_bytes, m,
-                       alloc_n_start, alloc_n_end);
+    ret = handle_alloc(bs, offset, &cluster_offset, &cur_bytes, m);
     if (ret < 0) {
         return ret;
     }
@@ -1150,7 +1153,7 @@ again:
     if (!*host_offset) {
         *host_offset = cluster_offset;
     }
-    nb_clusters = size_to_clusters(s, cur_bytes);
+    nb_clusters = size_to_clusters(s, cur_bytes + offset_into_cluster(s, offset));
 
     /* Some cleanup work */
 done:
diff --git a/block/qcow2.h b/block/qcow2.h
index c4eaf67..32806bd 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -271,6 +271,11 @@ static inline int64_t start_of_cluster(BDRVQcowState *s, int64_t offset)
     return offset & ~(s->cluster_size - 1);
 }
 
+static inline int64_t offset_into_cluster(BDRVQcowState *s, int64_t offset)
+{
+    return offset & (s->cluster_size - 1);
+}
+
 static inline int size_to_clusters(BDRVQcowState *s, int64_t size)
 {
     return (size + (s->cluster_size - 1)) >> s->cluster_bits;
commit 3b8e2e260c8cee63c9253718983a6682dc2771d7
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:02 2013 +0100

    qcow2: handle_alloc(): Get rid of keep_clusters parameter
    
    handle_alloc() is now called with the offset at which the actual new
    allocation starts instead of the offset at which the whole write request
    starts, part of which may already be processed.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 009f62a..8f4ef0d 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -876,12 +876,12 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
  *
  *  -errno: in error cases
  *
- * TODO Get rid of keep_clusters, n_start, n_end
+ * TODO Get rid of n_start, n_end
  * TODO Make *bytes actually behave as specified above
  */
 static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
-    int keep_clusters, int n_start, int n_end)
+    int n_start, int n_end)
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index;
@@ -892,7 +892,6 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
 
     uint64_t alloc_offset;
     uint64_t alloc_cluster_offset;
-    uint64_t keep_bytes = keep_clusters * s->cluster_size;
 
     trace_qcow2_handle_alloc(qemu_coroutine_self(), guest_offset, *host_offset,
                              *bytes);
@@ -911,14 +910,13 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
         return ret;
     }
 
-    entry = be64_to_cpu(l2_table[l2_index + keep_clusters]);
+    entry = be64_to_cpu(l2_table[l2_index]);
 
     /* For the moment, overwrite compressed clusters one by one */
     if (entry & QCOW_OFLAG_COMPRESSED) {
         nb_clusters = 1;
     } else {
-        nb_clusters = count_cow_clusters(s, nb_clusters, l2_table,
-                                         l2_index + keep_clusters);
+        nb_clusters = count_cow_clusters(s, nb_clusters, l2_table, l2_index);
     }
 
     ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
@@ -932,13 +930,8 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     }
 
     /* Calculate start and size of allocation */
-    alloc_offset = guest_offset + keep_bytes;
-
-    if (keep_clusters == 0) {
-        alloc_cluster_offset = 0;
-    } else {
-        alloc_cluster_offset = *host_offset + keep_bytes;
-    }
+    alloc_offset = guest_offset;
+    alloc_cluster_offset = *host_offset;
 
     /* Allocate, if necessary at a given offset in the image file */
     ret = do_alloc_cluster_offset(bs, alloc_offset, &alloc_cluster_offset,
@@ -961,13 +954,13 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
          * newly allocated cluster to the end of the aread that the write
          * request actually writes to (excluding COW at the end)
          */
-        int requested_sectors = n_end - keep_clusters * s->cluster_sectors;
+        int requested_sectors = n_end;
         int avail_sectors = nb_clusters
                             << (s->cluster_bits - BDRV_SECTOR_BITS);
-        int alloc_n_start = keep_clusters == 0 ? n_start : 0;
+        int alloc_n_start = *host_offset == 0 ? n_start : 0;
         int nb_sectors = MIN(requested_sectors, avail_sectors);
 
-        if (keep_clusters == 0) {
+        if (*host_offset == 0) {
             *host_offset = alloc_cluster_offset;
         }
 
@@ -1130,9 +1123,26 @@ again:
         goto done;
     }
 
+    int alloc_n_start;
+    int alloc_n_end;
+
+    if (keep_clusters != 0) {
+        offset         = start_of_cluster(s, offset
+                                             + keep_clusters * s->cluster_size);
+        cluster_offset = start_of_cluster(s, cluster_offset
+                                             + keep_clusters * s->cluster_size);
+
+        alloc_n_start = 0;
+        alloc_n_end = n_end - keep_clusters * s->cluster_sectors;
+    } else {
+        alloc_n_start = n_start;
+        alloc_n_end = n_end;
+    }
+
     cur_bytes = nb_clusters * s->cluster_size;
+
     ret = handle_alloc(bs, offset, &cluster_offset, &cur_bytes, m,
-                       keep_clusters, n_start, n_end);
+                       alloc_n_start, alloc_n_end);
     if (ret < 0) {
         return ret;
     }
diff --git a/block/qcow2.h b/block/qcow2.h
index a99d51b..c4eaf67 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -266,6 +266,11 @@ enum {
 
 #define REFT_OFFSET_MASK 0xffffffffffffff00ULL
 
+static inline int64_t start_of_cluster(BDRVQcowState *s, int64_t offset)
+{
+    return offset & ~(s->cluster_size - 1);
+}
+
 static inline int size_to_clusters(BDRVQcowState *s, int64_t size)
 {
     return (size + (s->cluster_size - 1)) >> s->cluster_bits;
commit f5bc63509471299176066d5f63bb8ff2e15af279
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:01 2013 +0100

    qcow2: handle_alloc(): Get rid of nb_clusters parameter
    
    We already communicate the same information in *bytes.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 454a30c..009f62a 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -876,17 +876,18 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
  *
  *  -errno: in error cases
  *
- * TODO Get rid of nb_clusters, keep_clusters, n_start, n_end
+ * TODO Get rid of keep_clusters, n_start, n_end
  * TODO Make *bytes actually behave as specified above
  */
 static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
     uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
-    unsigned int nb_clusters, int keep_clusters, int n_start, int n_end)
+    int keep_clusters, int n_start, int n_end)
 {
     BDRVQcowState *s = bs->opaque;
     int l2_index;
     uint64_t *l2_table;
     uint64_t entry;
+    unsigned int nb_clusters;
     int ret;
 
     uint64_t alloc_offset;
@@ -897,6 +898,13 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
                              *bytes);
     assert(*bytes > 0);
 
+    /*
+     * Calculate the number of clusters to look for. We stop at L2 table
+     * boundaries to keep things simple.
+     */
+    l2_index = offset_to_l2_index(s, guest_offset);
+    nb_clusters = MIN(size_to_clusters(s, *bytes), s->l2_size - l2_index);
+
     /* Find L2 entry for the first involved cluster */
     ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
     if (ret < 0) {
@@ -1103,6 +1111,7 @@ again:
     }
 
     cluster_offset &= L2E_OFFSET_MASK;
+    *host_offset = cluster_offset;
 
     /*
      * The L2 table isn't used any more after this. As long as the cache works
@@ -1123,11 +1132,14 @@ again:
 
     cur_bytes = nb_clusters * s->cluster_size;
     ret = handle_alloc(bs, offset, &cluster_offset, &cur_bytes, m,
-                       nb_clusters, keep_clusters, n_start, n_end);
+                       keep_clusters, n_start, n_end);
     if (ret < 0) {
         return ret;
     }
 
+    if (!*host_offset) {
+        *host_offset = cluster_offset;
+    }
     nb_clusters = size_to_clusters(s, cur_bytes);
 
     /* Some cleanup work */
@@ -1139,7 +1151,6 @@ done:
 
     assert(sectors > n_start);
     *num = sectors - n_start;
-    *host_offset = cluster_offset;
 
     return 0;
 }
commit 10f0ed8b2f0d3e9f0476b6f00868dd13b524066a
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:50:00 2013 +0100

    qcow2: Factor out handle_alloc()
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 9550927..454a30c 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -859,6 +859,146 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
 }
 
 /*
+ * Allocates new clusters for an area that either is yet unallocated or needs a
+ * copy on write. If *host_offset is non-zero, clusters are only allocated if
+ * the new allocation can match the specified host offset.
+ *
+ * Note that guest_offset may not be cluster aligned.
+ *
+ * Returns:
+ *   0:     if no clusters could be allocated. *bytes is set to 0,
+ *          *host_offset is left unchanged.
+ *
+ *   1:     if new clusters were allocated. *bytes may be decreased if the
+ *          new allocation doesn't cover all of the requested area.
+ *          *host_offset is updated to contain the host offset of the first
+ *          newly allocated cluster.
+ *
+ *  -errno: in error cases
+ *
+ * TODO Get rid of nb_clusters, keep_clusters, n_start, n_end
+ * TODO Make *bytes actually behave as specified above
+ */
+static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
+    uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m,
+    unsigned int nb_clusters, int keep_clusters, int n_start, int n_end)
+{
+    BDRVQcowState *s = bs->opaque;
+    int l2_index;
+    uint64_t *l2_table;
+    uint64_t entry;
+    int ret;
+
+    uint64_t alloc_offset;
+    uint64_t alloc_cluster_offset;
+    uint64_t keep_bytes = keep_clusters * s->cluster_size;
+
+    trace_qcow2_handle_alloc(qemu_coroutine_self(), guest_offset, *host_offset,
+                             *bytes);
+    assert(*bytes > 0);
+
+    /* Find L2 entry for the first involved cluster */
+    ret = get_cluster_table(bs, guest_offset, &l2_table, &l2_index);
+    if (ret < 0) {
+        return ret;
+    }
+
+    entry = be64_to_cpu(l2_table[l2_index + keep_clusters]);
+
+    /* For the moment, overwrite compressed clusters one by one */
+    if (entry & QCOW_OFLAG_COMPRESSED) {
+        nb_clusters = 1;
+    } else {
+        nb_clusters = count_cow_clusters(s, nb_clusters, l2_table,
+                                         l2_index + keep_clusters);
+    }
+
+    ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+    if (ret < 0) {
+        return ret;
+    }
+
+    if (nb_clusters == 0) {
+        *bytes = 0;
+        return 0;
+    }
+
+    /* Calculate start and size of allocation */
+    alloc_offset = guest_offset + keep_bytes;
+
+    if (keep_clusters == 0) {
+        alloc_cluster_offset = 0;
+    } else {
+        alloc_cluster_offset = *host_offset + keep_bytes;
+    }
+
+    /* Allocate, if necessary at a given offset in the image file */
+    ret = do_alloc_cluster_offset(bs, alloc_offset, &alloc_cluster_offset,
+                                  &nb_clusters);
+    if (ret < 0) {
+        goto fail;
+    }
+
+    /* save info needed for meta data update */
+    if (nb_clusters > 0) {
+        /*
+         * requested_sectors: Number of sectors from the start of the first
+         * newly allocated cluster to the end of the (possibly shortened
+         * before) write request.
+         *
+         * avail_sectors: Number of sectors from the start of the first
+         * newly allocated to the end of the last newly allocated cluster.
+         *
+         * nb_sectors: The number of sectors from the start of the first
+         * newly allocated cluster to the end of the aread that the write
+         * request actually writes to (excluding COW at the end)
+         */
+        int requested_sectors = n_end - keep_clusters * s->cluster_sectors;
+        int avail_sectors = nb_clusters
+                            << (s->cluster_bits - BDRV_SECTOR_BITS);
+        int alloc_n_start = keep_clusters == 0 ? n_start : 0;
+        int nb_sectors = MIN(requested_sectors, avail_sectors);
+
+        if (keep_clusters == 0) {
+            *host_offset = alloc_cluster_offset;
+        }
+
+        *m = g_malloc0(sizeof(**m));
+
+        **m = (QCowL2Meta) {
+            .alloc_offset   = alloc_cluster_offset,
+            .offset         = alloc_offset & ~(s->cluster_size - 1),
+            .nb_clusters    = nb_clusters,
+            .nb_available   = nb_sectors,
+
+            .cow_start = {
+                .offset     = 0,
+                .nb_sectors = alloc_n_start,
+            },
+            .cow_end = {
+                .offset     = nb_sectors * BDRV_SECTOR_SIZE,
+                .nb_sectors = avail_sectors - nb_sectors,
+            },
+        };
+        qemu_co_queue_init(&(*m)->dependent_requests);
+        QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
+
+        *bytes = nb_clusters * s->cluster_size;
+    } else {
+        *bytes = 0;
+        return 0;
+    }
+
+    return 1;
+
+fail:
+    if (*m && (*m)->nb_clusters > 0) {
+        QLIST_REMOVE(*m, next_in_flight);
+    }
+    return ret;
+}
+
+/*
  * alloc_cluster_offset
  *
  * For a given offset on the virtual disk, find the cluster offset in qcow2
@@ -977,93 +1117,21 @@ again:
     }
 
     /* If there is something left to allocate, do that now */
-    if (nb_clusters > 0) {
-        uint64_t alloc_offset;
-        uint64_t alloc_cluster_offset;
-        uint64_t keep_bytes = keep_clusters * s->cluster_size;
-
-        ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
-        if (ret < 0) {
-            return ret;
-        }
-
-        /* For the moment, overwrite compressed clusters one by one */
-        uint64_t entry = be64_to_cpu(l2_table[l2_index + keep_clusters]);
-        if (entry & QCOW_OFLAG_COMPRESSED) {
-            nb_clusters = 1;
-        } else {
-            nb_clusters = count_cow_clusters(s, nb_clusters, l2_table,
-                                             l2_index + keep_clusters);
-        }
-
-        ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
-        if (ret < 0) {
-            return ret;
-        }
-
-        /* Calculate start and size of allocation */
-        alloc_offset = offset + keep_bytes;
-
-        if (keep_clusters == 0) {
-            alloc_cluster_offset = 0;
-        } else {
-            alloc_cluster_offset = cluster_offset + keep_bytes;
-        }
-
-        /* Allocate, if necessary at a given offset in the image file */
-        ret = do_alloc_cluster_offset(bs, alloc_offset, &alloc_cluster_offset,
-                                      &nb_clusters);
-        if (ret < 0) {
-            goto fail;
-        }
-
-        /* save info needed for meta data update */
-        if (nb_clusters > 0) {
-            /*
-             * requested_sectors: Number of sectors from the start of the first
-             * newly allocated cluster to the end of the (possibly shortened
-             * before) write request.
-             *
-             * avail_sectors: Number of sectors from the start of the first
-             * newly allocated to the end of the last newly allocated cluster.
-             *
-             * nb_sectors: The number of sectors from the start of the first
-             * newly allocated cluster to the end of the aread that the write
-             * request actually writes to (excluding COW at the end)
-             */
-            int requested_sectors = n_end - keep_clusters * s->cluster_sectors;
-            int avail_sectors = nb_clusters
-                                << (s->cluster_bits - BDRV_SECTOR_BITS);
-            int alloc_n_start = keep_clusters == 0 ? n_start : 0;
-            int nb_sectors = MIN(requested_sectors, avail_sectors);
-
-            if (keep_clusters == 0) {
-                cluster_offset = alloc_cluster_offset;
-            }
+    if (nb_clusters == 0) {
+        goto done;
+    }
 
-            *m = g_malloc0(sizeof(**m));
-
-            **m = (QCowL2Meta) {
-                .alloc_offset   = alloc_cluster_offset,
-                .offset         = alloc_offset & ~(s->cluster_size - 1),
-                .nb_clusters    = nb_clusters,
-                .nb_available   = nb_sectors,
-
-                .cow_start = {
-                    .offset     = 0,
-                    .nb_sectors = alloc_n_start,
-                },
-                .cow_end = {
-                    .offset     = nb_sectors * BDRV_SECTOR_SIZE,
-                    .nb_sectors = avail_sectors - nb_sectors,
-                },
-            };
-            qemu_co_queue_init(&(*m)->dependent_requests);
-            QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
-        }
+    cur_bytes = nb_clusters * s->cluster_size;
+    ret = handle_alloc(bs, offset, &cluster_offset, &cur_bytes, m,
+                       nb_clusters, keep_clusters, n_start, n_end);
+    if (ret < 0) {
+        return ret;
     }
 
+    nb_clusters = size_to_clusters(s, cur_bytes);
+
     /* Some cleanup work */
+done:
     sectors = (keep_clusters + nb_clusters) << (s->cluster_bits - 9);
     if (sectors > n_end) {
         sectors = n_end;
@@ -1074,12 +1142,6 @@ again:
     *host_offset = cluster_offset;
 
     return 0;
-
-fail:
-    if (*m && (*m)->nb_clusters > 0) {
-        QLIST_REMOVE(*m, next_in_flight);
-    }
-    return ret;
 }
 
 static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
diff --git a/trace-events b/trace-events
index 406fe5f..9511a28 100644
--- a/trace-events
+++ b/trace-events
@@ -483,6 +483,7 @@ qcow2_writev_done_part(void *co, int cur_nr_sectors) "co %p cur_nr_sectors %d"
 qcow2_writev_data(void *co, uint64_t offset) "co %p offset %" PRIx64
 
 qcow2_alloc_clusters_offset(void *co, uint64_t offset, int n_start, int n_end) "co %p offet %" PRIx64 " n_start %d n_end %d"
+qcow2_handle_alloc(void *co, uint64_t guest_offset, uint64_t host_offset, uint64_t bytes) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " bytes %" PRIx64
 qcow2_do_alloc_clusters_offset(void *co, uint64_t guest_offset, uint64_t host_offset, int nb_clusters) "co %p guest_offet %" PRIx64 " host_offset %" PRIx64 " nb_clusters %d"
 qcow2_cluster_alloc_phys(void *co) "co %p"
 qcow2_cluster_link_l2(void *co, int nb_clusters) "co %p nb_clusters %d"
commit 037689d8969c493d39153fd920ad81e161b0d55c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:59 2013 +0100

    qcow2: Decouple cluster allocation from cluster reuse code
    
    This moves some code that prepares the allocation of new clusters to
    where the actual allocation happens. This is the minimum required to be
    able to move it to a separate function in the next patch.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 202adb4..9550927 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -946,10 +946,7 @@ again:
 
     cluster_offset = be64_to_cpu(l2_table[l2_index]);
 
-    /*
-     * Check how many clusters are already allocated and don't need COW, and how
-     * many need a new allocation.
-     */
+    /* Check how many clusters are already allocated and don't need COW */
     if (qcow2_get_cluster_type(cluster_offset) == QCOW2_CLUSTER_NORMAL
         && (cluster_offset & QCOW_OFLAG_COPIED))
     {
@@ -965,17 +962,6 @@ again:
         cluster_offset = 0;
     }
 
-    if (nb_clusters > 0) {
-        /* For the moment, overwrite compressed clusters one by one */
-        uint64_t entry = be64_to_cpu(l2_table[l2_index + keep_clusters]);
-        if (entry & QCOW_OFLAG_COMPRESSED) {
-            nb_clusters = 1;
-        } else {
-            nb_clusters = count_cow_clusters(s, nb_clusters, l2_table,
-                                             l2_index + keep_clusters);
-        }
-    }
-
     cluster_offset &= L2E_OFFSET_MASK;
 
     /*
@@ -996,6 +982,25 @@ again:
         uint64_t alloc_cluster_offset;
         uint64_t keep_bytes = keep_clusters * s->cluster_size;
 
+        ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
+        if (ret < 0) {
+            return ret;
+        }
+
+        /* For the moment, overwrite compressed clusters one by one */
+        uint64_t entry = be64_to_cpu(l2_table[l2_index + keep_clusters]);
+        if (entry & QCOW_OFLAG_COMPRESSED) {
+            nb_clusters = 1;
+        } else {
+            nb_clusters = count_cow_clusters(s, nb_clusters, l2_table,
+                                             l2_index + keep_clusters);
+        }
+
+        ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+        if (ret < 0) {
+            return ret;
+        }
+
         /* Calculate start and size of allocation */
         alloc_offset = offset + keep_bytes;
 
commit 65eb2e35c07632eb5d26f15a57461e321bacb883
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:58 2013 +0100

    qcow2: Change handle_dependency to byte granularity
    
    This is a more precise description of what really constitutes a
    dependency. The behaviour doesn't change at this point because the COW
    area of the old request is still aligned to cluster boundaries and
    therefore an overlap is detected wheneven the requests touch any part of
    the same cluster.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 7f4f73e..202adb4 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -759,31 +759,41 @@ out:
  * Check if there already is an AIO write request in flight which allocates
  * the same cluster. In this case we need to wait until the previous
  * request has completed and updated the L2 table accordingly.
+ *
+ * Returns:
+ *   0       if there was no dependency. *cur_bytes indicates the number of
+ *           bytes from guest_offset that can be read before the next
+ *           dependency must be processed (or the request is complete)
+ *
+ *   -EAGAIN if we had to wait for another request, previously gathered
+ *           information on cluster allocation may be invalid now. The caller
+ *           must start over anyway, so consider *cur_bytes undefined.
  */
 static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
-    unsigned int *nb_clusters)
+    uint64_t *cur_bytes)
 {
     BDRVQcowState *s = bs->opaque;
     QCowL2Meta *old_alloc;
+    uint64_t bytes = *cur_bytes;
 
     QLIST_FOREACH(old_alloc, &s->cluster_allocs, next_in_flight) {
 
-        uint64_t start = guest_offset >> s->cluster_bits;
-        uint64_t end = start + *nb_clusters;
-        uint64_t old_start = old_alloc->offset >> s->cluster_bits;
-        uint64_t old_end = old_start + old_alloc->nb_clusters;
+        uint64_t start = guest_offset;
+        uint64_t end = start + bytes;
+        uint64_t old_start = l2meta_cow_start(old_alloc);
+        uint64_t old_end = l2meta_cow_end(old_alloc);
 
         if (end <= old_start || start >= old_end) {
             /* No intersection */
         } else {
             if (start < old_start) {
                 /* Stop at the start of a running allocation */
-                *nb_clusters = old_start - start;
+                bytes = old_start - start;
             } else {
-                *nb_clusters = 0;
+                bytes = 0;
             }
 
-            if (*nb_clusters == 0) {
+            if (bytes == 0) {
                 /* Wait for the dependency to complete. We need to recheck
                  * the free/allocated clusters when we continue. */
                 qemu_co_mutex_unlock(&s->lock);
@@ -794,9 +804,9 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
         }
     }
 
-    if (!*nb_clusters) {
-        abort();
-    }
+    /* Make sure that existing clusters and new allocations are only used up to
+     * the next dependency if we shortened the request above */
+    *cur_bytes = bytes;
 
     return 0;
 }
@@ -875,6 +885,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
     uint64_t *l2_table;
     unsigned int nb_clusters, keep_clusters;
     uint64_t cluster_offset;
+    uint64_t cur_bytes;
 
     trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset,
                                       n_start, n_end);
@@ -887,6 +898,7 @@ again:
     l2_index = offset_to_l2_index(s, offset);
     nb_clusters = MIN(size_to_clusters(s, n_end << BDRV_SECTOR_BITS),
                       s->l2_size - l2_index);
+    n_end = MIN(n_end, nb_clusters * s->cluster_sectors);
 
     /*
      * Now start gathering as many contiguous clusters as possible:
@@ -911,7 +923,8 @@ again:
      * 3. If the request still hasn't completed, allocate new clusters,
      *    considering any cluster_offset of steps 1c or 2.
      */
-    ret = handle_dependencies(bs, offset, &nb_clusters);
+    cur_bytes = (n_end - n_start) * BDRV_SECTOR_SIZE;
+    ret = handle_dependencies(bs, offset, &cur_bytes);
     if (ret == -EAGAIN) {
         goto again;
     } else if (ret < 0) {
@@ -922,6 +935,9 @@ again:
          * correctly during the next loop iteration. */
     }
 
+    nb_clusters = size_to_clusters(s, offset + cur_bytes)
+                - (offset >> s->cluster_bits);
+
     /* Find L2 entry for the first involved cluster */
     ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
     if (ret < 0) {
diff --git a/block/qcow2.h b/block/qcow2.h
index 0940b1b..a99d51b 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -307,6 +307,17 @@ static inline bool qcow2_need_accurate_refcounts(BDRVQcowState *s)
     return !(s->incompatible_features & QCOW2_INCOMPAT_DIRTY);
 }
 
+static inline uint64_t l2meta_cow_start(QCowL2Meta *m)
+{
+    return m->offset + m->cow_start.offset;
+}
+
+static inline uint64_t l2meta_cow_end(QCowL2Meta *m)
+{
+    return m->offset + m->cow_end.offset
+        + (m->cow_end.nb_sectors << BDRV_SECTOR_BITS);
+}
+
 // FIXME Need qcow2_ prefix to global functions
 
 /* qcow2.c functions */
commit d9d74f4177af59bec23baa480d640709f56df0aa
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:57 2013 +0100

    qcow2: Improve check for overlapping allocations
    
    The old code detected an overlapping allocation even when the
    allocations didn't actually overlap, but were only adjacent.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 71e027a..7f4f73e 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -773,7 +773,7 @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
         uint64_t old_start = old_alloc->offset >> s->cluster_bits;
         uint64_t old_end = old_start + old_alloc->nb_clusters;
 
-        if (end < old_start || start > old_end) {
+        if (end <= old_start || start >= old_end) {
             /* No intersection */
         } else {
             if (start < old_start) {
diff --git a/tests/qemu-iotests/038.out b/tests/qemu-iotests/038.out
index acc7629..9cd0cd8 100644
--- a/tests/qemu-iotests/038.out
+++ b/tests/qemu-iotests/038.out
@@ -517,9 +517,7 @@ qemu-io> wrote 65536/65536 bytes at offset 16711680
 qemu-io> Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' 
 
 == Some concurrent requests touching the same cluster ==
-qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> wrote 81920/81920 bytes at offset XXX
-80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-wrote 65536/65536 bytes at offset XXX
+qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -579,6 +577,8 @@ wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset XXX
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
@@ -645,6 +645,8 @@ wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset XXX
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
@@ -703,8 +705,6 @@ wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 65536/65536 bytes at offset XXX
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-wrote 81920/81920 bytes at offset XXX
-80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
 == Verify image content ==
 qemu-io> read 4096/4096 bytes at offset 2064384
commit 17a71e58238138c3f02be7e9f5dc8de5d72a9a9d
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:56 2013 +0100

    qcow2: Handle dependencies earlier
    
    Handling overlapping allocations isn't just a detail of cluster
    allocation. It is rather one of three ways to get the host cluster
    offset for a write request:
    
    1. If a request overlaps an in-flight allocations, the cluster offset
       can be taken from there (this is what handle_dependencies will evolve
       into) or the request must just wait until the allocation has
       completed. Accessing the L2 is not valid in this case, it has
       outdated information.
    
    2. Outside overlapping areas, check the clusters that can be written to
       as they are, with no COW involved.
    
    3. If a COW is required, allocate new clusters
    
    Changing the code to reflect this doesn't change the behaviour because
    overlaps cannot exist for clusters that are kept in step 2. It does
    however make it easier for later patches to work on clusters that belong
    to an allocation that is still in flight.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index d72d063..71e027a 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -824,16 +824,10 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
     uint64_t *host_offset, unsigned int *nb_clusters)
 {
     BDRVQcowState *s = bs->opaque;
-    int ret;
 
     trace_qcow2_do_alloc_clusters_offset(qemu_coroutine_self(), guest_offset,
                                          *host_offset, *nb_clusters);
 
-    ret = handle_dependencies(bs, guest_offset, nb_clusters);
-    if (ret < 0) {
-        return ret;
-    }
-
     /* Allocate new clusters */
     trace_qcow2_cluster_alloc_phys(qemu_coroutine_self());
     if (*host_offset == 0) {
@@ -845,7 +839,7 @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
         *host_offset = cluster_offset;
         return 0;
     } else {
-        ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
+        int ret = qcow2_alloc_clusters_at(bs, *host_offset, *nb_clusters);
         if (ret < 0) {
             return ret;
         }
@@ -885,20 +879,55 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
     trace_qcow2_alloc_clusters_offset(qemu_coroutine_self(), offset,
                                       n_start, n_end);
 
-    /* Find L2 entry for the first involved cluster */
 again:
-    ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
-    if (ret < 0) {
-        return ret;
-    }
-
     /*
      * Calculate the number of clusters to look for. We stop at L2 table
      * boundaries to keep things simple.
      */
+    l2_index = offset_to_l2_index(s, offset);
     nb_clusters = MIN(size_to_clusters(s, n_end << BDRV_SECTOR_BITS),
                       s->l2_size - l2_index);
 
+    /*
+     * Now start gathering as many contiguous clusters as possible:
+     *
+     * 1. Check for overlaps with in-flight allocations
+     *
+     *      a) Overlap not in the first cluster -> shorten this request and let
+     *         the caller handle the rest in its next loop iteration.
+     *
+     *      b) Real overlaps of two requests. Yield and restart the search for
+     *         contiguous clusters (the situation could have changed while we
+     *         were sleeping)
+     *
+     *      c) TODO: Request starts in the same cluster as the in-flight
+     *         allocation ends. Shorten the COW of the in-fight allocation, set
+     *         cluster_offset to write to the same cluster and set up the right
+     *         synchronisation between the in-flight request and the new one.
+     *
+     * 2. Count contiguous COPIED clusters.
+     *    TODO: Consider cluster_offset if set in step 1c.
+     *
+     * 3. If the request still hasn't completed, allocate new clusters,
+     *    considering any cluster_offset of steps 1c or 2.
+     */
+    ret = handle_dependencies(bs, offset, &nb_clusters);
+    if (ret == -EAGAIN) {
+        goto again;
+    } else if (ret < 0) {
+        return ret;
+    } else {
+        /* handle_dependencies() may have decreased cur_bytes (shortened
+         * the allocations below) so that the next dependency is processed
+         * correctly during the next loop iteration. */
+    }
+
+    /* Find L2 entry for the first involved cluster */
+    ret = get_cluster_table(bs, offset, &l2_table, &l2_index);
+    if (ret < 0) {
+        return ret;
+    }
+
     cluster_offset = be64_to_cpu(l2_table[l2_index]);
 
     /*
@@ -963,9 +992,7 @@ again:
         /* Allocate, if necessary at a given offset in the image file */
         ret = do_alloc_cluster_offset(bs, alloc_offset, &alloc_cluster_offset,
                                       &nb_clusters);
-        if (ret == -EAGAIN) {
-            goto again;
-        } else if (ret < 0) {
+        if (ret < 0) {
             goto fail;
         }
 
diff --git a/block/qcow2.h b/block/qcow2.h
index e4b5e11..0940b1b 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -277,6 +277,11 @@ static inline int size_to_l1(BDRVQcowState *s, int64_t size)
     return (size + (1ULL << shift) - 1) >> shift;
 }
 
+static inline int offset_to_l2_index(BDRVQcowState *s, int64_t offset)
+{
+    return (offset >> s->cluster_bits) & (s->l2_size - 1);
+}
+
 static inline int64_t align_offset(int64_t offset, int n)
 {
     offset = (offset + n - 1) & ~(n - 1);
commit 9ee6439e27d15c528fde6d9da1e4c238a23b6b7a
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:55 2013 +0100

    qcow2: Remove bogus unlock of s->lock
    
    The unlock wakes up the next coroutine, but the currently running
    coroutine will lock it again before it yields, so this doesn't make a
    lot of sense.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index 8ea696a..3f7edf5 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -869,9 +869,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs,
                 QLIST_REMOVE(l2meta, next_in_flight);
             }
 
-            qemu_co_mutex_unlock(&s->lock);
             qemu_co_queue_restart_all(&l2meta->dependent_requests);
-            qemu_co_mutex_lock(&s->lock);
 
             g_free(l2meta);
             l2meta = NULL;
commit c349ca4bb2dbca53c15147d283ea9f6c94376c6c
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:54 2013 +0100

    qcow2: Fix "total clusters" number in bdrv_check
    
    This should be based on the virtual disk size, not on the size of the
    image.
    
    Interesting observation: With some VM state stored in the image file,
    percentages higher than 100% are possible, even though snapshots
    themselves are ignored. This is a qcow2 bug to be fixed another day: The
    VM state should be discarded in the active L2 tables after completing
    the snapshot creation.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 9bfb390..c38e970 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1152,9 +1152,11 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
 
     size = bdrv_getlength(bs->file);
     nb_clusters = size_to_clusters(s, size);
-    res->bfi.total_clusters = nb_clusters;
     refcount_table = g_malloc0(nb_clusters * sizeof(uint16_t));
 
+    res->bfi.total_clusters =
+        size_to_clusters(s, bs->total_sectors * BDRV_SECTOR_SIZE);
+
     /* header */
     inc_refcounts(bs, res, refcount_table, nb_clusters,
         0, s->cluster_size);
diff --git a/tests/qemu-iotests/044.out b/tests/qemu-iotests/044.out
index 5eed3f8..34c25c7 100644
--- a/tests/qemu-iotests/044.out
+++ b/tests/qemu-iotests/044.out
@@ -1,5 +1,5 @@
 No errors were found on the image.
-7292415/8391499= 86.90% allocated, 0.00% fragmented, 0.00% compressed clusters
+7292415/33554432 = 21.73% allocated, 0.00% fragmented, 0.00% compressed clusters
 Image end offset: 4296447488
 .
 ----------------------------------------------------------------------
commit 6f74928192e8e8a16f64b6208171eb13af890bbc
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Tue Mar 26 17:49:53 2013 +0100

    qemu-iotests: More concurrent allocation scenarios
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/tests/qemu-iotests/046 b/tests/qemu-iotests/046
index e0176f4..987bfff 100755
--- a/tests/qemu-iotests/046
+++ b/tests/qemu-iotests/046
@@ -66,7 +66,7 @@ function backing_io()
     done
 }
 
-backing_io 0 16 write | $QEMU_IO $TEST_IMG | _filter_qemu_io
+backing_io 0 32 write | $QEMU_IO $TEST_IMG | _filter_qemu_io
 
 mv $TEST_IMG $TEST_IMG.base
 
@@ -153,6 +153,36 @@ aio_write -P 101 0xaa000 0xe000
 resume A
 aio_flush
 EOF
+
+# Reverse sequential write
+cat  <<EOF
+break write_aio A
+aio_write -P 121 0xdc000 0x2000
+wait_break A
+aio_write -P 120 0xc4000 0x18000
+resume A
+aio_flush
+EOF
+
+# Reverse sequential write with a gap
+cat  <<EOF
+break write_aio A
+aio_write -P 141 0xfc000 0x2000
+wait_break A
+aio_write -P 140 0xe4000 0x14000
+resume A
+aio_flush
+EOF
+
+# Allocate an area in the middle and then overwrite with a larger request
+cat  <<EOF
+break write_aio A
+aio_write -P 161 0x10c000 0x8000
+wait_break A
+aio_write -P 160 0x104000 0x18000
+resume A
+aio_flush
+EOF
 }
 
 overlay_io | $QEMU_IO blkdebug::$TEST_IMG | _filter_qemu_io |\
@@ -203,6 +233,23 @@ function verify_io()
     echo read -P 10  0xa8000 0x2000
     echo read -P 101 0xaa000 0xe000
     echo read -P 110 0xb8000 0x8000
+
+    echo read -P 12  0xc0000 0x4000
+    echo read -P 120 0xc4000 0x18000
+    echo read -P 121 0xdc000 0x2000
+    echo read -P 13  0xde000 0x2000
+
+    echo read -P 14  0xe0000 0x4000
+    echo read -P 140 0xe4000 0x14000
+    echo read -P 15  0xf8000 0x4000
+    echo read -P 141 0xfc000 0x2000
+    echo read -P 15  0xfe000 0x2000
+
+    echo read -P 16  0x100000 0x4000
+    echo read -P 160 0x104000 0x8000
+    # Undefined content for 0x10c000 0x8000
+    echo read -P 160 0x114000 0x8000
+    echo read -P 17  0x11c000 0x4000
 }
 
 verify_io | $QEMU_IO $TEST_IMG | _filter_qemu_io
diff --git a/tests/qemu-iotests/046.out b/tests/qemu-iotests/046.out
index 565360f..4b50a17e 100644
--- a/tests/qemu-iotests/046.out
+++ b/tests/qemu-iotests/046.out
@@ -34,6 +34,38 @@ qemu-io> wrote 65536/65536 bytes at offset 917504
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-io> wrote 65536/65536 bytes at offset 983040
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1048576
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1114112
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1179648
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1245184
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1310720
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1376256
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1441792
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1507328
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1572864
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1638400
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1703936
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1769472
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1835008
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1900544
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 1966080
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> wrote 65536/65536 bytes at offset 2031616
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-io> Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' 
 
 == Some concurrent requests touching the same cluster ==
@@ -89,6 +121,24 @@ qemu-io> wrote 8192/8192 bytes at offset XXX
 8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 wrote 57344/57344 bytes at offset XXX
 56 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-io> blkdebug: Suspended request 'A'
+qemu-io> qemu-io> qemu-io> blkdebug: Resuming request 'A'
+qemu-io> wrote 8192/8192 bytes at offset XXX
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 98304/98304 bytes at offset XXX
+96 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-io> blkdebug: Suspended request 'A'
+qemu-io> qemu-io> qemu-io> blkdebug: Resuming request 'A'
+qemu-io> wrote 8192/8192 bytes at offset XXX
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 81920/81920 bytes at offset XXX
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> qemu-io> blkdebug: Suspended request 'A'
+qemu-io> qemu-io> qemu-io> blkdebug: Resuming request 'A'
+qemu-io> wrote 32768/32768 bytes at offset XXX
+32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 98304/98304 bytes at offset XXX
+96 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-io> 
 == Verify image content ==
 qemu-io> read 65536/65536 bytes at offset 0
@@ -159,5 +209,31 @@ qemu-io> read 57344/57344 bytes at offset 696320
 56 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-io> read 32768/32768 bytes at offset 753664
 32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 16384/16384 bytes at offset 786432
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 98304/98304 bytes at offset 802816
+96 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 901120
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 909312
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 16384/16384 bytes at offset 917504
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 81920/81920 bytes at offset 933888
+80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 16384/16384 bytes at offset 1015808
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 1032192
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 8192/8192 bytes at offset 1040384
+8 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 16384/16384 bytes at offset 1048576
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 32768/32768 bytes at offset 1064960
+32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 32768/32768 bytes at offset 1130496
+32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-io> read 16384/16384 bytes at offset 1163264
+16 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 qemu-io> No errors were found on the image.
 *** done
commit 142c6b1a89c3af769fbab6a22f51eefa7a3b0330
Author: Peter Lieven <pl at kamp.de>
Date:   Thu Mar 21 13:07:10 2013 +0100

    vl.c: call bdrv_init_with_whitelist() before cmdline parsing
    
    commit 4d454574 "qemu-option: move standard option definitions
    out of qemu-config.c" broke support for commandline option
    groups that where registered during bdrv_init(). In particular
    support for -iscsi options was broken since that commit.
    
    Fix by moving the bdrv_init_with_whitelist() before command
    line argument parsing.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/vl.c b/vl.c
index 7643f16..7f86a40 100644
--- a/vl.c
+++ b/vl.c
@@ -2941,6 +2941,8 @@ int main(int argc, char **argv, char **envp)
     nb_numa_nodes = 0;
     nb_nics = 0;
 
+    bdrv_init_with_whitelist();
+
     autostart= 1;
 
     /* first pass of option parsing */
@@ -4199,8 +4201,6 @@ int main(int argc, char **argv, char **envp)
 
     cpu_exec_init_all();
 
-    bdrv_init_with_whitelist();
-
     blk_mig_init();
 
     /* open the virtual block devices */
commit b0d62a3d8e1ea9eccd246829a03e2d23f0982431
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Mar 26 12:35:09 2013 +0000

    hw/tcx: Remove unused 'addr' field and the property that sets it
    
    Remove the 'addr' field from TCXState (since it is completely unused),
    also the qdev property which sets it. This seems to be a relic from
    many years past; devices don't need to know where they are mapped.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 2f214da..9ebda02 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -575,7 +575,6 @@ static void tcx_init(hwaddr addr, int vram_size, int width,
     SysBusDevice *s;
 
     dev = qdev_create(NULL, "SUNW,tcx");
-    qdev_prop_set_taddr(dev, "addr", addr);
     qdev_prop_set_uint32(dev, "vram_size", vram_size);
     qdev_prop_set_uint16(dev, "width", width);
     qdev_prop_set_uint16(dev, "height", height);
diff --git a/hw/tcx.c b/hw/tcx.c
index f1edffd..c44068e 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -37,7 +37,6 @@
 
 typedef struct TCXState {
     SysBusDevice busdev;
-    hwaddr addr;
     QemuConsole *con;
     uint8_t *vram;
     uint32_t *vram24, *cplane;
@@ -707,7 +706,6 @@ write_err:
 }
 
 static Property tcx_properties[] = {
-    DEFINE_PROP_TADDR("addr",      TCXState, addr,      -1),
     DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1),
     DEFINE_PROP_UINT16("width",    TCXState, width,     -1),
     DEFINE_PROP_UINT16("height",   TCXState, height,    -1),
commit 0f9d76e5a9a396a2209761265ba6d98ce89b6a32
Author: liguang <lig.fnst at cn.fujitsu.com>
Date:   Tue Mar 26 16:43:19 2013 +0800

    hw/i386/pc: format load_linux function
    
    Signed-off-by: liguang <lig.fnst at cn.fujitsu.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index ed7d9ba..b1e06fa 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -646,8 +646,8 @@ static long get_file_size(FILE *f)
 
 static void load_linux(void *fw_cfg,
                        const char *kernel_filename,
-		       const char *initrd_filename,
-		       const char *kernel_cmdline,
+                       const char *initrd_filename,
+                       const char *kernel_cmdline,
                        hwaddr max_ram_size)
 {
     uint16_t protocol;
@@ -664,60 +664,62 @@ static void load_linux(void *fw_cfg,
     /* load the kernel header */
     f = fopen(kernel_filename, "rb");
     if (!f || !(kernel_size = get_file_size(f)) ||
-	fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=
-	MIN(ARRAY_SIZE(header), kernel_size)) {
-	fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
-		kernel_filename, strerror(errno));
-	exit(1);
+        fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=
+        MIN(ARRAY_SIZE(header), kernel_size)) {
+        fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
+                kernel_filename, strerror(errno));
+        exit(1);
     }
 
     /* kernel protocol version */
 #if 0
     fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202));
 #endif
-    if (ldl_p(header+0x202) == 0x53726448)
-	protocol = lduw_p(header+0x206);
-    else {
-	/* This looks like a multiboot kernel. If it is, let's stop
-	   treating it like a Linux kernel. */
+    if (ldl_p(header+0x202) == 0x53726448) {
+        protocol = lduw_p(header+0x206);
+    } else {
+        /* This looks like a multiboot kernel. If it is, let's stop
+           treating it like a Linux kernel. */
         if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename,
-                           kernel_cmdline, kernel_size, header))
+                           kernel_cmdline, kernel_size, header)) {
             return;
-	protocol = 0;
+        }
+        protocol = 0;
     }
 
     if (protocol < 0x200 || !(header[0x211] & 0x01)) {
-	/* Low kernel */
-	real_addr    = 0x90000;
-	cmdline_addr = 0x9a000 - cmdline_size;
-	prot_addr    = 0x10000;
+        /* Low kernel */
+        real_addr    = 0x90000;
+        cmdline_addr = 0x9a000 - cmdline_size;
+        prot_addr    = 0x10000;
     } else if (protocol < 0x202) {
-	/* High but ancient kernel */
-	real_addr    = 0x90000;
-	cmdline_addr = 0x9a000 - cmdline_size;
-	prot_addr    = 0x100000;
+        /* High but ancient kernel */
+        real_addr    = 0x90000;
+        cmdline_addr = 0x9a000 - cmdline_size;
+        prot_addr    = 0x100000;
     } else {
-	/* High and recent kernel */
-	real_addr    = 0x10000;
-	cmdline_addr = 0x20000;
-	prot_addr    = 0x100000;
+        /* High and recent kernel */
+        real_addr    = 0x10000;
+        cmdline_addr = 0x20000;
+        prot_addr    = 0x100000;
     }
 
 #if 0
     fprintf(stderr,
-	    "qemu: real_addr     = 0x" TARGET_FMT_plx "\n"
-	    "qemu: cmdline_addr  = 0x" TARGET_FMT_plx "\n"
-	    "qemu: prot_addr     = 0x" TARGET_FMT_plx "\n",
-	    real_addr,
-	    cmdline_addr,
-	    prot_addr);
+            "qemu: real_addr     = 0x" TARGET_FMT_plx "\n"
+            "qemu: cmdline_addr  = 0x" TARGET_FMT_plx "\n"
+            "qemu: prot_addr     = 0x" TARGET_FMT_plx "\n",
+            real_addr,
+            cmdline_addr,
+            prot_addr);
 #endif
 
     /* highest address for loading the initrd */
-    if (protocol >= 0x203)
-	initrd_max = ldl_p(header+0x22c);
-    else
-	initrd_max = 0x37ffffff;
+    if (protocol >= 0x203) {
+        initrd_max = ldl_p(header+0x22c);
+    } else {
+        initrd_max = 0x37ffffff;
+    }
 
     if (initrd_max >= max_ram_size-ACPI_DATA_SIZE)
     	initrd_max = max_ram_size-ACPI_DATA_SIZE-1;
@@ -727,10 +729,10 @@ static void load_linux(void *fw_cfg,
     fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
 
     if (protocol >= 0x202) {
-	stl_p(header+0x228, cmdline_addr);
+        stl_p(header+0x228, cmdline_addr);
     } else {
-	stw_p(header+0x20, 0xA33F);
-	stw_p(header+0x22, cmdline_addr-real_addr);
+        stw_p(header+0x20, 0xA33F);
+        stw_p(header+0x22, cmdline_addr-real_addr);
     }
 
     /* handle vga= parameter */
@@ -755,23 +757,23 @@ static void load_linux(void *fw_cfg,
     /* High nybble = B reserved for QEMU; low nybble is revision number.
        If this code is substantially changed, you may want to consider
        incrementing the revision. */
-    if (protocol >= 0x200)
-	header[0x210] = 0xB0;
-
+    if (protocol >= 0x200) {
+        header[0x210] = 0xB0;
+    }
     /* heap */
     if (protocol >= 0x201) {
-	header[0x211] |= 0x80;	/* CAN_USE_HEAP */
-	stw_p(header+0x224, cmdline_addr-real_addr-0x200);
+        header[0x211] |= 0x80;	/* CAN_USE_HEAP */
+        stw_p(header+0x224, cmdline_addr-real_addr-0x200);
     }
 
     /* load initrd */
     if (initrd_filename) {
-	if (protocol < 0x200) {
-	    fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");
-	    exit(1);
-	}
+        if (protocol < 0x200) {
+            fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");
+            exit(1);
+        }
 
-	initrd_size = get_image_size(initrd_filename);
+        initrd_size = get_image_size(initrd_filename);
         if (initrd_size < 0) {
             fprintf(stderr, "qemu: error reading initrd %s\n",
                     initrd_filename);
@@ -787,14 +789,15 @@ static void load_linux(void *fw_cfg,
         fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
         fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size);
 
-	stl_p(header+0x218, initrd_addr);
-	stl_p(header+0x21c, initrd_size);
+        stl_p(header+0x218, initrd_addr);
+        stl_p(header+0x21c, initrd_size);
     }
 
     /* load kernel and setup */
     setup_size = header[0x1f1];
-    if (setup_size == 0)
-	setup_size = 4;
+    if (setup_size == 0) {
+        setup_size = 4;
+    }
     setup_size = (setup_size+1)*512;
     kernel_size -= setup_size;
 
commit 9941afdef4fc898ed1588468095d1e36574427a1
Author: Dunrong Huang <huangdr at cloud-times.com>
Date:   Sun Mar 24 15:05:27 2013 +0800

    configure: show debug-info option in --help output
    
    "--enable-debug-info" and "--disable-debug-info" were not shown
    in --help output.
    
    Signed-off-by: Dunrong Huang <huangdr at cloud-times.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/configure b/configure
index f2af714..61e71fa 100755
--- a/configure
+++ b/configure
@@ -1057,6 +1057,8 @@ echo "  --localstatedir=PATH     install local state in PATH"
 echo "  --with-confsuffix=SUFFIX suffix for QEMU data inside datadir and sysconfdir [$confsuffix]"
 echo "  --enable-debug-tcg       enable TCG debugging"
 echo "  --disable-debug-tcg      disable TCG debugging (default)"
+echo "  --enable-debug-info       enable debugging information (default)"
+echo "  --disable-debug-info      disable debugging information"
 echo "  --enable-debug           enable common debug build options"
 echo "  --enable-sparse          enable sparse checker"
 echo "  --disable-sparse         disable sparse checker (default)"
commit e280ff5e9159ed227a117339c1157143627cab96
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:08:03 2013 +0100

    spice-qemu-char: Drop hackish vmc_register on spice_chr_write
    
    Now that the core takes care of fe_open tracking we no longer need this hack.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-12-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index d249829..535f955 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -149,7 +149,6 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
     SpiceCharDriver *s = chr->opaque;
 
-    vmc_register_interface(s);
     assert(s->datalen == 0);
     if (s->bufsize < len) {
         s->bufsize = len;
commit bc6b815d9e34778aa7fbe785ecfa0b216c96f576
Author: Alon Levy <alevy at redhat.com>
Date:   Tue Mar 26 11:08:02 2013 +0100

    virtio-serial: propagate guest_connected to the port on post_load
    
    When migrating a host with with a spice agent running the mouse becomes
    non operational after the migration due to the agent state being
    inconsistent between the guest and the client.
    
    After migration the spicevmc backend on the destination has never been notified
    of the (non 0) guest_connected state. Virtio-serial holds this state
    information and migrates it, this patch properly propagates this information
    to virtio-console and through that to interested chardev backends.
    
    rhbz #725965
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-11-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index eb7af21..a9cb114 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -579,6 +579,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
     VirtIOSerial *s = opaque;
     VirtIOSerialPort *port;
     uint8_t host_connected;
+    VirtIOSerialPortClass *vsc;
 
     if (!s->post_load) {
         return;
@@ -594,6 +595,10 @@ static void virtio_serial_post_load_timer_cb(void *opaque)
             send_control_event(s, port->id, VIRTIO_CONSOLE_PORT_OPEN,
                                port->host_connected);
         }
+        vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
+        if (vsc->set_guest_connected) {
+            vsc->set_guest_connected(port, port->guest_connected);
+        }
     }
     g_free(s->post_load->connected);
     qemu_free_timer(s->post_load->timer);
commit b2c1394af13b46a72cd27ff580cdd1d9bb1e8934
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:08:01 2013 +0100

    virtio-serial: Consolidate guest_open/guest_close into set_guest_connected
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-10-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index 7c89990..284180f 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -66,26 +66,15 @@ static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
     return ret;
 }
 
-/* Callback function that's called when the guest opens the port */
-static void guest_open(VirtIOSerialPort *port)
+/* Callback function that's called when the guest opens/closes the port */
+static void set_guest_connected(VirtIOSerialPort *port, int guest_connected)
 {
     VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
 
     if (!vcon->chr) {
         return;
     }
-    qemu_chr_fe_set_open(vcon->chr, 1);
-}
-
-/* Callback function that's called when the guest closes the port */
-static void guest_close(VirtIOSerialPort *port)
-{
-    VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
-
-    if (!vcon->chr) {
-        return;
-    }
-    qemu_chr_fe_set_open(vcon->chr, 0);
+    qemu_chr_fe_set_open(vcon->chr, guest_connected);
 }
 
 /* Readiness of the guest to accept data on a port */
@@ -152,8 +141,7 @@ static void virtconsole_class_init(ObjectClass *klass, void *data)
     k->is_console = true;
     k->init = virtconsole_initfn;
     k->have_data = flush_buf;
-    k->guest_open = guest_open;
-    k->guest_close = guest_close;
+    k->set_guest_connected = set_guest_connected;
     dc->props = virtconsole_properties;
 }
 
@@ -176,8 +164,7 @@ static void virtserialport_class_init(ObjectClass *klass, void *data)
 
     k->init = virtconsole_initfn;
     k->have_data = flush_buf;
-    k->guest_open = guest_open;
-    k->guest_close = guest_close;
+    k->set_guest_connected = set_guest_connected;
     dc->props = virtserialport_properties;
 }
 
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index ab7168e..eb7af21 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -372,14 +372,9 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
 
     case VIRTIO_CONSOLE_PORT_OPEN:
         port->guest_connected = cpkt.value;
-        if (cpkt.value && vsc->guest_open) {
+        if (vsc->set_guest_connected) {
             /* Send the guest opened notification if an app is interested */
-            vsc->guest_open(port);
-        }
-
-        if (!cpkt.value && vsc->guest_close) {
-            /* Send the guest closed notification if an app is interested */
-            vsc->guest_close(port);
+            vsc->set_guest_connected(port, cpkt.value);
         }
         break;
     }
@@ -484,9 +479,9 @@ static void guest_reset(VirtIOSerial *vser)
         vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
         if (port->guest_connected) {
             port->guest_connected = false;
-
-            if (vsc->guest_close)
-                vsc->guest_close(port);
+            if (vsc->set_guest_connected) {
+                vsc->set_guest_connected(port, false);
+            }
         }
     }
 }
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index 484dcfe..516400f 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -92,10 +92,8 @@ typedef struct VirtIOSerialPortClass {
     int (*exit)(VirtIOSerialPort *port);
 
     /* Callbacks for guest events */
-        /* Guest opened device. */
-    void (*guest_open)(VirtIOSerialPort *port);
-        /* Guest closed device. */
-    void (*guest_close)(VirtIOSerialPort *port);
+        /* Guest opened/closed device. */
+    void (*set_guest_connected)(VirtIOSerialPort *port, int guest_connected);
 
         /* Guest is now ready to accept data (virtqueues set up). */
     void (*guest_ready)(VirtIOSerialPort *port);
commit a59bcd31c91397f8c67b6902e7716d626c5070e6
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:08:00 2013 +0100

    qemu-char: add_handlers: Don't re-send the be_open event on unregister
    
    Resending the be_open event only is useful when a frontend is registering, not
    when it is unregistering.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-9-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-char.c b/qemu-char.c
index ca9381b..dee623e 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -241,7 +241,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
 
     /* We're connecting to an already opened device, so let's make sure we
        also get the open event */
-    if (s->be_open) {
+    if (fe_open && s->be_open) {
         qemu_chr_be_generic_open(s);
     }
 }
commit 85d91e3295f3af21e4d4a19f1f6691c0bf2ed10c
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:59 2013 +0100

    qemu-char: Move incrementing of avail_connections to qdev-properties-system
    
    The decrement of avail_connections is done in qdev-properties-system move
    the increment there too for proper balancing of the calls.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-8-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c
index 28813d3..d9934b5 100644
--- a/hw/qdev-properties-system.c
+++ b/hw/qdev-properties-system.c
@@ -136,9 +136,11 @@ static void release_chr(Object *obj, const char *name, void *opaque)
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
     CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
+    CharDriverState *chr = *ptr;
 
-    if (*ptr) {
-        qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
+    if (chr) {
+        qemu_chr_add_handlers(chr, NULL, NULL, NULL, NULL);
+        ++chr->avail_connections;
     }
 }
 
diff --git a/qemu-char.c b/qemu-char.c
index bab2eb7..ca9381b 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -224,8 +224,6 @@ void qemu_chr_add_handlers(CharDriverState *s,
     int fe_open;
 
     if (!opaque && !fd_can_read && !fd_read && !fd_event) {
-        /* chr driver being released. */
-        ++s->avail_connections;
         fe_open = 0;
     } else {
         fe_open = 1;
commit 574b711a92db094a2d4e7ca707f3b34437a64246
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:58 2013 +0100

    qemu-char: Consolidate guest_close/guest_open into a set_fe_open callback
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-7-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/char/char.h b/include/char/char.h
index a726ddc..32c9999 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -68,8 +68,7 @@ struct CharDriverState {
     void (*chr_close)(struct CharDriverState *chr);
     void (*chr_accept_input)(struct CharDriverState *chr);
     void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
-    void (*chr_guest_open)(struct CharDriverState *chr);
-    void (*chr_guest_close)(struct CharDriverState *chr);
+    void (*chr_set_fe_open)(struct CharDriverState *chr, int fe_open);
     void *opaque;
     int idle_tag;
     char *label;
diff --git a/qemu-char.c b/qemu-char.c
index 29a2462..bab2eb7 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -514,8 +514,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
     chr->chr_update_read_handler = mux_chr_update_read_handler;
     chr->chr_accept_input = mux_chr_accept_input;
     /* Frontend guest-open / -close notification is not support with muxes */
-    chr->chr_guest_open = NULL;
-    chr->chr_guest_close = NULL;
+    chr->chr_set_fe_open = NULL;
 
     /* Muxes are always open on creation */
     qemu_chr_be_generic_open(chr);
@@ -3425,11 +3424,8 @@ void qemu_chr_fe_set_open(struct CharDriverState *chr, int fe_open)
         return;
     }
     chr->fe_open = fe_open;
-    if (fe_open && chr->chr_guest_open) {
-        chr->chr_guest_open(chr);
-    }
-    if (!fe_open && chr->chr_guest_close) {
-        chr->chr_guest_close(chr);
+    if (chr->chr_set_fe_open) {
+        chr->chr_set_fe_open(chr, fe_open);
     }
 }
 
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index c39095b..d249829 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -176,16 +176,14 @@ static void spice_chr_close(struct CharDriverState *chr)
     g_free(s);
 }
 
-static void spice_chr_guest_open(struct CharDriverState *chr)
+static void spice_chr_set_fe_open(struct CharDriverState *chr, int fe_open)
 {
     SpiceCharDriver *s = chr->opaque;
-    vmc_register_interface(s);
-}
-
-static void spice_chr_guest_close(struct CharDriverState *chr)
-{
-    SpiceCharDriver *s = chr->opaque;
-    vmc_unregister_interface(s);
+    if (fe_open) {
+        vmc_register_interface(s);
+    } else {
+        vmc_unregister_interface(s);
+    }
 }
 
 static void print_allowed_subtypes(void)
@@ -218,8 +216,7 @@ static CharDriverState *chr_open(const char *subtype)
     chr->opaque = s;
     chr->chr_write = spice_chr_write;
     chr->chr_close = spice_chr_close;
-    chr->chr_guest_open = spice_chr_guest_open;
-    chr->chr_guest_close = spice_chr_guest_close;
+    chr->chr_set_fe_open = spice_chr_set_fe_open;
 
     QLIST_INSERT_HEAD(&spice_chars, s, next);
 
commit 8e25daa87ac98c9070365b42dcfc070e47fca934
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:57 2013 +0100

    qemu-char: Cleanup: consolidate fe_open/fe_close into fe_set_open
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-6-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index 2f7c3df..7c89990 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -74,7 +74,7 @@ static void guest_open(VirtIOSerialPort *port)
     if (!vcon->chr) {
         return;
     }
-    qemu_chr_fe_open(vcon->chr);
+    qemu_chr_fe_set_open(vcon->chr, 1);
 }
 
 /* Callback function that's called when the guest closes the port */
@@ -85,7 +85,7 @@ static void guest_close(VirtIOSerialPort *port)
     if (!vcon->chr) {
         return;
     }
-    qemu_chr_fe_close(vcon->chr);
+    qemu_chr_fe_set_open(vcon->chr, 0);
 }
 
 /* Readiness of the guest to accept data on a port */
diff --git a/include/char/char.h b/include/char/char.h
index 3cd2aef..a726ddc 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -129,21 +129,12 @@ void qemu_chr_delete(CharDriverState *chr);
 void qemu_chr_fe_set_echo(struct CharDriverState *chr, bool echo);
 
 /**
- * @qemu_chr_fe_open:
+ * @qemu_chr_fe_set_open:
  *
- * Open a character backend.  This function call is an indication that the
- * front end is ready to begin doing I/O.
+ * Set character frontend open status.  This is an indication that the
+ * front end is ready (or not) to begin doing I/O.
  */
-void qemu_chr_fe_open(struct CharDriverState *chr);
-
-/**
- * @qemu_chr_fe_close:
- *
- * Close a character backend.  This function call indicates that the front end
- * no longer is able to process I/O.  To process I/O again, the front end will
- * call @qemu_chr_fe_open.
- */
-void qemu_chr_fe_close(struct CharDriverState *chr);
+void qemu_chr_fe_set_open(struct CharDriverState *chr, int fe_open);
 
 /**
  * @qemu_chr_fe_printf:
diff --git a/qemu-char.c b/qemu-char.c
index 947541a..29a2462 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -238,11 +238,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
         s->chr_update_read_handler(s);
 
     if (!s->explicit_fe_open) {
-        if (fe_open) {
-            qemu_chr_fe_open(s);
-        } else {
-            qemu_chr_fe_close(s);
-        }
+        qemu_chr_fe_set_open(s, fe_open);
     }
 
     /* We're connecting to an already opened device, so let's make sure we
@@ -3423,24 +3419,16 @@ void qemu_chr_fe_set_echo(struct CharDriverState *chr, bool echo)
     }
 }
 
-void qemu_chr_fe_open(struct CharDriverState *chr)
+void qemu_chr_fe_set_open(struct CharDriverState *chr, int fe_open)
 {
-    if (chr->fe_open) {
+    if (chr->fe_open == fe_open) {
         return;
     }
-    chr->fe_open = 1;
-    if (chr->chr_guest_open) {
+    chr->fe_open = fe_open;
+    if (fe_open && chr->chr_guest_open) {
         chr->chr_guest_open(chr);
     }
-}
-
-void qemu_chr_fe_close(struct CharDriverState *chr)
-{
-    if (!chr->fe_open) {
-        return;
-    }
-    chr->fe_open = 0;
-    if (chr->chr_guest_close) {
+    if (!fe_open && chr->chr_guest_close) {
         chr->chr_guest_close(chr);
     }
 }
commit 190832289fe670f764fb277e4dcaf00f94ca6553
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:56 2013 +0100

    qemu-char: Automatically do fe_open / fe_close on qemu_chr_add_handlers
    
    Most frontends can't really determine if the guest actually has the frontend
    side open. So lets automatically generate fe_open / fe_close as soon as a
    frontend becomes ready (as signalled by calling qemu_chr_add_handlers) /
    becomes non ready (as signalled by setting all handlers to NULL).
    
    And allow frontends which can actually determine if the guest is listening to
    opt-out of this.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-5-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 9734e42..d02a7b9 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1282,7 +1282,6 @@ static int usbredir_initfn(USBDevice *udev)
     dev->compatible_speedmask = USB_SPEED_MASK_FULL | USB_SPEED_MASK_HIGH;
 
     /* Let the backend know we are ready */
-    qemu_chr_fe_open(dev->cs);
     qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
                           usbredir_chardev_read, usbredir_chardev_event, dev);
 
@@ -1306,7 +1305,6 @@ static void usbredir_handle_destroy(USBDevice *udev)
 {
     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
 
-    qemu_chr_fe_close(dev->cs);
     qemu_chr_delete(dev->cs);
     /* Note must be done after qemu_chr_close, as that causes a close event */
     qemu_bh_delete(dev->chardev_close_bh);
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index e2d1c58..2f7c3df 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -131,6 +131,7 @@ static int virtconsole_initfn(VirtIOSerialPort *port)
     }
 
     if (vcon->chr) {
+        vcon->chr->explicit_fe_open = 1;
         qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
                               vcon);
     }
diff --git a/include/char/char.h b/include/char/char.h
index dbb1b89..3cd2aef 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -76,6 +76,7 @@ struct CharDriverState {
     char *filename;
     int be_open;
     int fe_open;
+    int explicit_fe_open;
     int avail_connections;
     QemuOpts *opts;
     QTAILQ_ENTRY(CharDriverState) next;
diff --git a/qemu-char.c b/qemu-char.c
index c9890ad..947541a 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -221,9 +221,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
                            IOEventHandler *fd_event,
                            void *opaque)
 {
+    int fe_open;
+
     if (!opaque && !fd_can_read && !fd_read && !fd_event) {
         /* chr driver being released. */
         ++s->avail_connections;
+        fe_open = 0;
+    } else {
+        fe_open = 1;
     }
     s->chr_can_read = fd_can_read;
     s->chr_read = fd_read;
@@ -232,6 +237,14 @@ void qemu_chr_add_handlers(CharDriverState *s,
     if (s->chr_update_read_handler)
         s->chr_update_read_handler(s);
 
+    if (!s->explicit_fe_open) {
+        if (fe_open) {
+            qemu_chr_fe_open(s);
+        } else {
+            qemu_chr_fe_close(s);
+        }
+    }
+
     /* We're connecting to an already opened device, so let's make sure we
        also get the open event */
     if (s->be_open) {
commit c0c4bd2cfae0fb83696000f1bfc355f22e2b41cb
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:55 2013 +0100

    qemu-char: Add fe_open tracking
    
    Add tracking of the fe_open state to struct CharDriverState.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-4-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/char/char.h b/include/char/char.h
index e9d2c10..dbb1b89 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -75,6 +75,7 @@ struct CharDriverState {
     char *label;
     char *filename;
     int be_open;
+    int fe_open;
     int avail_connections;
     QemuOpts *opts;
     QTAILQ_ENTRY(CharDriverState) next;
diff --git a/qemu-char.c b/qemu-char.c
index 345fd67..c9890ad 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3412,6 +3412,10 @@ void qemu_chr_fe_set_echo(struct CharDriverState *chr, bool echo)
 
 void qemu_chr_fe_open(struct CharDriverState *chr)
 {
+    if (chr->fe_open) {
+        return;
+    }
+    chr->fe_open = 1;
     if (chr->chr_guest_open) {
         chr->chr_guest_open(chr);
     }
@@ -3419,6 +3423,10 @@ void qemu_chr_fe_open(struct CharDriverState *chr)
 
 void qemu_chr_fe_close(struct CharDriverState *chr)
 {
+    if (!chr->fe_open) {
+        return;
+    }
+    chr->fe_open = 0;
     if (chr->chr_guest_close) {
         chr->chr_guest_close(chr);
     }
commit fee204fd46016c168ca4d404d04e2c06b8b34770
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:54 2013 +0100

    qemu-char: Rename qemu_chr_generic_open to qemu_chr_be_generic_open
    
    To better reflect that it is for handling a backend being opened.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-3-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/backends/baum.c b/backends/baum.c
index d7d658c..ea9ffe8 100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@ -611,7 +611,7 @@ CharDriverState *chr_baum_init(void)
 
     qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
 
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
 
     return chr;
 
diff --git a/include/char/char.h b/include/char/char.h
index 90443fc..e9d2c10 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -250,7 +250,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
                            IOEventHandler *fd_event,
                            void *opaque);
 
-void qemu_chr_generic_open(CharDriverState *s);
+void qemu_chr_be_generic_open(CharDriverState *s);
 void qemu_chr_accept_input(CharDriverState *s);
 int qemu_chr_add_client(CharDriverState *s, int fd);
 void qemu_chr_info_print(Monitor *mon, const QObject *ret_data);
diff --git a/qemu-char.c b/qemu-char.c
index 4419817..345fd67 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -120,7 +120,7 @@ void qemu_chr_be_event(CharDriverState *s, int event)
     s->chr_event(s->handler_opaque, event);
 }
 
-static gboolean qemu_chr_generic_open_bh(gpointer opaque)
+static gboolean qemu_chr_be_generic_open_bh(gpointer opaque)
 {
     CharDriverState *s = opaque;
     qemu_chr_be_event(s, CHR_EVENT_OPENED);
@@ -128,10 +128,10 @@ static gboolean qemu_chr_generic_open_bh(gpointer opaque)
     return FALSE;
 }
 
-void qemu_chr_generic_open(CharDriverState *s)
+void qemu_chr_be_generic_open(CharDriverState *s)
 {
     if (s->idle_tag == 0) {
-        s->idle_tag = g_idle_add(qemu_chr_generic_open_bh, s);
+        s->idle_tag = g_idle_add(qemu_chr_be_generic_open_bh, s);
     }
 }
 
@@ -235,7 +235,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
     /* We're connecting to an already opened device, so let's make sure we
        also get the open event */
     if (s->be_open) {
-        qemu_chr_generic_open(s);
+        qemu_chr_be_generic_open(s);
     }
 }
 
@@ -509,7 +509,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
     chr->chr_guest_close = NULL;
 
     /* Muxes are always open on creation */
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
 
     return chr;
 }
@@ -863,7 +863,7 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     chr->chr_update_read_handler = fd_chr_update_read_handler;
     chr->chr_close = fd_chr_close;
 
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
 
     return chr;
 }
@@ -1160,7 +1160,7 @@ static void pty_chr_state(CharDriverState *chr, int connected)
         pty_chr_rearm_timer(chr, 1000);
     } else {
         if (!s->connected)
-            qemu_chr_generic_open(chr);
+            qemu_chr_be_generic_open(chr);
         s->connected = 1;
     }
 }
@@ -1576,7 +1576,7 @@ static CharDriverState *qemu_chr_open_pp_fd(int fd)
     chr->chr_close = pp_close;
     chr->opaque = drv;
 
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
 
     return chr;
 }
@@ -1861,7 +1861,7 @@ static CharDriverState *qemu_chr_open_win_path(const char *filename)
         g_free(chr);
         return NULL;
     }
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
     return chr;
 }
 
@@ -1961,7 +1961,7 @@ static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
         g_free(chr);
         return NULL;
     }
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
     return chr;
 }
 
@@ -1975,7 +1975,7 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
     s->hcom = fd_out;
     chr->opaque = s;
     chr->chr_write = win_chr_write;
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
     return chr;
 }
 
@@ -2540,7 +2540,7 @@ static void tcp_chr_connect(void *opaque)
     if (s->chan) {
         s->tag = io_add_watch_poll(s->chan, tcp_chr_read_poll, tcp_chr_read, chr);
     }
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
 }
 
 #define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c;
diff --git a/ui/console.c b/ui/console.c
index eb7a2bc..e84ba8b 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1600,7 +1600,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
         s->t_attrib = s->t_attrib_default;
     }
 
-    qemu_chr_generic_open(chr);
+    qemu_chr_be_generic_open(chr);
     if (chr->init)
         chr->init(chr);
 }
diff --git a/ui/gtk.c b/ui/gtk.c
index 1edfaca..a5a8156 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1163,7 +1163,7 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
 
     gtk_menu_shell_append(GTK_MENU_SHELL(s->view_menu), vc->menu_item);
 
-    qemu_chr_generic_open(vc->chr);
+    qemu_chr_be_generic_open(vc->chr);
     if (vc->chr->init) {
         vc->chr->init(vc->chr);
     }
commit 16665b943b23e953220df257e7e04e669aa384d5
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 11:07:53 2013 +0100

    qemu-char: Rename opened to be_open
    
    Rename the opened variable to be_open to reflect that it contains the
    opened state of the backend.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>
    Message-id: 1364292483-16564-2-git-send-email-hdegoede at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 47ac8c9..7c314dc 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -495,7 +495,7 @@ static int usb_serial_initfn(USBDevice *dev)
                           usb_serial_event, s);
     usb_serial_handle_reset(dev);
 
-    if (s->cs->opened && !dev->attached) {
+    if (s->cs->be_open && !dev->attached) {
         usb_device_attach(dev);
     }
     return 0;
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index c519b9b..9734e42 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -258,7 +258,7 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
 {
     USBRedirDevice *dev = priv;
 
-    if (!dev->cs->opened) {
+    if (!dev->cs->be_open) {
         return 0;
     }
 
diff --git a/include/char/char.h b/include/char/char.h
index 5c3a7a5..90443fc 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -74,7 +74,7 @@ struct CharDriverState {
     int idle_tag;
     char *label;
     char *filename;
-    int opened;
+    int be_open;
     int avail_connections;
     QemuOpts *opts;
     QTAILQ_ENTRY(CharDriverState) next;
diff --git a/qemu-char.c b/qemu-char.c
index 936150f..4419817 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -108,10 +108,10 @@ void qemu_chr_be_event(CharDriverState *s, int event)
     /* Keep track if the char device is open */
     switch (event) {
         case CHR_EVENT_OPENED:
-            s->opened = 1;
+            s->be_open = 1;
             break;
         case CHR_EVENT_CLOSED:
-            s->opened = 0;
+            s->be_open = 0;
             break;
     }
 
@@ -234,7 +234,7 @@ void qemu_chr_add_handlers(CharDriverState *s,
 
     /* We're connecting to an already opened device, so let's make sure we
        also get the open event */
-    if (s->opened) {
+    if (s->be_open) {
         qemu_chr_generic_open(s);
     }
 }
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 8a9236d..c39095b 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -100,8 +100,8 @@ static void vmc_state(SpiceCharDeviceInstance *sin, int connected)
     }
 #endif
 
-    if ((scd->chr->opened && connected) ||
-        (!scd->chr->opened && !connected)) {
+    if ((scd->chr->be_open && connected) ||
+        (!scd->chr->be_open && !connected)) {
         return;
     }
 
commit 99835e00849369bab726a4dc4ceed1f6f9ed967c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 27 14:34:32 2013 +0100

    compiler: fix warning with GCC 4.8.0
    
    GCC 4.8.0 introduces a new warning:
    
        block/qcow2-snapshot.c: In function 'qcow2_write_snapshots’:
        block/qcow2-snapshot.c:252:18: error: typedef 'qemu_build_bug_on__253'
                  locally defined but not used [-Werror=unused-local-typedefs]
             QEMU_BUILD_BUG_ON(offsetof(QCowHeader, snapshots_offset) !=
                      ^
        cc1: all warnings being treated as errors
    
    (Caret diagnostics aren't perfect yet with macros... :)) Work around it
    with __attribute__((unused)).
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1364391272-1128-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
index 2f7998b..6175c24 100644
--- a/include/qemu/compiler.h
+++ b/include/qemu/compiler.h
@@ -33,7 +33,7 @@
 #define cat(x,y) x ## y
 #define cat2(x,y) cat(x,y)
 #define QEMU_BUILD_BUG_ON(x) \
-    typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1];
+    typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1] __attribute__((unused));
 
 #if defined __GNUC__
 # if !QEMU_GNUC_PREREQ(4, 4)
commit 404e7a4f4af753bd2aef649adf79e7434fb6dc31
Merge: 18501ae 6214e73
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 26 16:16:43 2013 -0500

    Merge remote-tracking branch 'mst/tags/for_anthony' into staging
    
    virtio,pci,qom
    
    Work by Alex to support VGA assignment,
    pci and virtio fixes by Stefan, Jason and myself, and a
    new qmp event for hotplug support by myself.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    
    # gpg: Signature made Tue 26 Mar 2013 02:02:24 PM CDT using RSA key ID D28D5469
    # gpg: Can't check signature: public key not found
    
    # By Alex Williamson (13) and others
    # Via Michael S. Tsirkin
    * mst/tags/for_anthony: (23 commits)
      pcie: Add endpoint capability initialization wrapper
      roms: switch oldnoconfig to olddefconfig
      pcie: Mangle types to match topology
      pci: Create and use API to determine root buses
      pci: Create pci_bus_is_express helper
      pci: Q35, Root Ports, and Switches create PCI Express buses
      pci: Allow PCI bus creation interfaces to specify the type of bus
      pci: Move PCI and PCIE type defines
      pci: Create and register a new PCI Express TypeInfo
      exec: assert that RAMBlock size is non-zero
      pci: refuse empty ROM files
      pci_bridge: Remove duplicate IRQ swizzle function
      pci_bridge: Use a default map_irq function
      pci: Fix INTx routing notifier recursion
      pci_bridge: drop formatting from source
      pci_bridge: factor out common code
      pci: Teach PCI Bridges about VGA routing
      pci: Add PCI VGA helpers
      virtio-pci: guest notifier mask without non-irqfd
      virtio-net: remove layout assumptions for mq ctrl
      ...

diff --cc hw/spapr_pci.c
index 42c8b61,20b9015..3e0d8d1
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@@ -619,29 -621,10 +619,29 @@@ static int spapr_phb_init(SysBusDevice 
                                      &sphb->msiwindow);
      }
  
 -    bus = pci_register_bus(DEVICE(s), sphb->busname,
 +    /*
 +     * Selecting a busname is more complex than you'd think, due to
 +     * interacting constraints.  If the user has specified an id
 +     * explicitly for the phb , then we want to use the qdev default
 +     * of naming the bus based on the bridge device (so the user can
 +     * then assign devices to it in the way they expect).  For the
 +     * first / default PCI bus (index=0) we want to use just "pci"
 +     * because libvirt expects there to be a bus called, simply,
 +     * "pci".  Otherwise, we use the same name as in the device tree,
 +     * since it's unique by construction, and makes the guest visible
 +     * BUID clear.
 +     */
 +    if (s->qdev.id) {
 +        busname = NULL;
 +    } else if (sphb->index == 0) {
 +        busname = "pci";
 +    } else {
 +        busname = sphb->dtbusname;
 +    }
 +    bus = pci_register_bus(DEVICE(s), busname,
                             pci_spapr_set_irq, pci_spapr_map_irq, sphb,
                             &sphb->memspace, &sphb->iospace,
-                            PCI_DEVFN(0, 0), PCI_NUM_PINS);
+                            PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
      phb->bus = bus;
  
      sphb->dma_window_start = 0;
commit 6214e73cc5b75a4f8d89a70d71727edfa47a81b3
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Tue Mar 19 12:11:24 2013 -0600

    pcie: Add endpoint capability initialization wrapper
    
    Fix the awkward API of mangling the caller specified PCIe type and
    just provide an interface to initialize an endpoint device.  This
    will pick either a regular endpoint or integrated endpoint based on
    the bus and return pcie_cap_init to doing exactly what is asked.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index bcfbae4..62bd0b8 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -48,19 +48,6 @@ int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
 
     assert(pci_is_express(dev));
 
-    /*
-     * Mangle type to convert Endpoints to Root Complex Integrated Endpoints.
-     * Windows will report Code 10 (device cannot start) for regular Endpoints
-     * on the Root Complex.
-     */
-    if (pci_bus_is_express(dev->bus) && pci_bus_is_root(dev->bus)) {
-        switch (type) {
-        case PCI_EXP_TYPE_ENDPOINT:
-            type = PCI_EXP_TYPE_RC_END;
-            break;
-        }
-    }
-
     pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
                                  PCI_EXP_VER2_SIZEOF);
     if (pos < 0) {
@@ -100,6 +87,22 @@ int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
     return pos;
 }
 
+int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset)
+{
+    uint8_t type = PCI_EXP_TYPE_ENDPOINT;
+
+    /*
+     * Windows guests will report Code 10, device cannot start, if
+     * a regular Endpoint type is exposed on a root complex.  These
+     * should instead be Root Complex Integrated Endpoints.
+     */
+    if (pci_bus_is_express(dev->bus) && pci_bus_is_root(dev->bus)) {
+        type = PCI_EXP_TYPE_RC_END;
+    }
+
+    return pcie_cap_init(dev, offset, type, 0);
+}
+
 void pcie_cap_exit(PCIDevice *dev)
 {
     pci_del_capability(dev, PCI_CAP_ID_EXP, PCI_EXP_VER2_SIZEOF);
diff --git a/hw/pci/pcie.h b/hw/pci/pcie.h
index 31604e2..c010007 100644
--- a/hw/pci/pcie.h
+++ b/hw/pci/pcie.h
@@ -95,6 +95,7 @@ struct PCIExpressDevice {
 
 /* PCI express capability helper functions */
 int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port);
+int pcie_endpoint_cap_init(PCIDevice *dev, uint8_t offset);
 void pcie_cap_exit(PCIDevice *dev);
 uint8_t pcie_cap_get_type(const PCIDevice *dev);
 void pcie_cap_flags_set_vector(PCIDevice *dev, uint8_t vector);
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 07afdee..5aa342b 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -3332,7 +3332,7 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
                      PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64,
                      &xhci->mem);
 
-    ret = pcie_cap_init(&xhci->pci_dev, 0xa0, PCI_EXP_TYPE_ENDPOINT, 0);
+    ret = pcie_endpoint_cap_init(&xhci->pci_dev, 0xa0);
     assert(ret >= 0);
 
     if (xhci->flags & (1 << XHCI_FLAG_USE_MSI)) {
commit a5519b42cfd6c00e9f8b31c5aad7682e7a9f1181
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Thu Mar 21 14:04:21 2013 +0200

    roms: switch oldnoconfig to olddefconfig
    
    When a new option is added that qemu does not know
    about, the prudent thing is to use the default not
    force it to "no".
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/roms/configure-seabios.sh b/roms/configure-seabios.sh
index 98f59a2..4bb6c2b 100755
--- a/roms/configure-seabios.sh
+++ b/roms/configure-seabios.sh
@@ -2,4 +2,4 @@
 config="$1"
 make -C seabios clean distclean
 cp "$config" seabios/.config
-make -C seabios oldnoconfig
+make -C seabios olddefconfig
commit eb28cb1bb0cb156aef7e613395af403bba0e7f30
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:01:35 2013 -0600

    pcie: Mangle types to match topology
    
    Windows will fail to start drivers for devices with an Endpoint type
    PCIe capability attached to a Root Complex (code 10 - Device cannot
    start).  The proper type for such a device is Root Complex Integrated
    Endpoint.  Devices don't care which they are, so do this conversion
    automatically.
    
    This allows the Windows driver to load for nec-usb-xhci when attached
    to pcie.0 of a q35 machine.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 485c94c..bcfbae4 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -48,6 +48,19 @@ int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port)
 
     assert(pci_is_express(dev));
 
+    /*
+     * Mangle type to convert Endpoints to Root Complex Integrated Endpoints.
+     * Windows will report Code 10 (device cannot start) for regular Endpoints
+     * on the Root Complex.
+     */
+    if (pci_bus_is_express(dev->bus) && pci_bus_is_root(dev->bus)) {
+        switch (type) {
+        case PCI_EXP_TYPE_ENDPOINT:
+            type = PCI_EXP_TYPE_RC_END;
+            break;
+        }
+    }
+
     pos = pci_add_capability(dev, PCI_CAP_ID_EXP, offset,
                                  PCI_EXP_VER2_SIZEOF);
     if (pos < 0) {
commit 0889464a5050c25611d08ca33d8447796c88c7f7
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:01:29 2013 -0600

    pci: Create and use API to determine root buses
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 7f28101..d5257ed 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -302,6 +302,11 @@ bool pci_bus_is_express(PCIBus *bus)
     return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS);
 }
 
+bool pci_bus_is_root(PCIBus *bus)
+{
+    return !bus->parent_dev;
+}
+
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
@@ -360,7 +365,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
 
 int pci_bus_num(PCIBus *s)
 {
-    if (!s->parent_dev)
+    if (pci_bus_is_root(s))
         return 0;       /* pci host bridge */
     return s->parent_dev->config[PCI_SECONDARY_BUS];
 }
@@ -1186,7 +1191,7 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
 /* Special hooks used by device assignment */
 void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq)
 {
-    assert(!bus->parent_dev);
+    assert(pci_bus_is_root(bus));
     bus->route_intx_to_irq = route_intx_to_irq;
 }
 
@@ -1651,7 +1656,7 @@ static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num)
     }
 
     /* Consider all bus numbers in range for the host pci bridge. */
-    if (bus->parent_dev &&
+    if (!pci_bus_is_root(bus) &&
         !pci_secondary_bus_in_range(bus->parent_dev, bus_num)) {
         return NULL;
     }
@@ -1659,7 +1664,7 @@ static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num)
     /* try child bus */
     for (; bus; bus = sec) {
         QLIST_FOREACH(sec, &bus->child, sibling) {
-            assert(sec->parent_dev);
+            assert(!pci_bus_is_root(sec));
             if (sec->parent_dev->config[PCI_SECONDARY_BUS] == bus_num) {
                 return sec;
             }
diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index d715e6f..774369c 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -345,6 +345,7 @@ typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
 #define TYPE_PCIE_BUS "PCIE"
 
 bool pci_bus_is_express(PCIBus *bus);
+bool pci_bus_is_root(PCIBus *bus);
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
commit 8c0bf9e24242c89c1abbd708c714dd2a89febbd2
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:01:23 2013 -0600

    pci: Create pci_bus_is_express helper
    
    For testing the bus type.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 7c5f2e2..7f28101 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -297,6 +297,11 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent,
     vmstate_register(NULL, -1, &vmstate_pcibus, bus);
 }
 
+bool pci_bus_is_express(PCIBus *bus)
+{
+    return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS);
+}
+
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index 10aeaf0..d715e6f 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -344,6 +344,7 @@ typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
 #define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
 #define TYPE_PCIE_BUS "PCIE"
 
+bool pci_bus_is_express(PCIBus *bus);
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
commit afb661eb902f4ad1456d57b31cdd02f0b4aac33f
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:01:17 2013 -0600

    pci: Q35, Root Ports, and Switches create PCI Express buses
    
    Convert q35, ioh3420, xio3130_upstream, and xio3130_downstream to
    use the new TYPE_PCIE_BUS.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/ioh3420.c b/hw/ioh3420.c
index 74d84d4..5cff61e 100644
--- a/hw/ioh3420.c
+++ b/hw/ioh3420.c
@@ -97,7 +97,7 @@ static int ioh3420_initfn(PCIDevice *d)
     PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
     int rc;
 
-    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
+    rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
     if (rc < 0) {
         return rc;
     }
diff --git a/hw/q35.c b/hw/q35.c
index 37592bc..6ea081a 100644
--- a/hw/q35.c
+++ b/hw/q35.c
@@ -55,7 +55,7 @@ static int q35_host_init(SysBusDevice *dev)
     }
     b = pci_bus_new(&s->host.pci.busdev.qdev, "pcie.0",
                     s->mch.pci_address_space, s->mch.address_space_io,
-                    0, TYPE_PCI_BUS);
+                    0, TYPE_PCIE_BUS);
     s->host.pci.bus = b;
     qdev_set_parent_bus(DEVICE(&s->mch), BUS(b));
     qdev_init_nofail(DEVICE(&s->mch));
diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c
index a76d89b..b868f56 100644
--- a/hw/xio3130_downstream.c
+++ b/hw/xio3130_downstream.c
@@ -61,7 +61,7 @@ static int xio3130_downstream_initfn(PCIDevice *d)
     PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
     int rc;
 
-    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
+    rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
     if (rc < 0) {
         return rc;
     }
diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c
index d8fd19e..cd5d97d 100644
--- a/hw/xio3130_upstream.c
+++ b/hw/xio3130_upstream.c
@@ -57,7 +57,7 @@ static int xio3130_upstream_initfn(PCIDevice *d)
     PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
     int rc;
 
-    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
+    rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
     if (rc < 0) {
         return rc;
     }
commit 60a0e44320cc2601236450fbe95d952830192a1d
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:01:11 2013 -0600

    pci: Allow PCI bus creation interfaces to specify the type of bus
    
    No change to any types.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index 770dc8c..b1e0044 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -775,7 +775,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
 
     b = pci_register_bus(dev, "pci",
                          typhoon_set_irq, sys_map_irq, s,
-                         &s->pchip.reg_mem, addr_space_io, 0, 64);
+                         &s->pchip.reg_mem, addr_space_io, 0, 64, TYPE_PCI_BUS);
     phb->bus = b;
 
     /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 7992d6f..754ca6c 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -329,7 +329,7 @@ static int apb_pci_bridge_initfn(PCIDevice *dev)
 {
     int rc;
 
-    rc = pci_bridge_initfn(dev);
+    rc = pci_bridge_initfn(dev, TYPE_PCI_BUS);
     if (rc < 0) {
         return rc;
     }
@@ -381,7 +381,7 @@ PCIBus *pci_apb_init(hwaddr special_base,
                               pci_apb_set_irq, pci_pbm_map_irq, d,
                               &d->pci_mmio,
                               get_system_io(),
-                              0, 32);
+                              0, 32, TYPE_PCI_BUS);
 
     *pbm_irqs = d->pbm_irqs;
     d->ivec_irqs = ivec_irqs;
diff --git a/hw/bonito.c b/hw/bonito.c
index 3456e78..e58655a 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -707,7 +707,7 @@ static int bonito_pcihost_initfn(SysBusDevice *dev)
     phb->bus = pci_register_bus(DEVICE(dev), "pci",
                                 pci_bonito_set_irq, pci_bonito_map_irq, dev,
                                 get_system_memory(), get_system_io(),
-                                0x28, 32);
+                                0x28, 32, TYPE_PCI_BUS);
 
     return 0;
 }
diff --git a/hw/dec_pci.c b/hw/dec_pci.c
index 64a5092..6ec3d22 100644
--- a/hw/dec_pci.c
+++ b/hw/dec_pci.c
@@ -51,12 +51,17 @@ static int dec_map_irq(PCIDevice *pci_dev, int irq_num)
     return irq_num;
 }
 
+static int dec_pci_bridge_initfn(PCIDevice *pci_dev)
+{
+    return pci_bridge_initfn(pci_dev, TYPE_PCI_BUS);
+}
+
 static void dec_21154_pci_bridge_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 
-    k->init = pci_bridge_initfn;
+    k->init = dec_pci_bridge_initfn;
     k->exit = pci_bridge_exitfn;
     k->vendor_id = PCI_VENDOR_ID_DEC;
     k->device_id = PCI_DEVICE_ID_DEC_21154;
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 11e47d5..69344d9 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -88,7 +88,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
                                 pic,
                                 &d->pci_mmio,
                                 address_space_io,
-                                0, 4);
+                                0, 4, TYPE_PCI_BUS);
 
     pci_create_simple(phb->bus, 0, "grackle");
 
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index c73a58a..37be9c2 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -1107,7 +1107,7 @@ PCIBus *gt64120_register(qemu_irq *pic)
                                 pic,
                                 get_system_memory(),
                                 get_system_io(),
-                                PCI_DEVFN(18, 0), 4);
+                                PCI_DEVFN(18, 0), 4, TYPE_PCI_BUS);
     memory_region_init_io(&d->ISD_mem, &isd_mem_ops, d, "isd-mem", 0x1000);
 
     pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci");
diff --git a/hw/i82801b11.c b/hw/i82801b11.c
index 992095c..8b4a9c6 100644
--- a/hw/i82801b11.c
+++ b/hw/i82801b11.c
@@ -59,7 +59,7 @@ static int i82801b11_bridge_initfn(PCIDevice *d)
 {
     int rc;
 
-    rc = pci_bridge_initfn(d);
+    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
     if (rc < 0) {
         return rc;
     }
diff --git a/hw/ioh3420.c b/hw/ioh3420.c
index 43f8554..74d84d4 100644
--- a/hw/ioh3420.c
+++ b/hw/ioh3420.c
@@ -97,7 +97,7 @@ static int ioh3420_initfn(PCIDevice *d)
     PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
     int rc;
 
-    rc = pci_bridge_initfn(d);
+    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
     if (rc < 0) {
         return rc;
     }
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 74f449d..7c5f2e2 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -301,9 +301,9 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
-                         uint8_t devfn_min)
+                         uint8_t devfn_min, const char *typename)
 {
-    qbus_create_inplace(bus, TYPE_PCI_BUS, parent, name);
+    qbus_create_inplace(bus, typename, parent, name);
     pci_bus_init(bus, parent, name, address_space_mem,
                  address_space_io, devfn_min);
 }
@@ -311,11 +311,11 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
 PCIBus *pci_bus_new(DeviceState *parent, const char *name,
                     MemoryRegion *address_space_mem,
                     MemoryRegion *address_space_io,
-                    uint8_t devfn_min)
+                    uint8_t devfn_min, const char *typename)
 {
     PCIBus *bus;
 
-    bus = PCI_BUS(qbus_create(TYPE_PCI_BUS, parent, name));
+    bus = PCI_BUS(qbus_create(typename, parent, name));
     pci_bus_init(bus, parent, name, address_space_mem,
                  address_space_io, devfn_min);
     return bus;
@@ -343,12 +343,12 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
-                         uint8_t devfn_min, int nirq)
+                         uint8_t devfn_min, int nirq, const char *typename)
 {
     PCIBus *bus;
 
     bus = pci_bus_new(parent, name, address_space_mem,
-                      address_space_io, devfn_min);
+                      address_space_io, devfn_min, typename);
     pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
     return bus;
 }
diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index 37fb522..10aeaf0 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -348,11 +348,11 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
-                         uint8_t devfn_min);
+                         uint8_t devfn_min, const char *typename);
 PCIBus *pci_bus_new(DeviceState *parent, const char *name,
                     MemoryRegion *address_space_mem,
                     MemoryRegion *address_space_io,
-                    uint8_t devfn_min);
+                    uint8_t devfn_min, const char *typename);
 void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                   void *irq_opaque, int nirq);
 int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
@@ -364,7 +364,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
-                         uint8_t devfn_min, int nirq);
+                         uint8_t devfn_min, int nirq, const char *typename);
 void pci_bus_set_route_irq_fn(PCIBus *, pci_route_irq_fn);
 PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
 bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new);
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index bf93ac6..24be6c5 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -328,7 +328,7 @@ void pci_bridge_reset(DeviceState *qdev)
 }
 
 /* default qdev initialization function for PCI-to-PCI bridge */
-int pci_bridge_initfn(PCIDevice *dev)
+int pci_bridge_initfn(PCIDevice *dev, const char *typename)
 {
     PCIBus *parent = dev->bus;
     PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
@@ -363,8 +363,7 @@ int pci_bridge_initfn(PCIDevice *dev)
 	    br->bus_name = dev->qdev.id;
     }
 
-    qbus_create_inplace(&sec_bus->qbus, TYPE_PCI_BUS, &dev->qdev,
-                        br->bus_name);
+    qbus_create_inplace(&sec_bus->qbus, typename, &dev->qdev, br->bus_name);
     sec_bus->parent_dev = dev;
     sec_bus->map_irq = br->map_irq ? br->map_irq : pci_swizzle_map_irq_fn;
     sec_bus->address_space_mem = &br->address_space_mem;
diff --git a/hw/pci/pci_bridge.h b/hw/pci/pci_bridge.h
index e549b78..1868f7a 100644
--- a/hw/pci/pci_bridge.h
+++ b/hw/pci/pci_bridge.h
@@ -43,7 +43,7 @@ void pci_bridge_disable_base_limit(PCIDevice *dev);
 void pci_bridge_reset_reg(PCIDevice *dev);
 void pci_bridge_reset(DeviceState *qdev);
 
-int pci_bridge_initfn(PCIDevice *pci_dev);
+int pci_bridge_initfn(PCIDevice *pci_dev, const char *typename);
 void pci_bridge_exitfn(PCIDevice *pci_dev);
 
 
diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c
index 840ef43..971b432 100644
--- a/hw/pci_bridge_dev.c
+++ b/hw/pci_bridge_dev.c
@@ -42,7 +42,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev)
     PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
     int err;
 
-    err = pci_bridge_initfn(dev);
+    err = pci_bridge_initfn(dev, TYPE_PCI_BUS);
     if (err) {
         goto bridge_error;
     }
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index e10bc1c..ce39779 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -245,7 +245,7 @@ static PCIBus *i440fx_common_init(const char *device_name,
     dev = qdev_create(NULL, "i440FX-pcihost");
     s = PCI_HOST_BRIDGE(dev);
     b = pci_bus_new(dev, NULL, pci_address_space,
-                    address_space_io, 0);
+                    address_space_io, 0, TYPE_PCI_BUS);
     s->bus = b;
     object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
     qdev_init_nofail(dev);
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index f3bbe88..854e170 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -349,7 +349,7 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
 
     b = pci_register_bus(DEVICE(dev), NULL, ppc4xx_pci_set_irq,
                          ppc4xx_pci_map_irq, s->irq, get_system_memory(),
-                         get_system_io(), 0, 4);
+                         get_system_io(), 0, 4, TYPE_PCI_BUS);
     h->bus = b;
 
     pci_create_simple(b, 0, "ppc4xx-host-bridge");
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 310ae1c..abc7ebe 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -356,7 +356,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
 
     b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
                          mpc85xx_pci_map_irq, s->irq, address_space_mem,
-                         &s->pio, PCI_DEVFN(s->first_slot, 0), 4);
+                         &s->pio, PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS);
     h->bus = b;
 
     pci_create_simple(b, 0, "e500-host-bridge");
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index d21e876..58df245 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -154,7 +154,7 @@ static void raven_pcihost_initfn(Object *obj)
     DeviceState *pci_dev;
 
     pci_bus_new_inplace(&s->pci_bus, DEVICE(obj), NULL,
-                        address_space_mem, address_space_io, 0);
+                        address_space_mem, address_space_io, 0, TYPE_PCI_BUS);
     h->bus = &s->pci_bus;
 
     object_initialize(&s->pci_dev, TYPE_RAVEN_PCI_DEVICE);
diff --git a/hw/q35.c b/hw/q35.c
index 0a25b8b..37592bc 100644
--- a/hw/q35.c
+++ b/hw/q35.c
@@ -54,7 +54,8 @@ static int q35_host_init(SysBusDevice *dev)
         return -1;
     }
     b = pci_bus_new(&s->host.pci.busdev.qdev, "pcie.0",
-                    s->mch.pci_address_space, s->mch.address_space_io, 0);
+                    s->mch.pci_address_space, s->mch.address_space_io,
+                    0, TYPE_PCI_BUS);
     s->host.pci.bus = b;
     qdev_set_parent_bus(DEVICE(&s->mch), BUS(b));
     qdev_init_nofail(DEVICE(&s->mch));
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index 96535db..e3e7550 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -124,7 +124,7 @@ static int sh_pci_device_init(SysBusDevice *dev)
                               s->irq,
                               get_system_memory(),
                               get_system_io(),
-                              PCI_DEVFN(0, 0), 4);
+                              PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
     memory_region_init_io(&s->memconfig_p4, &sh_pci_reg_ops, s,
                           "sh_pci", 0x224);
     memory_region_init_alias(&s->memconfig_a7, "sh_pci.2", &s->memconfig_p4,
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 36adbc5..20b9015 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -624,7 +624,7 @@ static int spapr_phb_init(SysBusDevice *s)
     bus = pci_register_bus(DEVICE(s), sphb->busname,
                            pci_spapr_set_irq, pci_spapr_map_irq, sphb,
                            &sphb->memspace, &sphb->iospace,
-                           PCI_DEVFN(0, 0), PCI_NUM_PINS);
+                           PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
     phb->bus = bus;
 
     sphb->dma_window_start = 0;
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index cb95ad1..fff235d 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -239,7 +239,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic,
                               pic,
                               &d->pci_mmio,
                               address_space_io,
-                              PCI_DEVFN(11, 0), 4);
+                              PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
 
 #if 0
     pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north");
@@ -305,7 +305,7 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic,
                               pic,
                               &d->pci_mmio,
                               address_space_io,
-                              PCI_DEVFN(11, 0), 4);
+                              PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
 
     sysbus_mmio_map(s, 0, 0xf0800000);
     sysbus_mmio_map(s, 1, 0xf0c00000);
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index 0b97a40..d67ca79 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -70,7 +70,7 @@ static int pci_vpb_init(SysBusDevice *dev)
     bus = pci_register_bus(&dev->qdev, "pci",
                            pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
                            get_system_memory(), get_system_io(),
-                           PCI_DEVFN(11, 0), 4);
+                           PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
 
     /* ??? Register memory space.  */
 
diff --git a/hw/xio3130_downstream.c b/hw/xio3130_downstream.c
index 4bccd0d..a76d89b 100644
--- a/hw/xio3130_downstream.c
+++ b/hw/xio3130_downstream.c
@@ -61,7 +61,7 @@ static int xio3130_downstream_initfn(PCIDevice *d)
     PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
     int rc;
 
-    rc = pci_bridge_initfn(d);
+    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
     if (rc < 0) {
         return rc;
     }
diff --git a/hw/xio3130_upstream.c b/hw/xio3130_upstream.c
index 82556aa..d8fd19e 100644
--- a/hw/xio3130_upstream.c
+++ b/hw/xio3130_upstream.c
@@ -57,7 +57,7 @@ static int xio3130_upstream_initfn(PCIDevice *d)
     PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
     int rc;
 
-    rc = pci_bridge_initfn(d);
+    rc = pci_bridge_initfn(d, TYPE_PCI_BUS);
     if (rc < 0) {
         return rc;
     }
commit cf09458d644934976aa64e88bb41ef9a4cc2766a
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:01:05 2013 -0600

    pci: Move PCI and PCIE type defines
    
    Move these so that we can reference them from a more common header
    instead of including pci_bus.h everywhere.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index d837a65..37fb522 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -339,6 +339,11 @@ typedef enum {
 
 typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
                               PCIHotplugState state);
+
+#define TYPE_PCI_BUS "PCI"
+#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
+#define TYPE_PCIE_BUS "PCIE"
+
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
                          MemoryRegion *address_space_mem,
diff --git a/hw/pci/pci_bus.h b/hw/pci/pci_bus.h
index 6d3155f..6ee443c 100644
--- a/hw/pci/pci_bus.h
+++ b/hw/pci/pci_bus.h
@@ -8,10 +8,6 @@
  * use accessor functions in pci.h, pci_bridge.h
  */
 
-#define TYPE_PCI_BUS "PCI"
-#define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
-#define TYPE_PCIE_BUS "PCIE"
-
 struct PCIBus {
     BusState qbus;
     PCIDMAContextFunc dma_context_fn;
commit 3a861c466cee46fed042d76100fa0fd9644f3091
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 14 16:00:59 2013 -0600

    pci: Create and register a new PCI Express TypeInfo
    
    This will allow us to differentiate Express and Legacy buses.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 81028cb..74f449d 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -75,6 +75,11 @@ static const TypeInfo pci_bus_info = {
     .class_init = pci_bus_class_init,
 };
 
+static const TypeInfo pcie_bus_info = {
+    .name = TYPE_PCIE_BUS,
+    .parent = TYPE_PCI_BUS,
+};
+
 static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num);
 static void pci_update_mappings(PCIDevice *d);
 static void pci_set_irq(void *opaque, int irq_num, int level);
@@ -2236,6 +2241,7 @@ static const TypeInfo pci_device_type_info = {
 static void pci_register_types(void)
 {
     type_register_static(&pci_bus_info);
+    type_register_static(&pcie_bus_info);
     type_register_static(&pci_device_type_info);
 }
 
diff --git a/hw/pci/pci_bus.h b/hw/pci/pci_bus.h
index aef559a..6d3155f 100644
--- a/hw/pci/pci_bus.h
+++ b/hw/pci/pci_bus.h
@@ -10,6 +10,7 @@
 
 #define TYPE_PCI_BUS "PCI"
 #define PCI_BUS(obj) OBJECT_CHECK(PCIBus, (obj), TYPE_PCI_BUS)
+#define TYPE_PCIE_BUS "PCIE"
 
 struct PCIBus {
     BusState qbus;
commit 49cd9ac6a1929467e2df5783a5183fc7708ec3ff
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Mon Mar 11 10:20:21 2013 +0100

    exec: assert that RAMBlock size is non-zero
    
    find_ram_offset() does not handle size=0 gracefully.  It hands out the
    same RAMBlock offset multiple times, leading to obscure failures later
    on.
    
    Add an assert to warn early if something is incorrectly allocating a
    zero size RAMBlock.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/exec.c b/exec.c
index 8a6aac3..786987a 100644
--- a/exec.c
+++ b/exec.c
@@ -925,6 +925,8 @@ static ram_addr_t find_ram_offset(ram_addr_t size)
     RAMBlock *block, *next_block;
     ram_addr_t offset = RAM_ADDR_MAX, mingap = RAM_ADDR_MAX;
 
+    assert(size != 0); /* it would hand out same offset multiple times */
+
     if (QTAILQ_EMPTY(&ram_list.blocks))
         return 0;
 
commit 8c7f3dd05e4f1ee90000c89e428e69ae2e6bd691
Author: Stefan Hajnoczi <stefanha at redhat.com>
Date:   Mon Mar 11 10:20:20 2013 +0100

    pci: refuse empty ROM files
    
    A zero size ROM file is invalid and should produce a warning.
    Attempting to use a zero size file ends up hitting an assertion
    qemu_ram_set_idstr() because RAMBlocks with duplicate addresses are
    allocated - due to zero size the allocator doesn't increment the next
    available RAMBlock offset.
    
    Also convert __FUNCTION__ to __func__ while we're touching this code.
    There are no other __FUNCTION__ instances in pci.c anymore.
    
    Reported-by: Milos Ivanovic <milosivanovic at orcon.net.nz>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index f24c389..81028cb 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1912,7 +1912,12 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom)
     size = get_image_size(path);
     if (size < 0) {
         error_report("%s: failed to find romfile \"%s\"",
-                     __FUNCTION__, pdev->romfile);
+                     __func__, pdev->romfile);
+        g_free(path);
+        return -1;
+    } else if (size == 0) {
+        error_report("%s: ignoring empty romfile \"%s\"",
+                     __func__, pdev->romfile);
         g_free(path);
         return -1;
     }
commit ea7cfed68bb4f26fc65b078ab735a4097e9b4fe2
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 7 16:17:00 2013 -0700

    pci_bridge: Remove duplicate IRQ swizzle function
    
    pci_bridge_dev_map_irq_fn() is identical to pci_swizzle_map_irq_fn(),
    which is now the default for all PCI bridges.  We can therefore remove
    this function and the pci_bridge_map_irq() call that used it.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci_bridge_dev.c b/hw/pci_bridge_dev.c
index 9cc6a40..840ef43 100644
--- a/hw/pci_bridge_dev.c
+++ b/hw/pci_bridge_dev.c
@@ -36,21 +36,12 @@ struct PCIBridgeDev {
 };
 typedef struct PCIBridgeDev PCIBridgeDev;
 
-/* Mapping mandated by PCI-to-PCI Bridge architecture specification,
- * revision 1.2 */
-/* Table 9-1: Interrupt Binding for Devices Behind a Bridge */
-static int pci_bridge_dev_map_irq_fn(PCIDevice *dev, int irq_num)
-{
-    return (irq_num + PCI_SLOT(dev->devfn)) % PCI_NUM_PINS;
-}
-
 static int pci_bridge_dev_initfn(PCIDevice *dev)
 {
     PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
     PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
     int err;
 
-    pci_bridge_map_irq(br, NULL, pci_bridge_dev_map_irq_fn);
     err = pci_bridge_initfn(dev);
     if (err) {
         goto bridge_error;
commit 659fefeed36a4b58191595cebab2dbc003788d90
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 7 16:16:54 2013 -0700

    pci_bridge: Use a default map_irq function
    
    The PCI bridge spec defines a default swizzle for translating INTx
    IRQs from secondary bus to primary.  Use this by default for any
    bridge that doesn't set a function.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index edb8c8d..bf93ac6 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -366,7 +366,7 @@ int pci_bridge_initfn(PCIDevice *dev)
     qbus_create_inplace(&sec_bus->qbus, TYPE_PCI_BUS, &dev->qdev,
                         br->bus_name);
     sec_bus->parent_dev = dev;
-    sec_bus->map_irq = br->map_irq;
+    sec_bus->map_irq = br->map_irq ? br->map_irq : pci_swizzle_map_irq_fn;
     sec_bus->address_space_mem = &br->address_space_mem;
     memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX);
     sec_bus->address_space_io = &br->address_space_io;
commit e5368f0da75c1c668e85398aa930be2f4273e684
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Thu Mar 7 11:29:19 2013 -0700

    pci: Fix INTx routing notifier recursion
    
    For some reason we recurse to fire the INTx routing notifier for each
    child of a bus, for each possible device of a bus.  That means that if
    we add a root port, the notifier gets called for that bridge 256
    times.  If we add an upstream switch behind that root port, 256^2.  But
    of course we need a downstream switch, 256^3.  This starts to be
    noticeable.  Stop the insanity.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 8772707..f24c389 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1215,9 +1215,10 @@ void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
         if (dev && dev->intx_routing_notifier) {
             dev->intx_routing_notifier(dev);
         }
-        QLIST_FOREACH(sec, &bus->child, sibling) {
-            pci_bus_fire_intx_routing_notifier(sec);
-        }
+    }
+
+    QLIST_FOREACH(sec, &bus->child, sibling) {
+        pci_bus_fire_intx_routing_notifier(sec);
     }
 }
 
commit 600d05b9aa4b4d23775fc17968dd6b581928001d
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Mar 4 11:31:21 2013 +0200

    pci_bridge: drop formatting from source
    
    We use the same formatting for all files, it
    doesn't make sense to have formatting directives only
    in pci bridge header.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci_bridge.h b/hw/pci/pci_bridge.h
index 9d25c1b..e549b78 100644
--- a/hw/pci/pci_bridge.h
+++ b/hw/pci/pci_bridge.h
@@ -63,11 +63,3 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
 #define  PCI_BRIDGE_CTL_DISCARD_SERR	0x800	/* Discard timer SERR# enable */
 
 #endif  /* QEMU_PCI_BRIDGE_H */
-/*
- * Local variables:
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 8
- *  indent-tab-mode: nil
- * End:
- */
commit 45eb768c706d3a5fbe55224c589e8b4e252781d9
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Mar 4 11:23:49 2013 +0200

    pci_bridge: factor out common code
    
    Reuse common code in pcie_port, override the hardwired-to-0
    bits per PCI Express spec.
    No functional change but makes the code easier to follow.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index a881602..8772707 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -668,16 +668,10 @@ static void pci_init_mask_bridge(PCIDevice *d)
     pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_LIMIT,
                                PCI_PREF_RANGE_TYPE_64);
 
-/* TODO: add this define to pci_regs.h in linux and then in qemu. */
-#define  PCI_BRIDGE_CTL_VGA_16BIT	0x10	/* VGA 16-bit decode */
-#define  PCI_BRIDGE_CTL_DISCARD		0x100	/* Primary discard timer */
-#define  PCI_BRIDGE_CTL_SEC_DISCARD	0x200	/* Secondary discard timer */
-#define  PCI_BRIDGE_CTL_DISCARD_STATUS	0x400	/* Discard timer status */
-#define  PCI_BRIDGE_CTL_DISCARD_SERR	0x800	/* Discard timer SERR# enable */
-/*
- * TODO: Bridges default to 10-bit VGA decoding but we currently only
- * implement 16-bit decoding (no alias support).
- */
+    /*
+     * TODO: Bridges default to 10-bit VGA decoding but we currently only
+     * implement 16-bit decoding (no alias support).
+     */
     pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
                  PCI_BRIDGE_CTL_PARITY |
                  PCI_BRIDGE_CTL_SERR |
diff --git a/hw/pci/pci_bridge.h b/hw/pci/pci_bridge.h
index 455cb66..9d25c1b 100644
--- a/hw/pci/pci_bridge.h
+++ b/hw/pci/pci_bridge.h
@@ -55,6 +55,13 @@ void pci_bridge_exitfn(PCIDevice *pci_dev);
 void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
                         pci_map_irq_fn map_irq);
 
+/* TODO: add this define to pci_regs.h in linux and then in qemu. */
+#define  PCI_BRIDGE_CTL_VGA_16BIT	0x10	/* VGA 16-bit decode */
+#define  PCI_BRIDGE_CTL_DISCARD		0x100	/* Primary discard timer */
+#define  PCI_BRIDGE_CTL_SEC_DISCARD	0x200	/* Secondary discard timer */
+#define  PCI_BRIDGE_CTL_DISCARD_STATUS	0x400	/* Discard timer status */
+#define  PCI_BRIDGE_CTL_DISCARD_SERR	0x800	/* Discard timer SERR# enable */
+
 #endif  /* QEMU_PCI_BRIDGE_H */
 /*
  * Local variables:
diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c
index 1be107b..91b53a0 100644
--- a/hw/pci/pcie_port.c
+++ b/hw/pci/pcie_port.c
@@ -27,15 +27,17 @@ void pcie_port_init_reg(PCIDevice *d)
     pci_set_word(d->config + PCI_STATUS, 0);
     pci_set_word(d->config + PCI_SEC_STATUS, 0);
 
-    /* Unlike conventional pci bridge, some bits are hardwired to 0. */
-#define  PCI_BRIDGE_CTL_VGA_16BIT       0x10    /* VGA 16-bit decode */
-    pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
-                 PCI_BRIDGE_CTL_PARITY |
-                 PCI_BRIDGE_CTL_ISA |
-                 PCI_BRIDGE_CTL_VGA |
-                 PCI_BRIDGE_CTL_VGA_16BIT | /* Req, but no alias support yet */
-                 PCI_BRIDGE_CTL_SERR |
-                 PCI_BRIDGE_CTL_BUS_RESET);
+    /*
+     * Unlike conventional pci bridge, for some bits the spec states:
+     * Does not apply to PCI Express and must be hardwired to 0.
+     */
+    pci_word_test_and_clear_mask(d->wmask + PCI_BRIDGE_CONTROL,
+                                 PCI_BRIDGE_CTL_MASTER_ABORT |
+                                 PCI_BRIDGE_CTL_FAST_BACK |
+                                 PCI_BRIDGE_CTL_DISCARD |
+                                 PCI_BRIDGE_CTL_SEC_DISCARD |
+                                 PCI_BRIDGE_CTL_DISCARD_STATUS |
+                                 PCI_BRIDGE_CTL_DISCARD_SERR);
 }
 
 /**************************************************************************
commit ba7d8515c1e929baccea9f53d06d131fd2b007a1
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Sun Mar 3 10:21:32 2013 -0700

    pci: Teach PCI Bridges about VGA routing
    
    Each PCI Bridge has a set of implied VGA regions that are enabled when
    the VGA bit is set in the bridge control register.  This allows VGA
    devices behind bridges.  Unfortunately with VGA Enable, which we
    formerly allowed but didn't back, comes along some required VGA
    baggage.  VGA Palette Snooping is required, along with VGA 16-bit
    decoding.  We don't yet have support for palette snooping.
    We also don't have support for 10-bit VGA aliases, the default mode, but
    we enable the register, even on root ports, to avoid confusing guests.
    Fortunately there's likely nothing from this century that requires these
    features, so the missing bits are noted with TODOs.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index ed43111..a881602 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -674,6 +674,10 @@ static void pci_init_mask_bridge(PCIDevice *d)
 #define  PCI_BRIDGE_CTL_SEC_DISCARD	0x200	/* Secondary discard timer */
 #define  PCI_BRIDGE_CTL_DISCARD_STATUS	0x400	/* Discard timer status */
 #define  PCI_BRIDGE_CTL_DISCARD_SERR	0x800	/* Discard timer SERR# enable */
+/*
+ * TODO: Bridges default to 10-bit VGA decoding but we currently only
+ * implement 16-bit decoding (no alias support).
+ */
     pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
                  PCI_BRIDGE_CTL_PARITY |
                  PCI_BRIDGE_CTL_SERR |
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 995842a..edb8c8d 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -151,6 +151,28 @@ static void pci_bridge_init_alias(PCIBridge *bridge, MemoryRegion *alias,
     memory_region_add_subregion_overlap(parent_space, base, alias, 1);
 }
 
+static void pci_bridge_init_vga_aliases(PCIBridge *br, PCIBus *parent,
+                                        MemoryRegion *alias_vga)
+{
+    uint16_t brctl = pci_get_word(br->dev.config + PCI_BRIDGE_CONTROL);
+
+    memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_LO],
+                             "pci_bridge_vga_io_lo", &br->address_space_io,
+                             QEMU_PCI_VGA_IO_LO_BASE, QEMU_PCI_VGA_IO_LO_SIZE);
+    memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_HI],
+                             "pci_bridge_vga_io_hi", &br->address_space_io,
+                             QEMU_PCI_VGA_IO_HI_BASE, QEMU_PCI_VGA_IO_HI_SIZE);
+    memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_MEM],
+                             "pci_bridge_vga_mem", &br->address_space_mem,
+                             QEMU_PCI_VGA_MEM_BASE, QEMU_PCI_VGA_MEM_SIZE);
+
+    if (brctl & PCI_BRIDGE_CTL_VGA) {
+        pci_register_vga(&br->dev, &alias_vga[QEMU_PCI_VGA_MEM],
+                         &alias_vga[QEMU_PCI_VGA_IO_LO],
+                         &alias_vga[QEMU_PCI_VGA_IO_HI]);
+    }
+}
+
 static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br)
 {
     PCIBus *parent = br->dev.bus;
@@ -175,7 +197,8 @@ static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br)
                           &br->address_space_io,
                           parent->address_space_io,
                           cmd & PCI_COMMAND_IO);
-   /* TODO: optinal VGA and VGA palette snooping support. */
+
+    pci_bridge_init_vga_aliases(br, parent, w->alias_vga);
 
     return w;
 }
@@ -187,6 +210,7 @@ static void pci_bridge_region_del(PCIBridge *br, PCIBridgeWindows *w)
     memory_region_del_subregion(parent->address_space_io, &w->alias_io);
     memory_region_del_subregion(parent->address_space_mem, &w->alias_mem);
     memory_region_del_subregion(parent->address_space_mem, &w->alias_pref_mem);
+    pci_unregister_vga(&br->dev);
 }
 
 static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w)
@@ -194,6 +218,9 @@ static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w)
     memory_region_destroy(&w->alias_io);
     memory_region_destroy(&w->alias_mem);
     memory_region_destroy(&w->alias_pref_mem);
+    memory_region_destroy(&w->alias_vga[QEMU_PCI_VGA_IO_LO]);
+    memory_region_destroy(&w->alias_vga[QEMU_PCI_VGA_IO_HI]);
+    memory_region_destroy(&w->alias_vga[QEMU_PCI_VGA_MEM]);
     g_free(w);
 }
 
@@ -227,7 +254,10 @@ void pci_bridge_write_config(PCIDevice *d,
 
         /* memory base/limit, prefetchable base/limit and
            io base/limit upper 16 */
-        ranges_overlap(address, len, PCI_MEMORY_BASE, 20)) {
+        ranges_overlap(address, len, PCI_MEMORY_BASE, 20) ||
+
+        /* vga enable */
+        ranges_overlap(address, len, PCI_BRIDGE_CONTROL, 2)) {
         pci_bridge_update_mappings(s);
     }
 
@@ -306,6 +336,16 @@ int pci_bridge_initfn(PCIDevice *dev)
 
     pci_word_test_and_set_mask(dev->config + PCI_STATUS,
                                PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
+
+    /*
+     * TODO: We implement VGA Enable in the Bridge Control Register
+     * therefore per the PCI to PCI bridge spec we must also implement
+     * VGA Palette Snooping.  When done, set this bit writable:
+     *
+     * pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND,
+     *                            PCI_COMMAND_VGA_PALETTE);
+     */
+
     pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_PCI);
     dev->config[PCI_HEADER_TYPE] =
         (dev->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |
diff --git a/hw/pci/pci_bus.h b/hw/pci/pci_bus.h
index f905b9e..aef559a 100644
--- a/hw/pci/pci_bus.h
+++ b/hw/pci/pci_bus.h
@@ -47,6 +47,13 @@ struct PCIBridgeWindows {
     MemoryRegion alias_pref_mem;
     MemoryRegion alias_mem;
     MemoryRegion alias_io;
+    /*
+     * When bridge control VGA forwarding is enabled, bridges will
+     * provide positive decode on the PCI VGA defined I/O port and
+     * MMIO ranges.  When enabled forwarding is only qualified on the
+     * I/O and memory enable bits in the bridge command register.
+     */
+    MemoryRegion alias_vga[QEMU_PCI_VGA_NUM_REGIONS];
 };
 
 struct PCIBridge {
diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c
index 33a6b0a..1be107b 100644
--- a/hw/pci/pcie_port.c
+++ b/hw/pci/pcie_port.c
@@ -28,10 +28,12 @@ void pcie_port_init_reg(PCIDevice *d)
     pci_set_word(d->config + PCI_SEC_STATUS, 0);
 
     /* Unlike conventional pci bridge, some bits are hardwired to 0. */
+#define  PCI_BRIDGE_CTL_VGA_16BIT       0x10    /* VGA 16-bit decode */
     pci_set_word(d->wmask + PCI_BRIDGE_CONTROL,
                  PCI_BRIDGE_CTL_PARITY |
                  PCI_BRIDGE_CTL_ISA |
                  PCI_BRIDGE_CTL_VGA |
+                 PCI_BRIDGE_CTL_VGA_16BIT | /* Req, but no alias support yet */
                  PCI_BRIDGE_CTL_SERR |
                  PCI_BRIDGE_CTL_BUS_RESET);
 }
commit e01fd687185444944b0b5b0f8c739ae4b33eb029
Author: Alex Williamson <alex.williamson at redhat.com>
Date:   Sun Mar 3 10:21:26 2013 -0700

    pci: Add PCI VGA helpers
    
    Allow devices to register VGA memory regions for handling PCI spec
    defined VGA I/O port and MMIO areas.  PCI will attach these to the
    bus address spaces and enable them according to the device command
    register value.
    
    Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 2f45c8f..ed43111 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -875,6 +875,8 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
             continue;
         memory_region_del_subregion(r->address_space, r->memory);
     }
+
+    pci_unregister_vga(pci_dev);
 }
 
 static int pci_unregister_device(DeviceState *dev)
@@ -937,6 +939,63 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
         : pci_dev->bus->address_space_mem;
 }
 
+static void pci_update_vga(PCIDevice *pci_dev)
+{
+    uint16_t cmd;
+
+    if (!pci_dev->has_vga) {
+        return;
+    }
+
+    cmd = pci_get_word(pci_dev->config + PCI_COMMAND);
+
+    memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_MEM],
+                              cmd & PCI_COMMAND_MEMORY);
+    memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO],
+                              cmd & PCI_COMMAND_IO);
+    memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI],
+                              cmd & PCI_COMMAND_IO);
+}
+
+void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem,
+                      MemoryRegion *io_lo, MemoryRegion *io_hi)
+{
+    assert(!pci_dev->has_vga);
+
+    assert(memory_region_size(mem) == QEMU_PCI_VGA_MEM_SIZE);
+    pci_dev->vga_regions[QEMU_PCI_VGA_MEM] = mem;
+    memory_region_add_subregion_overlap(pci_dev->bus->address_space_mem,
+                                        QEMU_PCI_VGA_MEM_BASE, mem, 1);
+
+    assert(memory_region_size(io_lo) == QEMU_PCI_VGA_IO_LO_SIZE);
+    pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO] = io_lo;
+    memory_region_add_subregion_overlap(pci_dev->bus->address_space_io,
+                                        QEMU_PCI_VGA_IO_LO_BASE, io_lo, 1);
+
+    assert(memory_region_size(io_hi) == QEMU_PCI_VGA_IO_HI_SIZE);
+    pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI] = io_hi;
+    memory_region_add_subregion_overlap(pci_dev->bus->address_space_io,
+                                        QEMU_PCI_VGA_IO_HI_BASE, io_hi, 1);
+    pci_dev->has_vga = true;
+
+    pci_update_vga(pci_dev);
+}
+
+void pci_unregister_vga(PCIDevice *pci_dev)
+{
+    if (!pci_dev->has_vga) {
+        return;
+    }
+
+    memory_region_del_subregion(pci_dev->bus->address_space_mem,
+                                pci_dev->vga_regions[QEMU_PCI_VGA_MEM]);
+    memory_region_del_subregion(pci_dev->bus->address_space_io,
+                                pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO]);
+    memory_region_del_subregion(pci_dev->bus->address_space_io,
+                                pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI]);
+    pci_dev->has_vga = false;
+}
+
 pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num)
 {
     return pci_dev->io_regions[region_num].addr;
@@ -1036,6 +1095,8 @@ static void pci_update_mappings(PCIDevice *d)
                                                 r->addr, r->memory, 1);
         }
     }
+
+    pci_update_vga(d);
 }
 
 static inline int pci_irq_disabled(PCIDevice *d)
diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index f340fe5..d837a65 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -108,6 +108,20 @@ typedef struct PCIIORegion {
 #define PCI_ROM_SLOT 6
 #define PCI_NUM_REGIONS 7
 
+enum {
+    QEMU_PCI_VGA_MEM,
+    QEMU_PCI_VGA_IO_LO,
+    QEMU_PCI_VGA_IO_HI,
+    QEMU_PCI_VGA_NUM_REGIONS,
+};
+
+#define QEMU_PCI_VGA_MEM_BASE 0xa0000
+#define QEMU_PCI_VGA_MEM_SIZE 0x20000
+#define QEMU_PCI_VGA_IO_LO_BASE 0x3b0
+#define QEMU_PCI_VGA_IO_LO_SIZE 0xc
+#define QEMU_PCI_VGA_IO_HI_BASE 0x3c0
+#define QEMU_PCI_VGA_IO_HI_SIZE 0x20
+
 #include "hw/pci/pci_regs.h"
 
 /* PCI HEADER_TYPE */
@@ -234,6 +248,10 @@ struct PCIDevice {
     /* IRQ objects for the INTA-INTD pins.  */
     qemu_irq *irq;
 
+    /* Legacy PCI VGA regions */
+    MemoryRegion *vga_regions[QEMU_PCI_VGA_NUM_REGIONS];
+    bool has_vga;
+
     /* Current IRQ levels.  Used internally by the generic PCI code.  */
     uint8_t irq_state;
 
@@ -287,6 +305,9 @@ struct PCIDevice {
 
 void pci_register_bar(PCIDevice *pci_dev, int region_num,
                       uint8_t attr, MemoryRegion *memory);
+void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem,
+                      MemoryRegion *io_lo, MemoryRegion *io_hi);
+void pci_unregister_vga(PCIDevice *pci_dev);
 pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
 
 int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
commit a38b2c49bfd3f1cfc2aadd08cd049af16a342b1e
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Mar 13 21:37:08 2013 +0200

    virtio-pci: guest notifier mask without non-irqfd
    
    non-irqfd setups are currently broken with vhost:
    we start up masked and nothing unmasks the interrupts.
    Fix by using mask notifiers, same as the irqfd path.
    
    Sharing irqchip/non irqchip code is always a good thing,
    in this case it will help non irqchip benefit
    from backend masking optimization.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 39c1966..19965e5 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -609,20 +609,23 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs)
     }
 }
 
-static int kvm_virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
-                                        unsigned int queue_no,
-                                        unsigned int vector,
-                                        MSIMessage msg)
+static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
+                                       unsigned int queue_no,
+                                       unsigned int vector,
+                                       MSIMessage msg)
 {
     VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
     EventNotifier *n = virtio_queue_get_guest_notifier(vq);
-    VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
+    VirtIOIRQFD *irqfd;
     int ret = 0;
 
-    if (irqfd->msg.data != msg.data || irqfd->msg.address != msg.address) {
-        ret = kvm_irqchip_update_msi_route(kvm_state, irqfd->virq, msg);
-        if (ret < 0) {
-            return ret;
+    if (proxy->vector_irqfd) {
+        irqfd = &proxy->vector_irqfd[vector];
+        if (irqfd->msg.data != msg.data || irqfd->msg.address != msg.address) {
+            ret = kvm_irqchip_update_msi_route(kvm_state, irqfd->virq, msg);
+            if (ret < 0) {
+                return ret;
+            }
         }
     }
 
@@ -642,7 +645,7 @@ static int kvm_virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
     return ret;
 }
 
-static void kvm_virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy,
+static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy,
                                              unsigned int queue_no,
                                              unsigned int vector)
 {
@@ -656,8 +659,8 @@ static void kvm_virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy,
     }
 }
 
-static int kvm_virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
-                                     MSIMessage msg)
+static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
+                                    MSIMessage msg)
 {
     VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
     VirtIODevice *vdev = proxy->vdev;
@@ -670,7 +673,7 @@ static int kvm_virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
         if (virtio_queue_vector(vdev, queue_no) != vector) {
             continue;
         }
-        ret = kvm_virtio_pci_vq_vector_unmask(proxy, queue_no, vector, msg);
+        ret = virtio_pci_vq_vector_unmask(proxy, queue_no, vector, msg);
         if (ret < 0) {
             goto undo;
         }
@@ -682,12 +685,12 @@ undo:
         if (virtio_queue_vector(vdev, queue_no) != vector) {
             continue;
         }
-        kvm_virtio_pci_vq_vector_mask(proxy, queue_no, vector);
+        virtio_pci_vq_vector_mask(proxy, queue_no, vector);
     }
     return ret;
 }
 
-static void kvm_virtio_pci_vector_mask(PCIDevice *dev, unsigned vector)
+static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector)
 {
     VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
     VirtIODevice *vdev = proxy->vdev;
@@ -700,13 +703,13 @@ static void kvm_virtio_pci_vector_mask(PCIDevice *dev, unsigned vector)
         if (virtio_queue_vector(vdev, queue_no) != vector) {
             continue;
         }
-        kvm_virtio_pci_vq_vector_mask(proxy, queue_no, vector);
+        virtio_pci_vq_vector_mask(proxy, queue_no, vector);
     }
 }
 
-static void kvm_virtio_pci_vector_poll(PCIDevice *dev,
-                                       unsigned int vector_start,
-                                       unsigned int vector_end)
+static void virtio_pci_vector_poll(PCIDevice *dev,
+                                   unsigned int vector_start,
+                                   unsigned int vector_end)
 {
     VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
     VirtIODevice *vdev = proxy->vdev;
@@ -781,11 +784,13 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
     proxy->nvqs_with_notifiers = nvqs;
 
     /* Must unset vector notifier while guest notifier is still assigned */
-    if (proxy->vector_irqfd && !assign) {
+    if ((proxy->vector_irqfd || vdev->guest_notifier_mask) && !assign) {
         msix_unset_vector_notifiers(&proxy->pci_dev);
-        kvm_virtio_pci_vector_release(proxy, nvqs);
-        g_free(proxy->vector_irqfd);
-        proxy->vector_irqfd = NULL;
+        if (proxy->vector_irqfd) {
+            kvm_virtio_pci_vector_release(proxy, nvqs);
+            g_free(proxy->vector_irqfd);
+            proxy->vector_irqfd = NULL;
+        }
     }
 
     for (n = 0; n < nvqs; n++) {
@@ -801,18 +806,20 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
     }
 
     /* Must set vector notifier after guest notifier has been assigned */
-    if (with_irqfd && assign) {
-        proxy->vector_irqfd =
-            g_malloc0(sizeof(*proxy->vector_irqfd) *
-                      msix_nr_vectors_allocated(&proxy->pci_dev));
-        r = kvm_virtio_pci_vector_use(proxy, nvqs);
-        if (r < 0) {
-            goto assign_error;
+    if ((with_irqfd || vdev->guest_notifier_mask) && assign) {
+        if (with_irqfd) {
+            proxy->vector_irqfd =
+                g_malloc0(sizeof(*proxy->vector_irqfd) *
+                          msix_nr_vectors_allocated(&proxy->pci_dev));
+            r = kvm_virtio_pci_vector_use(proxy, nvqs);
+            if (r < 0) {
+                goto assign_error;
+            }
         }
         r = msix_set_vector_notifiers(&proxy->pci_dev,
-                                      kvm_virtio_pci_vector_unmask,
-                                      kvm_virtio_pci_vector_mask,
-                                      kvm_virtio_pci_vector_poll);
+                                      virtio_pci_vector_unmask,
+                                      virtio_pci_vector_mask,
+                                      virtio_pci_vector_poll);
         if (r < 0) {
             goto notifiers_error;
         }
@@ -821,8 +828,10 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
     return 0;
 
 notifiers_error:
-    assert(assign);
-    kvm_virtio_pci_vector_release(proxy, nvqs);
+    if (with_irqfd) {
+        assert(assign);
+        kvm_virtio_pci_vector_release(proxy, nvqs);
+    }
 
 assign_error:
     /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
commit f8f7c533e20d1681feeb665109301151bdb739b4
Author: Jason Wang <jasowang at redhat.com>
Date:   Wed Mar 6 13:50:27 2013 +0800

    virtio-net: remove layout assumptions for mq ctrl
    
    Following commit 921ac5d0f3a0df869db5ce4edf752f51d8b1596a (virtio-net:
    remove layout assumptions for ctrl vq), this patch makes multiqueue ctrl
    handling not rely on the layout of descriptors.
    
    Signed-off-by: Jason Wang <jasowang at redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 8c9d871..4590557 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -578,13 +578,14 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
 }
 
 static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
-                                VirtQueueElement *elem)
+                                struct iovec *iov, unsigned int iov_cnt)
 {
-    struct virtio_net_ctrl_mq s;
+    struct virtio_net_ctrl_mq mq;
+    size_t s;
+    uint16_t queues;
 
-    if (elem->out_num != 2 ||
-        elem->out_sg[1].iov_len != sizeof(struct virtio_net_ctrl_mq)) {
-        error_report("virtio-net ctrl invalid steering command");
+    s = iov_to_buf(iov, iov_cnt, 0, &mq, sizeof(mq));
+    if (s != sizeof(mq)) {
         return VIRTIO_NET_ERR;
     }
 
@@ -592,16 +593,16 @@ static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
         return VIRTIO_NET_ERR;
     }
 
-    memcpy(&s, elem->out_sg[1].iov_base, sizeof(struct virtio_net_ctrl_mq));
+    queues = lduw_p(&mq.virtqueue_pairs);
 
-    if (s.virtqueue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
-        s.virtqueue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX ||
-        s.virtqueue_pairs > n->max_queues ||
+    if (queues < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
+        queues > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX ||
+        queues > n->max_queues ||
         !n->multiqueue) {
         return VIRTIO_NET_ERR;
     }
 
-    n->curr_queues = s.virtqueue_pairs;
+    n->curr_queues = queues;
     /* stop the backend before changing the number of queues to avoid handling a
      * disabled queue */
     virtio_net_set_status(&n->vdev, n->vdev.status);
@@ -639,7 +640,7 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
         } else if (ctrl.class == VIRTIO_NET_CTRL_VLAN) {
             status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, iov_cnt);
         } else if (ctrl.class == VIRTIO_NET_CTRL_MQ) {
-            status = virtio_net_handle_mq(n, ctrl.cmd, &elem);
+            status = virtio_net_handle_mq(n, ctrl.cmd, iov, iov_cnt);
         }
 
         s = iov_from_buf(elem.in_sg, elem.in_num, 0, &status, sizeof(status));
commit 15054fce2df8592dec70bba23faf126f0f372f81
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Mar 11 15:11:04 2013 +0200

    qmp: add path to device_deleted event
    
    Add QOM path to device deleted event.  It now becomes useful to report
    it for devices which don't have an ID assigned.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt
index 24cf3e8..dcc826d 100644
--- a/QMP/qmp-events.txt
+++ b/QMP/qmp-events.txt
@@ -147,9 +147,11 @@ Device removal can be initiated by the guest or by HMP/QMP commands.
 Data:
 
 - "device": device name (json-string, optional)
+- "path": device path (json-string)
 
 { "event": "DEVICE_DELETED",
-  "data": { "device": "virtio-net-pci-0" },
+  "data": { "device": "virtio-net-pci-0",
+            "path": "/machine/peripheral/virtio-net-pci-0" },
   "timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
 
 DEVICE_TRAY_MOVED
diff --git a/hw/qdev.c b/hw/qdev.c
index 5e8a89c..0cdf568 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -764,6 +764,7 @@ static void device_unparent(Object *obj)
     DeviceClass *dc = DEVICE_GET_CLASS(dev);
     BusState *bus;
     QObject *event_data;
+    gchar *path = object_get_canonical_path(obj);
 
     while (dev->num_child_bus) {
         bus = QLIST_FIRST(&dev->child_bus);
@@ -784,12 +785,14 @@ static void device_unparent(Object *obj)
     }
 
     if (dev->id) {
-        event_data = qobject_from_jsonf("{ 'device': %s }", dev->id);
+        event_data = qobject_from_jsonf("{ 'device': %s, 'path': %s }",
+                                        dev->id, path);
     } else {
-        event_data = qobject_from_jsonf("{ }");
+        event_data = qobject_from_jsonf("{ 'path': %s }", path);
     }
     monitor_protocol_event(QEVENT_DEVICE_DELETED, event_data);
     qobject_decref(event_data);
+    g_free(path);
 }
 
 static void device_class_init(ObjectClass *class, void *data)
commit e998fa8df828ef68ea540a12917d10b4d335c1dd
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Mar 18 21:01:37 2013 +0200

    qom: call class destructor before unparent
    
    It seems more logical to have destruction flow start with the subclass
    and move up to the base class.  This ensures object has a valid
    canonical path when destructor is called.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/qom/object.c b/qom/object.c
index 3d638ff..a0e3cbe 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -363,12 +363,12 @@ static void object_property_del_child(Object *obj, Object *child, Error **errp)
 void object_unparent(Object *obj)
 {
     object_ref(obj);
-    if (obj->parent) {
-        object_property_del_child(obj->parent, obj, NULL);
-    }
     if (obj->class->unparent) {
         (obj->class->unparent)(obj);
     }
+    if (obj->parent) {
+        object_property_del_child(obj->parent, obj, NULL);
+    }
     object_unref(obj);
 }
 
commit 18501ae6e825d8da72369fd091018ef71071bd87
Merge: fad5593 500f006
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 26 13:38:00 2013 -0500

    Merge remote-tracking branch 'quintela/migration.next' into staging
    
    # By Peter Lieven (9) and others
    # Via Juan Quintela
    * quintela/migration.next: (22 commits)
      Use qemu_put_buffer_async for guest memory pages
      Add qemu_put_buffer_async
      Use writev ops if available
      Store the data to send also in iovec
      Update bytes_xfer in qemu_put_byte
      Add socket_writev_buffer function
      Add QemuFileWritevBuffer QemuFileOps
      migration: use XBZRLE only after bulk stage
      migration: do not search dirty pages in bulk stage
      migration: do not sent zero pages in bulk stage
      migration: add an indicator for bulk state of ram migration
      migration: search for zero instead of dup pages
      bitops: unroll while loop in find_next_bit()
      buffer_is_zero: use vector optimizations if possible
      cutils: add a function to find non-zero content in a buffer
      move vector definitions to qemu-common.h
      savevm: Fix bugs in the VMSTATE_VBUFFER_MULTIPLY definition
      savevm: Add VMSTATE_STRUCT_VARRAY_POINTER_UINT32
      savevm: Add VMSTATE_FLOAT64 helpers
      savevm: Add VMSTATE_UINTTL_EQUAL helper
      ...

commit fad5593ca646010d3cb83f7926d78dd30c20c610
Merge: 0fbf01f b57ed9b
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 26 13:34:38 2013 -0500

    Merge remote-tracking branch 'cohuck/virtio-ccw-upstr' into staging
    
    # By Cornelia Huck
    # Via Cornelia Huck
    * cohuck/virtio-ccw-upstr:
      virtio-ccw: Queue sanity check for notify hypercall.

commit b57ed9bf075e33cdd2f9eb545ff555301dd57221
Author: Cornelia Huck <cornelia.huck at de.ibm.com>
Date:   Tue Mar 26 17:32:44 2013 +0100

    virtio-ccw: Queue sanity check for notify hypercall.
    
    Verify that the virtio-ccw notify hypercall passed a reasonable
    value for queue.
    
    Cc: qemu-stable at nongnu.org
    Reported-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Cornelia Huck <cornelia.huck at de.ibm.com>

diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index d436414..76b63e2 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -31,6 +31,9 @@ static int virtio_ccw_hcall_notify(const uint64_t *args)
     if (!sch || !css_subch_visible(sch)) {
         return -EINVAL;
     }
+    if (queue >= VIRTIO_PCI_QUEUE_MAX) {
+        return -EINVAL;
+    }
     virtio_queue_notify(virtio_ccw_get_vdev(sch), queue);
     return 0;
 
commit 0fbf01fe911e84c588be41636570f46f597113d6
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 26 10:04:43 2013 -0500

    qtest: use synchronous I/O for char device
    
    Peter reported that rtc-test would periodically hang.  It turns out
    this was due to an EAGAIN occurring on qemu_chr_fe_write.
    
    Instead of heavily refactoring qtest, just use a synchronous version
    of the write operation for qemu_chr_fe_write to address this problem.
    
    Reported-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qtest.c b/qtest.c
index 5e0e9ec..b03b68a 100644
--- a/qtest.c
+++ b/qtest.c
@@ -191,7 +191,7 @@ static void GCC_FMT_ATTR(2, 3) qtest_send(CharDriverState *chr,
     len = vsnprintf(buffer, sizeof(buffer), fmt, ap);
     va_end(ap);
 
-    qemu_chr_fe_write(chr, (uint8_t *)buffer, len);
+    qemu_chr_fe_write_all(chr, (uint8_t *)buffer, len);
     if (qtest_log_fp && qtest_opened) {
         fprintf(qtest_log_fp, "%s", buffer);
     }
commit cd18720a294bd7244ffda719677dd9c737317b67
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 26 10:04:17 2013 -0500

    char: introduce a blocking version of qemu_chr_fe_write
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/char/char.h b/include/char/char.h
index 0326b2a..5c3a7a5 100644
--- a/include/char/char.h
+++ b/include/char/char.h
@@ -170,6 +170,21 @@ int qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
 int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len);
 
 /**
+ * @qemu_chr_fe_write_all:
+ *
+ * Write data to a character backend from the front end.  This function will
+ * send data from the front end to the back end.  Unlike @qemu_chr_fe_write,
+ * this function will block if the back end cannot consume all of the data
+ * attempted to be written.
+ *
+ * @buf the data
+ * @len the number of bytes to send
+ *
+ * Returns: the number of bytes consumed
+ */
+int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len);
+
+/**
  * @qemu_chr_fe_ioctl:
  *
  * Issue a device specific ioctl to a backend.
diff --git a/qemu-char.c b/qemu-char.c
index 4e011df..936150f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -140,6 +140,33 @@ int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len)
     return s->chr_write(s, buf, len);
 }
 
+int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len)
+{
+    int offset = 0;
+    int res;
+
+    while (offset < len) {
+        do {
+            res = s->chr_write(s, buf + offset, len - offset);
+            if (res == -1 && errno == EAGAIN) {
+                g_usleep(100);
+            }
+        } while (res == -1 && errno == EAGAIN);
+
+        if (res == 0) {
+            break;
+        }
+
+        if (res < 0) {
+            return res;
+        }
+
+        offset += res;
+    }
+
+    return offset;
+}
+
 int qemu_chr_fe_ioctl(CharDriverState *s, int cmd, void *arg)
 {
     if (!s->chr_ioctl)
commit e769bdc26ded6d7681cddd9f67c5f87a4b5ba53c
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 25 13:15:14 2013 +0000

    hw/qdev: Abort rather than ignoring errors adding device properties
    
    Instead of ignoring any errors that occur when adding properties
    to a new device in device_initfn(), check for them and abort if any
    occur. The most likely cause is accidentally adding a duplicate
    property, which is a programming error by the device author.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1364217314-7400-3-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev.c b/hw/qdev.c
index 04ec456..6b1947e 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -710,6 +710,7 @@ static void device_initfn(Object *obj)
     DeviceState *dev = DEVICE(obj);
     ObjectClass *class;
     Property *prop;
+    Error *err = NULL;
 
     if (qdev_hotplug) {
         dev->hotplugged = 1;
@@ -725,15 +726,18 @@ static void device_initfn(Object *obj)
     class = object_get_class(OBJECT(dev));
     do {
         for (prop = DEVICE_CLASS(class)->props; prop && prop->name; prop++) {
-            qdev_property_add_legacy(dev, prop, NULL);
-            qdev_property_add_static(dev, prop, NULL);
+            qdev_property_add_legacy(dev, prop, &err);
+            assert_no_error(err);
+            qdev_property_add_static(dev, prop, &err);
+            assert_no_error(err);
         }
         class = object_class_get_parent(class);
     } while (class != object_class_by_name(TYPE_DEVICE));
     qdev_prop_set_globals(dev);
 
     object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
-                             (Object **)&dev->parent_bus, NULL);
+                             (Object **)&dev->parent_bus, &err);
+    assert_no_error(err);
 }
 
 /* Unlink device from bus and free the structure.  */
commit 54852b03711f06c5f24af72de583346922176947
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 25 13:15:13 2013 +0000

    qom: Detect attempts to add a property that already exists
    
    Detect attempts to add a property to an object if one of
    that name already exists, and report them as errors.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Reviewed-by: Anthony Liguori <aliguori at us.ibm.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1364217314-7400-2-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qom/object.c b/qom/object.c
index 3d638ff..3f77968 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -629,7 +629,18 @@ void object_property_add(Object *obj, const char *name, const char *type,
                          ObjectPropertyRelease *release,
                          void *opaque, Error **errp)
 {
-    ObjectProperty *prop = g_malloc0(sizeof(*prop));
+    ObjectProperty *prop;
+
+    QTAILQ_FOREACH(prop, &obj->properties, node) {
+        if (strcmp(prop->name, name) == 0) {
+            error_setg(errp, "attempt to add duplicate property '%s'"
+                       " to object (type '%s')", name,
+                       object_get_typename(obj));
+            return;
+        }
+    }
+
+    prop = g_malloc0(sizeof(*prop));
 
     prop->name = g_strdup(name);
     prop->type = g_strdup(type);
commit b000dfbd42e8aac9af66ae0ed787ef1021bea29f
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Mar 25 13:40:44 2013 +0000

    hw/qdev-properties.c: Improve diagnostic for setting property after realize
    
    Now we have error_setg() we can improve the error message emitted if
    you attempt to set a property of a device after the device is realized
    (the previous message was "permission denied" which was not very
    informative).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Message-id: 1364218844-7509-1-git-send-email-peter.maydell at linaro.org
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/qdev-addr.c b/hw/qdev-addr.c
index 2398b4a..80a38bb 100644
--- a/hw/qdev-addr.c
+++ b/hw/qdev-addr.c
@@ -42,7 +42,7 @@ static void set_taddr(Object *obj, Visitor *v, void *opaque,
     int64_t value;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c
index 8795144..28813d3 100644
--- a/hw/qdev-properties-system.c
+++ b/hw/qdev-properties-system.c
@@ -43,7 +43,7 @@ static void set_pointer(Object *obj, Visitor *v, Property *prop,
     int ret;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -287,7 +287,7 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque,
     NetClientState *hubport;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 247ca6c..168c466 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -7,6 +7,20 @@
 #include "qapi/visitor.h"
 #include "char/char.h"
 
+void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
+                                  Error **errp)
+{
+    if (dev->id) {
+        error_setg(errp, "Attempt to set property '%s' on device '%s' "
+                   "(type '%s') after it was realized", name, dev->id,
+                   object_get_typename(OBJECT(dev)));
+    } else {
+        error_setg(errp, "Attempt to set property '%s' on anonymous device "
+                   "(type '%s') after it was realized", name,
+                   object_get_typename(OBJECT(dev)));
+    }
+}
+
 void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
 {
     void *ptr = dev;
@@ -33,7 +47,7 @@ static void set_enum(Object *obj, Visitor *v, void *opaque,
     int *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -86,7 +100,7 @@ static void set_bit(Object *obj, Visitor *v, void *opaque,
     bool value;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -126,7 +140,7 @@ static void set_uint8(Object *obj, Visitor *v, void *opaque,
     uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -193,7 +207,7 @@ static void set_uint16(Object *obj, Visitor *v, void *opaque,
     uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -226,7 +240,7 @@ static void set_uint32(Object *obj, Visitor *v, void *opaque,
     uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -251,7 +265,7 @@ static void set_int32(Object *obj, Visitor *v, void *opaque,
     int32_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -324,7 +338,7 @@ static void set_uint64(Object *obj, Visitor *v, void *opaque,
     uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -414,7 +428,7 @@ static void set_string(Object *obj, Visitor *v, void *opaque,
     char *str;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -478,7 +492,7 @@ static void set_mac(Object *obj, Visitor *v, void *opaque,
     char *str, *p;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -570,7 +584,7 @@ static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
     char *str;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -641,7 +655,7 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
     const int64_t max = 32768;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -709,7 +723,7 @@ static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
     unsigned int slot = 0, func = 0;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
@@ -824,7 +838,7 @@ static void set_prop_arraylen(Object *obj, Visitor *v, void *opaque,
     int i;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
     if (*alenptr) {
diff --git a/hw/qdev-properties.h b/hw/qdev-properties.h
index c9bb246..a379339 100644
--- a/hw/qdev-properties.h
+++ b/hw/qdev-properties.h
@@ -167,4 +167,16 @@ void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
  */
 void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
 
+/**
+ * @qdev_prop_set_after_realize:
+ * @dev: device
+ * @name: name of property
+ * @errp: indirect pointer to Error to be set
+ * Set the Error object to report that an attempt was made to set a property
+ * on a device after it has already been realized. This is a utility function
+ * which allows property-setter functions to easily report the error in
+ * a friendly format identifying both the device and the property.
+ */
+void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
+                                 Error **errp);
 #endif
diff --git a/hw/qdev.c b/hw/qdev.c
index 708a058..04ec456 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -562,7 +562,7 @@ static void qdev_set_legacy_property(Object *obj, Visitor *v, void *opaque,
     int ret;
 
     if (dev->realized) {
-        error_set(errp, QERR_PERMISSION_DENIED);
+        qdev_prop_set_after_realize(dev, name, errp);
         return;
     }
 
commit c19f806e01ba5c4a4d4fac80b76841512ed4a11e
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:20 2013 +0100

    virtio-scsi: cleanup: remove qdev field.
    
    The qdev field is no longer needed. Just drop it.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-11-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 96e3688..06a58a6 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -704,8 +704,6 @@ static int virtio_scsi_device_init(VirtIODevice *vdev)
 
     s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *));
 
-    s->qdev = qdev;
-
     /* TODO set up vdev function pointers */
     vdev->get_config = virtio_scsi_get_config;
     vdev->set_config = virtio_scsi_set_config;
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index fe2c7d6..31e97bb 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -39,7 +39,6 @@ struct VirtIOSCSIConf {
 
 typedef struct VirtIOSCSI {
     VirtIODevice parent_obj;
-    DeviceState *qdev;
     VirtIOSCSIConf conf;
 
     SCSIBus bus;
commit 763684befd34461371c2d2188655b69e4d93a5db
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:19 2013 +0100

    virtio-scsi: cleanup: init and exit functions.
    
    This remove old init and exit function as they are no longer needed.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-10-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index c341d24..96e3688 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -692,35 +692,19 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
     .load_request = virtio_scsi_load_request,
 };
 
-static VirtIODevice *virtio_scsi_common_init(DeviceState *dev,
-                                             VirtIOSCSIConf *proxyconf,
-                                             VirtIOSCSI **ps)
+static int virtio_scsi_device_init(VirtIODevice *vdev)
 {
-    VirtIOSCSI *s = *ps;
-    VirtIODevice *vdev = VIRTIO_DEVICE(s);
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
     static int virtio_scsi_id;
     int i;
 
-    /*
-     * We have two cases here: the old virtio-scsi-pci device, and the
-     * refactored virtio-scsi.
-     */
+    virtio_init(VIRTIO_DEVICE(s), "virtio-scsi", VIRTIO_ID_SCSI,
+                sizeof(VirtIOSCSIConfig));
 
-    if (s == NULL) {
-        /* virtio-scsi-pci */
-        s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
-                                             sizeof(VirtIOSCSIConfig),
-                                             sizeof(VirtIOSCSI));
-    } else {
-        /* virtio-scsi */
-        virtio_init(VIRTIO_DEVICE(s), "virtio-scsi", VIRTIO_ID_SCSI,
-                    sizeof(VirtIOSCSIConfig));
-    }
+    s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *));
 
-    s->cmd_vqs = g_malloc0(proxyconf->num_queues * sizeof(VirtQueue *));
-
-    s->qdev = dev;
-    s->conf = *proxyconf;
+    s->qdev = qdev;
 
     /* TODO set up vdev function pointers */
     vdev->get_config = virtio_scsi_get_config;
@@ -737,38 +721,14 @@ static VirtIODevice *virtio_scsi_common_init(DeviceState *dev,
                                          virtio_scsi_handle_cmd);
     }
 
-    scsi_bus_new(&s->bus, dev, &virtio_scsi_scsi_info);
-    if (!dev->hotplugged) {
+    scsi_bus_new(&s->bus, qdev, &virtio_scsi_scsi_info);
+    if (!qdev->hotplugged) {
         scsi_bus_legacy_handle_cmdline(&s->bus);
     }
 
-    register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
+    register_savevm(qdev, "virtio-scsi", virtio_scsi_id++, 1,
                     virtio_scsi_save, virtio_scsi_load, s);
 
-    return vdev;
-}
-
-VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
-{
-    VirtIOSCSI *s = NULL;
-    return virtio_scsi_common_init(dev, proxyconf, &s);
-}
-
-void virtio_scsi_exit(VirtIODevice *vdev)
-{
-    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
-    unregister_savevm(s->qdev, "virtio-scsi", s);
-    g_free(s->cmd_vqs);
-    virtio_cleanup(vdev);
-}
-
-static int virtio_scsi_device_init(VirtIODevice *vdev)
-{
-    DeviceState *qdev = DEVICE(vdev);
-    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
-    if (virtio_scsi_common_init(qdev, &(s->conf), &s) == NULL) {
-        return -1;
-    }
     return 0;
 }
 
commit 0ac8e139274245320b1c56f6e9ec9318c2da963a
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:18 2013 +0100

    virtio-scsi: cleanup: use QOM casts.
    
    As the virtio-scsi-pci and virtio-scsi-s390 are switched to the new API,
    we can use QOM casts.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-9-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 56d1b27..c341d24 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -172,6 +172,7 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
 {
     VirtIOSCSI *s = req->dev;
     VirtQueue *vq = req->vq;
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
     virtqueue_push(vq, &req->elem, req->qsgl.size + req->elem.in_sg[0].iov_len);
     qemu_sglist_destroy(&req->qsgl);
     if (req->sreq) {
@@ -179,7 +180,7 @@ static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
         scsi_req_unref(req->sreq);
     }
     g_free(req);
-    virtio_notify(&s->vdev, vq);
+    virtio_notify(vdev, vq);
 }
 
 static void virtio_scsi_bad_req(void)
@@ -566,16 +567,16 @@ static void virtio_scsi_reset(VirtIODevice *vdev)
  */
 static void virtio_scsi_save(QEMUFile *f, void *opaque)
 {
-    VirtIOSCSI *s = opaque;
-    virtio_save(&s->vdev, f);
+    VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
+    virtio_save(vdev, f);
 }
 
 static int virtio_scsi_load(QEMUFile *f, void *opaque, int version_id)
 {
-    VirtIOSCSI *s = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
     int ret;
 
-    ret = virtio_load(&s->vdev, f);
+    ret = virtio_load(vdev, f);
     if (ret) {
         return ret;
     }
@@ -587,9 +588,10 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
 {
     VirtIOSCSIReq *req = virtio_scsi_pop_req(s, s->event_vq);
     VirtIOSCSIEvent *evt;
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
     int in_size;
 
-    if (!(s->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
         return;
     }
 
@@ -633,7 +635,7 @@ static void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
 
 static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIOSCSI *s = (VirtIOSCSI *)vdev;
+    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
 
     if (s->events_dropped) {
         virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
@@ -643,8 +645,9 @@ static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq)
 static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
 {
     VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
-    if (((s->vdev.guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) &&
+    if (((vdev->guest_features >> VIRTIO_SCSI_F_CHANGE) & 1) &&
         dev->type != TYPE_ROM) {
         virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE,
                                sense.asc | (sense.ascq << 8));
@@ -654,8 +657,9 @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
 static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev)
 {
     VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
-    if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
+    if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
         virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET,
                                VIRTIO_SCSI_EVT_RESET_RESCAN);
     }
@@ -664,8 +668,9 @@ static void virtio_scsi_hotplug(SCSIBus *bus, SCSIDevice *dev)
 static void virtio_scsi_hot_unplug(SCSIBus *bus, SCSIDevice *dev)
 {
     VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
 
-    if ((s->vdev.guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
+    if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) {
         virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_TRANSPORT_RESET,
                                VIRTIO_SCSI_EVT_RESET_REMOVED);
     }
@@ -692,6 +697,7 @@ static VirtIODevice *virtio_scsi_common_init(DeviceState *dev,
                                              VirtIOSCSI **ps)
 {
     VirtIOSCSI *s = *ps;
+    VirtIODevice *vdev = VIRTIO_DEVICE(s);
     static int virtio_scsi_id;
     int i;
 
@@ -717,17 +723,17 @@ static VirtIODevice *virtio_scsi_common_init(DeviceState *dev,
     s->conf = *proxyconf;
 
     /* TODO set up vdev function pointers */
-    s->vdev.get_config = virtio_scsi_get_config;
-    s->vdev.set_config = virtio_scsi_set_config;
-    s->vdev.get_features = virtio_scsi_get_features;
-    s->vdev.reset = virtio_scsi_reset;
-
-    s->ctrl_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
-                                   virtio_scsi_handle_ctrl);
-    s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
+    vdev->get_config = virtio_scsi_get_config;
+    vdev->set_config = virtio_scsi_set_config;
+    vdev->get_features = virtio_scsi_get_features;
+    vdev->reset = virtio_scsi_reset;
+
+    s->ctrl_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
+                                  virtio_scsi_handle_ctrl);
+    s->event_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
                                    virtio_scsi_handle_event);
     for (i = 0; i < s->conf.num_queues; i++) {
-        s->cmd_vqs[i] = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
+        s->cmd_vqs[i] = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE,
                                          virtio_scsi_handle_cmd);
     }
 
@@ -739,7 +745,7 @@ static VirtIODevice *virtio_scsi_common_init(DeviceState *dev,
     register_savevm(dev, "virtio-scsi", virtio_scsi_id++, 1,
                     virtio_scsi_save, virtio_scsi_load, s);
 
-    return &s->vdev;
+    return vdev;
 }
 
 VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index 758c29b..fe2c7d6 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -38,7 +38,7 @@ struct VirtIOSCSIConf {
 };
 
 typedef struct VirtIOSCSI {
-    VirtIODevice vdev;
+    VirtIODevice parent_obj;
     DeviceState *qdev;
     VirtIOSCSIConf conf;
 
commit c908ea1052f8c6391c2d321693220130846f703c
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:17 2013 +0100

    virtio-scsi-ccw: switch to new API
    
    Here the virtio-scsi-ccw is modified for the new API. The device
    virtio-scsi-ccw extends virtio-ccw-device as before. It creates and
    connects a virtio-scsi during the init. The properties are not modified.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-8-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index a2f9f52..7e79c57 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -626,22 +626,24 @@ static int virtio_ccw_balloon_exit(VirtioCcwDevice *dev)
     return virtio_ccw_exit(dev);
 }
 
-static int virtio_ccw_scsi_init(VirtioCcwDevice *dev)
+static int virtio_ccw_scsi_init(VirtioCcwDevice *ccw_dev)
 {
-    VirtIODevice *vdev;
+    VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(ccw_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
 
-    vdev = virtio_scsi_init((DeviceState *)dev, &dev->scsi);
-    if (!vdev) {
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    if (qdev_init(vdev) < 0) {
         return -1;
     }
 
-    return virtio_ccw_device_init(dev, vdev);
+    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
 }
 
-static int virtio_ccw_scsi_exit(VirtioCcwDevice *dev)
+static void virtio_ccw_scsi_instance_init(Object *obj)
 {
-    virtio_scsi_exit(dev->vdev);
-    return virtio_ccw_exit(dev);
+    VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 }
 
 static int virtio_ccw_rng_init(VirtioCcwDevice *dev)
@@ -832,7 +834,7 @@ static const TypeInfo virtio_ccw_balloon = {
 
 static Property virtio_ccw_scsi_properties[] = {
     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtioCcwDevice, scsi),
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSICcw, vdev.conf),
     DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]),
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -843,15 +845,16 @@ static void virtio_ccw_scsi_class_init(ObjectClass *klass, void *data)
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
     k->init = virtio_ccw_scsi_init;
-    k->exit = virtio_ccw_scsi_exit;
+    k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = virtio_ccw_scsi_properties;
 }
 
 static const TypeInfo virtio_ccw_scsi = {
-    .name          = "virtio-scsi-ccw",
+    .name          = TYPE_VIRTIO_SCSI_CCW,
     .parent        = TYPE_VIRTIO_CCW_DEVICE,
-    .instance_size = sizeof(VirtioCcwDevice),
+    .instance_size = sizeof(VirtIOSCSICcw),
+    .instance_init = virtio_ccw_scsi_instance_init,
     .class_init    = virtio_ccw_scsi_class_init,
 };
 
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 3993bc5..d9f7399 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -76,7 +76,6 @@ struct VirtioCcwDevice {
     uint32_t host_features[VIRTIO_CCW_FEATURE_SIZE];
     virtio_serial_conf serial;
     virtio_net_conf net;
-    VirtIOSCSIConf scsi;
     VirtIORNGConf rng;
     VirtioBusState bus;
     /* Guest provided values: */
@@ -93,6 +92,17 @@ typedef struct VirtualCssBus {
 #define VIRTUAL_CSS_BUS(obj) \
      OBJECT_CHECK(VirtualCssBus, (obj), TYPE_VIRTUAL_CSS_BUS)
 
+/* virtio-scsi-ccw */
+
+#define TYPE_VIRTIO_SCSI_CCW "virtio-scsi-ccw"
+#define VIRTIO_SCSI_CCW(obj) \
+        OBJECT_CHECK(VirtIOSCSICcw, (obj), TYPE_VIRTIO_SCSI_CCW)
+
+typedef struct VirtIOSCSICcw {
+    VirtioCcwDevice parent_obj;
+    VirtIOSCSI vdev;
+} VirtIOSCSICcw;
+
 /* virtio-blk-ccw */
 
 #define TYPE_VIRTIO_BLK_CCW "virtio-blk-ccw"
commit 9ef13d8f1956b086f4bcb1d70cd5ff96e5faa2cb
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:16 2013 +0100

    virtio-scsi-s390: switch to the new API.
    
    Here the virtio-scsi-s390 is modified for the new API. The device
    virtio-scsi-s390 extends virtio-s390-device as before. It creates and
    connects a virtio-scsi during the init. The properties are not modified.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-7-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 89441f8..8c529c1 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -202,16 +202,24 @@ static int s390_virtio_serial_init(VirtIOS390Device *dev)
     return r;
 }
 
-static int s390_virtio_scsi_init(VirtIOS390Device *dev)
+static int s390_virtio_scsi_init(VirtIOS390Device *s390_dev)
 {
-    VirtIODevice *vdev;
+    VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(s390_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
 
-    vdev = virtio_scsi_init((DeviceState *)dev, &dev->scsi);
-    if (!vdev) {
+    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
+    if (qdev_init(vdev) < 0) {
         return -1;
     }
 
-    return s390_virtio_device_init(dev, vdev);
+    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
+}
+
+static void s390_virtio_scsi_instance_init(Object *obj)
+{
+    VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 }
 
 static int s390_virtio_rng_init(VirtIOS390Device *dev)
@@ -538,7 +546,7 @@ static const TypeInfo virtio_s390_device_info = {
 };
 
 static Property s390_virtio_scsi_properties[] = {
-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOS390Device, scsi),
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSIS390, vdev.conf),
     DEFINE_VIRTIO_SCSI_FEATURES(VirtIOS390Device, host_features),
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -553,9 +561,10 @@ static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo s390_virtio_scsi = {
-    .name          = "virtio-scsi-s390",
+    .name          = TYPE_VIRTIO_SCSI_S390,
     .parent        = TYPE_VIRTIO_S390_DEVICE,
-    .instance_size = sizeof(VirtIOS390Device),
+    .instance_size = sizeof(VirtIOSCSIS390),
+    .instance_init = s390_virtio_scsi_instance_init,
     .class_init    = s390_virtio_scsi_class_init,
 };
 
diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h
index 1a63411..ebe8794 100644
--- a/hw/s390x/s390-virtio-bus.h
+++ b/hw/s390x/s390-virtio-bus.h
@@ -93,7 +93,6 @@ struct VirtIOS390Device {
     uint32_t host_features;
     virtio_serial_conf serial;
     virtio_net_conf net;
-    VirtIOSCSIConf scsi;
     VirtIORNGConf rng;
     VirtioBusState bus;
 };
@@ -131,5 +130,15 @@ typedef struct VirtIOBlkS390 {
     VirtIOBlkConf blk;
 } VirtIOBlkS390;
 
+/* virtio-scsi-s390 */
+
+#define TYPE_VIRTIO_SCSI_S390 "virtio-scsi-s390"
+#define VIRTIO_SCSI_S390(obj) \
+        OBJECT_CHECK(VirtIOSCSIS390, (obj), TYPE_VIRTIO_SCSI_S390)
+
+typedef struct VirtIOSCSIS390 {
+    VirtIOS390Device parent_obj;
+    VirtIOSCSI vdev;
+} VirtIOSCSIS390;
 
 #endif
commit bc7b90a010719612344c4a78be7819841e76b7ec
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:15 2013 +0100

    virtio-scsi-pci: switch to new API.
    
    Here the virtio-scsi-pci is modified for the new API. The device virtio-scsi-pci
    extends virtio-pci. It creates and connects a virtio-scsi during the init.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-6-git-send-email-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 0cf8b2e..668060d 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -1190,64 +1190,6 @@ static const TypeInfo virtio_rng_info = {
     .class_init    = virtio_rng_class_init,
 };
 
-static int virtio_scsi_init_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-    VirtIODevice *vdev;
-
-    vdev = virtio_scsi_init(&pci_dev->qdev, &proxy->scsi);
-    if (!vdev) {
-        return -EINVAL;
-    }
-
-    vdev->nvectors = proxy->nvectors == DEV_NVECTORS_UNSPECIFIED
-                                        ? proxy->scsi.num_queues + 3
-                                        : proxy->nvectors;
-    virtio_init_pci(proxy, vdev);
-
-    /* make the actual value visible */
-    proxy->nvectors = vdev->nvectors;
-    return 0;
-}
-
-static void virtio_scsi_exit_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-
-    virtio_scsi_exit(proxy->vdev);
-    virtio_exit_pci(pci_dev);
-}
-
-static Property virtio_scsi_properties[] = {
-    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
-    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED),
-    DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features),
-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, scsi),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void virtio_scsi_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = virtio_scsi_init_pci;
-    k->exit = virtio_scsi_exit_pci;
-    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
-    k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
-    k->revision = 0x00;
-    k->class_id = PCI_CLASS_STORAGE_SCSI;
-    dc->reset = virtio_pci_reset;
-    dc->props = virtio_scsi_properties;
-}
-
-static const TypeInfo virtio_scsi_info = {
-    .name          = "virtio-scsi-pci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(VirtIOPCIProxy),
-    .class_init    = virtio_scsi_class_init,
-};
-
 #ifdef CONFIG_VIRTFS
 static int virtio_9p_init_pci(PCIDevice *pci_dev)
 {
@@ -1454,6 +1396,62 @@ static const TypeInfo virtio_blk_pci_info = {
     .class_init    = virtio_blk_pci_class_init,
 };
 
+/* virtio-scsi-pci */
+
+static Property virtio_scsi_pci_properties[] = {
+    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
+                    VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
+                       DEV_NVECTORS_UNSPECIFIED),
+    DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSIPCI, vdev.conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static int virtio_scsi_pci_init_pci(VirtIOPCIProxy *vpci_dev)
+{
+    VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
+
+    if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
+        vpci_dev->nvectors = dev->vdev.conf.num_queues + 3;
+    }
+
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    if (qdev_init(vdev) < 0) {
+        return -1;
+    }
+    return 0;
+}
+
+static void virtio_scsi_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+    k->init = virtio_scsi_pci_init_pci;
+    dc->props = virtio_scsi_pci_properties;
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
+    pcidev_k->revision = 0x00;
+    pcidev_k->class_id = PCI_CLASS_STORAGE_SCSI;
+}
+
+static void virtio_scsi_pci_instance_init(Object *obj)
+{
+    VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+}
+
+static const TypeInfo virtio_scsi_pci_info = {
+    .name          = TYPE_VIRTIO_SCSI_PCI,
+    .parent        = TYPE_VIRTIO_PCI,
+    .instance_size = sizeof(VirtIOSCSIPCI),
+    .instance_init = virtio_scsi_pci_instance_init,
+    .class_init    = virtio_scsi_pci_class_init,
+};
+
 /* virtio-pci-bus */
 
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
@@ -1495,7 +1493,6 @@ static void virtio_pci_register_types(void)
     type_register_static(&virtio_net_info);
     type_register_static(&virtio_serial_info);
     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_register_static(&virtio_pci_info);
@@ -1503,6 +1500,7 @@ static void virtio_pci_register_types(void)
     type_register_static(&virtio_9p_info);
 #endif
     type_register_static(&virtio_blk_pci_info);
+    type_register_static(&virtio_scsi_pci_info);
 }
 
 type_init(virtio_pci_register_types)
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index a9dbfff..bfe7a8e 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -26,6 +26,7 @@
 
 typedef struct VirtIOPCIProxy VirtIOPCIProxy;
 typedef struct VirtIOBlkPCI VirtIOBlkPCI;
+typedef struct VirtIOSCSIPCI VirtIOSCSIPCI;
 
 /* virtio-pci-bus */
 
@@ -81,7 +82,6 @@ struct VirtIOPCIProxy {
 #endif
     virtio_serial_conf serial;
     virtio_net_conf net;
-    VirtIOSCSIConf scsi;
     VirtIORNGConf rng;
     bool ioeventfd_disabled;
     bool ioeventfd_started;
@@ -90,6 +90,19 @@ struct VirtIOPCIProxy {
     VirtioBusState bus;
 };
 
+
+/*
+ * virtio-scsi-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_SCSI_PCI "virtio-scsi-pci"
+#define VIRTIO_SCSI_PCI(obj) \
+        OBJECT_CHECK(VirtIOSCSIPCI, (obj), TYPE_VIRTIO_SCSI_PCI)
+
+struct VirtIOSCSIPCI {
+    VirtIOPCIProxy parent_obj;
+    VirtIOSCSI vdev;
+};
+
 /*
  * virtio-blk-pci: This extends VirtioPCIProxy.
  */
commit 3ab1dfdd50a7c852e4921935250c22f486c5b8a4
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:14 2013 +0100

    virtio-scsi: add the virtio-scsi device.
    
    Create virtio-scsi which extends virtio-device, so it can be connected on
    virtio-bus.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-5-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 08fcb80..56d1b27 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -17,6 +17,7 @@
 #include "qemu/error-report.h"
 #include <hw/scsi.h>
 #include <hw/scsi-defs.h>
+#include "hw/virtio-bus.h"
 
 #define VIRTIO_SCSI_VQ_SIZE     128
 #define VIRTIO_SCSI_CDB_SIZE    32
@@ -686,15 +687,30 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
     .load_request = virtio_scsi_load_request,
 };
 
-VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
+static VirtIODevice *virtio_scsi_common_init(DeviceState *dev,
+                                             VirtIOSCSIConf *proxyconf,
+                                             VirtIOSCSI **ps)
 {
-    VirtIOSCSI *s;
+    VirtIOSCSI *s = *ps;
     static int virtio_scsi_id;
     int i;
 
-    s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
-                                         sizeof(VirtIOSCSIConfig),
-                                         sizeof(VirtIOSCSI));
+    /*
+     * We have two cases here: the old virtio-scsi-pci device, and the
+     * refactored virtio-scsi.
+     */
+
+    if (s == NULL) {
+        /* virtio-scsi-pci */
+        s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
+                                             sizeof(VirtIOSCSIConfig),
+                                             sizeof(VirtIOSCSI));
+    } else {
+        /* virtio-scsi */
+        virtio_init(VIRTIO_DEVICE(s), "virtio-scsi", VIRTIO_ID_SCSI,
+                    sizeof(VirtIOSCSIConfig));
+    }
+
     s->cmd_vqs = g_malloc0(proxyconf->num_queues * sizeof(VirtQueue *));
 
     s->qdev = dev;
@@ -726,6 +742,12 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
     return &s->vdev;
 }
 
+VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
+{
+    VirtIOSCSI *s = NULL;
+    return virtio_scsi_common_init(dev, proxyconf, &s);
+}
+
 void virtio_scsi_exit(VirtIODevice *vdev)
 {
     VirtIOSCSI *s = (VirtIOSCSI *)vdev;
@@ -733,3 +755,56 @@ void virtio_scsi_exit(VirtIODevice *vdev)
     g_free(s->cmd_vqs);
     virtio_cleanup(vdev);
 }
+
+static int virtio_scsi_device_init(VirtIODevice *vdev)
+{
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIOSCSI *s = VIRTIO_SCSI(vdev);
+    if (virtio_scsi_common_init(qdev, &(s->conf), &s) == NULL) {
+        return -1;
+    }
+    return 0;
+}
+
+static int virtio_scsi_device_exit(DeviceState *qdev)
+{
+    VirtIOSCSI *s = VIRTIO_SCSI(qdev);
+    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+
+    unregister_savevm(qdev, "virtio-scsi", s);
+    g_free(s->cmd_vqs);
+    virtio_common_cleanup(vdev);
+    return 0;
+}
+
+static Property virtio_scsi_properties[] = {
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSI, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_scsi_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    dc->exit = virtio_scsi_device_exit;
+    dc->props = virtio_scsi_properties;
+    vdc->init = virtio_scsi_device_init;
+    vdc->get_config = virtio_scsi_get_config;
+    vdc->set_config = virtio_scsi_set_config;
+    vdc->get_features = virtio_scsi_get_features;
+    vdc->reset = virtio_scsi_reset;
+}
+
+static const TypeInfo virtio_scsi_info = {
+    .name = TYPE_VIRTIO_SCSI,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VirtIOSCSI),
+    .class_init = virtio_scsi_class_init,
+};
+
+static void virtio_register_types(void)
+{
+    type_register_static(&virtio_scsi_info);
+}
+
+type_init(virtio_register_types)
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index da02f08..758c29b 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -18,6 +18,11 @@
 #include "hw/pci/pci.h"
 #include "hw/scsi.h"
 
+#define TYPE_VIRTIO_SCSI "virtio-scsi"
+#define VIRTIO_SCSI(obj) \
+        OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI)
+
+
 /* The ID for virtio_scsi */
 #define VIRTIO_ID_SCSI  8
 
commit 4bfeb18a454bd71c406683fb473375e02c724b00
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:13 2013 +0100

    virtio-scsi: moving host_features from properties to transport properties.
    
    host_features field is part of the transport device. So move all the
    host_features related properties into transport device.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-4-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index c5d5456..89441f8 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -538,7 +538,8 @@ static const TypeInfo virtio_s390_device_info = {
 };
 
 static Property s390_virtio_scsi_properties[] = {
-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOS390Device, host_features, scsi),
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOS390Device, scsi),
+    DEFINE_VIRTIO_SCSI_FEATURES(VirtIOS390Device, host_features),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 4c44b7e..a2f9f52 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -832,7 +832,8 @@ static const TypeInfo virtio_ccw_balloon = {
 
 static Property virtio_ccw_scsi_properties[] = {
     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtioCcwDevice, host_features[0], scsi),
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtioCcwDevice, scsi),
+    DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index f3ece78..0cf8b2e 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -1221,7 +1221,8 @@ static void virtio_scsi_exit_pci(PCIDevice *pci_dev)
 static Property virtio_scsi_properties[] = {
     DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, DEV_NVECTORS_UNSPECIFIED),
-    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, host_features, scsi),
+    DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOPCIProxy, scsi),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index fb83b67..da02f08 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -47,12 +47,16 @@ typedef struct VirtIOSCSI {
     VirtQueue **cmd_vqs;
 } VirtIOSCSI;
 
-#define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _features_field, _conf_field) \
-    DEFINE_VIRTIO_COMMON_FEATURES(_state, _features_field), \
-    DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \
-    DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF), \
-    DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128), \
-    DEFINE_PROP_BIT("hotplug", _state, _features_field, VIRTIO_SCSI_F_HOTPLUG, true), \
-    DEFINE_PROP_BIT("param_change", _state, _features_field, VIRTIO_SCSI_F_CHANGE, true)
+#define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _conf_field)                     \
+    DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1),       \
+    DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF),\
+    DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128)
+
+#define DEFINE_VIRTIO_SCSI_FEATURES(_state, _feature_field)                    \
+    DEFINE_VIRTIO_COMMON_FEATURES(_state, _feature_field),                     \
+    DEFINE_PROP_BIT("hotplug", _state, _feature_field, VIRTIO_SCSI_F_HOTPLUG,  \
+                                                       true),                  \
+    DEFINE_PROP_BIT("param_change", _state, _feature_field,                    \
+                                            VIRTIO_SCSI_F_CHANGE, true)
 
 #endif /* _QEMU_VIRTIO_SCSI_H */
commit 22219527f4272f5199a581bbd3950e9ba96bbc75
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:12 2013 +0100

    virtio-scsi: allocate cmd_vqs array separately.
    
    Allocate/Free the cmd_vqs array separately to have a fixed size device.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-3-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 55191c5..08fcb80 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -690,12 +690,12 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
 {
     VirtIOSCSI *s;
     static int virtio_scsi_id;
-    size_t sz;
     int i;
 
-    sz = sizeof(VirtIOSCSI) + proxyconf->num_queues * sizeof(VirtQueue *);
     s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
-                                         sizeof(VirtIOSCSIConfig), sz);
+                                         sizeof(VirtIOSCSIConfig),
+                                         sizeof(VirtIOSCSI));
+    s->cmd_vqs = g_malloc0(proxyconf->num_queues * sizeof(VirtQueue *));
 
     s->qdev = dev;
     s->conf = *proxyconf;
@@ -730,5 +730,6 @@ void virtio_scsi_exit(VirtIODevice *vdev)
 {
     VirtIOSCSI *s = (VirtIOSCSI *)vdev;
     unregister_savevm(s->qdev, "virtio-scsi", s);
+    g_free(s->cmd_vqs);
     virtio_cleanup(vdev);
 }
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index 6a0a95e..fb83b67 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -44,7 +44,7 @@ typedef struct VirtIOSCSI {
     bool events_dropped;
     VirtQueue *ctrl_vq;
     VirtQueue *event_vq;
-    VirtQueue *cmd_vqs[0];
+    VirtQueue **cmd_vqs;
 } VirtIOSCSI;
 
 #define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _features_field, _conf_field) \
commit 394e2e4c59294f2c5da58d2970693667218c7cf3
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Mar 21 15:15:11 2013 +0100

    virtio-scsi: don't use pointer for configuration.
    
    The configuration field must not be a pointer as it will be used for virtio-scsi
    properties. So *conf is replaced by conf.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1363875320-7985-2-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio-scsi.c b/hw/virtio-scsi.c
index 8620712..55191c5 100644
--- a/hw/virtio-scsi.c
+++ b/hw/virtio-scsi.c
@@ -237,7 +237,7 @@ static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
     VirtIOSCSIReq *req = sreq->hba_private;
     uint32_t n = virtio_queue_get_id(req->vq) - 2;
 
-    assert(n < req->dev->conf->num_queues);
+    assert(n < req->dev->conf.num_queues);
     qemu_put_be32s(f, &n);
     qemu_put_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
 }
@@ -251,7 +251,7 @@ static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
 
     req = g_malloc(sizeof(*req));
     qemu_get_be32s(f, &n);
-    assert(n < s->conf->num_queues);
+    assert(n < s->conf.num_queues);
     qemu_get_buffer(f, (unsigned char *)&req->elem, sizeof(req->elem));
     virtio_scsi_parse_req(s, s->cmd_vqs[n], req);
 
@@ -513,10 +513,10 @@ static void virtio_scsi_get_config(VirtIODevice *vdev,
     VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
     VirtIOSCSI *s = (VirtIOSCSI *)vdev;
 
-    stl_raw(&scsiconf->num_queues, s->conf->num_queues);
+    stl_raw(&scsiconf->num_queues, s->conf.num_queues);
     stl_raw(&scsiconf->seg_max, 128 - 2);
-    stl_raw(&scsiconf->max_sectors, s->conf->max_sectors);
-    stl_raw(&scsiconf->cmd_per_lun, s->conf->cmd_per_lun);
+    stl_raw(&scsiconf->max_sectors, s->conf.max_sectors);
+    stl_raw(&scsiconf->cmd_per_lun, s->conf.cmd_per_lun);
     stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
     stl_raw(&scsiconf->sense_size, s->sense_size);
     stl_raw(&scsiconf->cdb_size, s->cdb_size);
@@ -698,7 +698,7 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
                                          sizeof(VirtIOSCSIConfig), sz);
 
     s->qdev = dev;
-    s->conf = proxyconf;
+    s->conf = *proxyconf;
 
     /* TODO set up vdev function pointers */
     s->vdev.get_config = virtio_scsi_get_config;
@@ -710,7 +710,7 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf)
                                    virtio_scsi_handle_ctrl);
     s->event_vq = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
                                    virtio_scsi_handle_event);
-    for (i = 0; i < s->conf->num_queues; i++) {
+    for (i = 0; i < s->conf.num_queues; i++) {
         s->cmd_vqs[i] = virtio_add_queue(&s->vdev, VIRTIO_SCSI_VQ_SIZE,
                                          virtio_scsi_handle_cmd);
     }
diff --git a/hw/virtio-scsi.h b/hw/virtio-scsi.h
index ccf1e42..6a0a95e 100644
--- a/hw/virtio-scsi.h
+++ b/hw/virtio-scsi.h
@@ -35,7 +35,7 @@ struct VirtIOSCSIConf {
 typedef struct VirtIOSCSI {
     VirtIODevice vdev;
     DeviceState *qdev;
-    VirtIOSCSIConf *conf;
+    VirtIOSCSIConf conf;
 
     SCSIBus bus;
     uint32_t sense_size;
commit 2fd1a053e3696738d7499733df0feb1efd0d97e0
Merge: dcadaa9 4d70043
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Mar 26 09:25:45 2013 -0500

    Merge remote-tracking branch 'luiz/queue/qmp' into staging
    
    # By Corey Bryant (2) and others
    # Via Luiz Capitulino
    * luiz/queue/qmp:
      New QMP command query-cpu-max and HMP command cpu_max
      qmp: fix handling of boolean values in qmp-shell
      QMP: TPM QMP and man page documentation updates
      QMP: Remove duplicate TPM type from query-tpm

commit 500f0061d628b52220038939728f0d7aee634468
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:48:03 2013 +0200

    Use qemu_put_buffer_async for guest memory pages
    
    This will remove an unneeded copy of guest memory pages.
    For the page header and device state we still copy the data to the
    static buffer the other option is to allocate the memory on demand
    which is more expensive.
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index e1af898..4ef5a15 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -478,7 +478,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
             /* XBZRLE overflow or normal page */
             if (bytes_sent == -1) {
                 bytes_sent = save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE);
-                qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
+                qemu_put_buffer_async(f, p, TARGET_PAGE_SIZE);
                 bytes_sent += TARGET_PAGE_SIZE;
                 acct_info.norm_pages++;
             }
commit 6181ec245529e0d40ac669fe3044eef3a9e19610
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:48:02 2013 +0200

    Add qemu_put_buffer_async
    
    This allows us to add a buffer to the iovec to send without copying it
    into the static buffer, the buffer will be sent later when qemu_fflush is called.
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index 8b8070f..623c434 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -75,6 +75,11 @@ int qemu_fclose(QEMUFile *f);
 int64_t qemu_ftell(QEMUFile *f);
 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
 void qemu_put_byte(QEMUFile *f, int v);
+/*
+ * put_buffer without copying the buffer.
+ * The buffer should be available till it is sent asynchronously.
+ */
+void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, int size);
 
 static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v)
 {
diff --git a/savevm.c b/savevm.c
index 1d92987..406caa9 100644
--- a/savevm.c
+++ b/savevm.c
@@ -633,6 +633,28 @@ static void add_to_iovec(QEMUFile *f, const uint8_t *buf, int size)
     }
 }
 
+void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, int size)
+{
+    if (f->last_error) {
+        return;
+    }
+
+    if (f->is_write == 0 && f->buf_index > 0) {
+        fprintf(stderr,
+                "Attempted to write to buffer while read buffer is not empty\n");
+        abort();
+    }
+
+    add_to_iovec(f, buf, size);
+
+    f->is_write = 1;
+    f->bytes_xfer += size;
+
+    if (f->buf_index >= IO_BUF_SIZE || f->iovcnt >= MAX_IOV_SIZE) {
+        qemu_fflush(f);
+    }
+}
+
 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
 {
     int l;
@@ -652,18 +674,14 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
         if (l > size)
             l = size;
         memcpy(f->buf + f->buf_index, buf, l);
-        add_to_iovec(f, f->buf + f->buf_index, l);
         f->is_write = 1;
         f->buf_index += l;
-        f->bytes_xfer += l;
+        qemu_put_buffer_async(f, f->buf + (f->buf_index - l), l);
+        if (qemu_file_get_error(f)) {
+            break;
+        }
         buf += l;
         size -= l;
-        if (f->buf_index >= IO_BUF_SIZE || f->iovcnt >= MAX_IOV_SIZE) {
-            qemu_fflush(f);
-            if (qemu_file_get_error(f)) {
-                break;
-            }
-        }
     }
 }
 
commit cb88aa88d7e96cd12328915b33bf4a1bc054aa3f
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:48:01 2013 +0200

    Use writev ops if available
    
    Update qemu_fflush and stdio_close to use writev ops if they are available
    Use the buffers stored in the iovec.
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index aaaf39a..1d92987 100644
--- a/savevm.c
+++ b/savevm.c
@@ -293,7 +293,7 @@ static int stdio_fclose(void *opaque)
     QEMUFileStdio *s = opaque;
     int ret = 0;
 
-    if (s->file->ops->put_buffer) {
+    if (s->file->ops->put_buffer || s->file->ops->writev_buffer) {
         int fd = fileno(s->stdio_file);
         struct stat st;
 
@@ -516,20 +516,35 @@ static void qemu_file_set_error(QEMUFile *f, int ret)
     }
 }
 
-/** Flushes QEMUFile buffer
+/**
+ * Flushes QEMUFile buffer
  *
+ * If there is writev_buffer QEMUFileOps it uses it otherwise uses
+ * put_buffer ops.
  */
 static void qemu_fflush(QEMUFile *f)
 {
-    int ret = 0;
+    ssize_t ret = 0;
+    int i = 0;
 
-    if (!f->ops->put_buffer) {
+    if (!f->ops->writev_buffer && !f->ops->put_buffer) {
         return;
     }
-    if (f->is_write && f->buf_index > 0) {
-        ret = f->ops->put_buffer(f->opaque, f->buf, f->pos, f->buf_index);
-        if (ret >= 0) {
-            f->pos += f->buf_index;
+
+    if (f->is_write && f->iovcnt > 0) {
+        if (f->ops->writev_buffer) {
+            ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt);
+            if (ret >= 0) {
+                f->pos += ret;
+            }
+        } else {
+            for (i = 0; i < f->iovcnt && ret >= 0; i++) {
+                ret = f->ops->put_buffer(f->opaque, f->iov[i].iov_base, f->pos,
+                                         f->iov[i].iov_len);
+                if (ret >= 0) {
+                    f->pos += ret;
+                }
+            }
         }
         f->buf_index = 0;
         f->iovcnt = 0;
commit b3ea2bdb792f6d961ba3adf45cf1f0c63c61e09d
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:48:00 2013 +0200

    Store the data to send also in iovec
    
    All data is still copied into the static buffer.
    Adjacent iovecs are coalesced so we send one big buffer
    instead of many small buffers.
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 5ab256c..aaaf39a 100644
--- a/savevm.c
+++ b/savevm.c
@@ -114,6 +114,7 @@ void qemu_announce_self(void)
 /* savevm/loadvm support */
 
 #define IO_BUF_SIZE 32768
+#define MAX_IOV_SIZE MIN(IOV_MAX, 64)
 
 struct QEMUFile {
     const QEMUFileOps *ops;
@@ -129,6 +130,9 @@ struct QEMUFile {
     int buf_size; /* 0 when writing */
     uint8_t buf[IO_BUF_SIZE];
 
+    struct iovec iov[MAX_IOV_SIZE];
+    unsigned int iovcnt;
+
     int last_error;
 };
 
@@ -528,6 +532,7 @@ static void qemu_fflush(QEMUFile *f)
             f->pos += f->buf_index;
         }
         f->buf_index = 0;
+        f->iovcnt = 0;
     }
     if (ret < 0) {
         qemu_file_set_error(f, ret);
@@ -601,6 +606,18 @@ int qemu_fclose(QEMUFile *f)
     return ret;
 }
 
+static void add_to_iovec(QEMUFile *f, const uint8_t *buf, int size)
+{
+    /* check for adjacent buffer and coalesce them */
+    if (f->iovcnt > 0 && buf == f->iov[f->iovcnt - 1].iov_base +
+        f->iov[f->iovcnt - 1].iov_len) {
+        f->iov[f->iovcnt - 1].iov_len += size;
+    } else {
+        f->iov[f->iovcnt].iov_base = (uint8_t *)buf;
+        f->iov[f->iovcnt++].iov_len = size;
+    }
+}
+
 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
 {
     int l;
@@ -620,12 +637,13 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
         if (l > size)
             l = size;
         memcpy(f->buf + f->buf_index, buf, l);
+        add_to_iovec(f, f->buf + f->buf_index, l);
         f->is_write = 1;
         f->buf_index += l;
         f->bytes_xfer += l;
         buf += l;
         size -= l;
-        if (f->buf_index >= IO_BUF_SIZE) {
+        if (f->buf_index >= IO_BUF_SIZE || f->iovcnt >= MAX_IOV_SIZE) {
             qemu_fflush(f);
             if (qemu_file_get_error(f)) {
                 break;
@@ -650,7 +668,9 @@ void qemu_put_byte(QEMUFile *f, int v)
     f->is_write = 1;
     f->bytes_xfer++;
 
-    if (f->buf_index >= IO_BUF_SIZE) {
+    add_to_iovec(f, f->buf + (f->buf_index - 1), 1);
+
+    if (f->buf_index >= IO_BUF_SIZE || f->iovcnt >= MAX_IOV_SIZE) {
         qemu_fflush(f);
     }
 }
commit 7d8a30bb98e89c203b3d2289ab0638c38bbeb7c1
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:47:59 2013 +0200

    Update bytes_xfer in qemu_put_byte
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 3466ef4..5ab256c 100644
--- a/savevm.c
+++ b/savevm.c
@@ -648,6 +648,8 @@ void qemu_put_byte(QEMUFile *f, int v)
 
     f->buf[f->buf_index++] = v;
     f->is_write = 1;
+    f->bytes_xfer++;
+
     if (f->buf_index >= IO_BUF_SIZE) {
         qemu_fflush(f);
     }
commit 28085f7b4d06970efa004257fcef013caf495a08
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:47:58 2013 +0200

    Add socket_writev_buffer function
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/savevm.c b/savevm.c
index 8f1344a..3466ef4 100644
--- a/savevm.c
+++ b/savevm.c
@@ -39,6 +39,7 @@
 #include "qmp-commands.h"
 #include "trace.h"
 #include "qemu/bitops.h"
+#include "qemu/iov.h"
 
 #define SELF_ANNOUNCE_ROUNDS 5
 
@@ -171,6 +172,19 @@ static void coroutine_fn yield_until_fd_readable(int fd)
     qemu_coroutine_yield();
 }
 
+static ssize_t socket_writev_buffer(void *opaque, struct iovec *iov, int iovcnt)
+{
+    QEMUFileSocket *s = opaque;
+    ssize_t len;
+    ssize_t size = iov_size(iov, iovcnt);
+
+    len = iov_send(s->fd, iov, iovcnt, 0, size);
+    if (len < size) {
+        len = -socket_error();
+    }
+    return len;
+}
+
 static int socket_get_fd(void *opaque)
 {
     QEMUFileSocket *s = opaque;
@@ -387,6 +401,7 @@ static const QEMUFileOps socket_read_ops = {
 static const QEMUFileOps socket_write_ops = {
     .get_fd =     socket_get_fd,
     .put_buffer = socket_put_buffer,
+    .writev_buffer = socket_writev_buffer,
     .close =      socket_close
 };
 
commit d913829f0fd8451abcb1fd9d6dfce5586d9d7e10
Author: Orit Wasserman <owasserm at redhat.com>
Date:   Fri Mar 22 16:47:57 2013 +0200

    Add QemuFileWritevBuffer QemuFileOps
    
    This will allow us to write an iovec
    
    Signed-off-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h
index df81261..8b8070f 100644
--- a/include/migration/qemu-file.h
+++ b/include/migration/qemu-file.h
@@ -51,11 +51,18 @@ typedef int (QEMUFileCloseFunc)(void *opaque);
  */
 typedef int (QEMUFileGetFD)(void *opaque);
 
+/*
+ * This function writes an iovec to file.
+ */
+typedef ssize_t (QEMUFileWritevBufferFunc)(void *opaque, struct iovec *iov,
+                                           int iovcnt);
+
 typedef struct QEMUFileOps {
     QEMUFilePutBufferFunc *put_buffer;
     QEMUFileGetBufferFunc *get_buffer;
     QEMUFileCloseFunc *close;
     QEMUFileGetFD *get_fd;
+    QEMUFileWritevBufferFunc *writev_buffer;
 } QEMUFileOps;
 
 QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops);
commit 5cc11c46cf187c7d5306b68e730ec0d372cd7ef0
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:39 2013 +0100

    migration: use XBZRLE only after bulk stage
    
    at the beginning of migration all pages are marked dirty and
    in the first round a bulk migration of all pages is performed.
    
    currently all these pages are copied to the page cache regardless
    of whether they are frequently updated or not. this doesn't make sense
    since most of these pages are never transferred again.
    
    this patch changes the XBZRLE transfer to only be used after
    the bulk stage has been completed. that means a page is added
    to the page cache the second time it is transferred and XBZRLE
    can benefit from the third time of transfer.
    
    since the page cache is likely smaller than the number of pages
    it's also likely that in the second round the page is missing in the
    cache due to collisions in the bulk phase.
    
    on the other hand a lot of unnecessary mallocs, memdups and frees
    are saved.
    
    the following results have been taken earlier while executing
    the test program from docs/xbzrle.txt. (+) with the patch and (-)
    without. (thanks to Eric Blake for reformatting and comments)
    
    + total time: 22185 milliseconds
    - total time: 22410 milliseconds
    
    Shaved 0.3 seconds, better than 1%!
    
    + downtime: 29 milliseconds
    - downtime: 21 milliseconds
    
    Not sure why downtime seemed worse, but probably not the end of the world.
    
    + transferred ram: 706034 kbytes
    - transferred ram: 721318 kbytes
    
    Fewer bytes sent - good.
    
    + remaining ram: 0 kbytes
    - remaining ram: 0 kbytes
    + total ram: 1057216 kbytes
    - total ram: 1057216 kbytes
    + duplicate: 108556 pages
    - duplicate: 105553 pages
    + normal: 175146 pages
    - normal: 179589 pages
    + normal bytes: 700584 kbytes
    - normal bytes: 718356 kbytes
    
    Fewer normal bytes...
    
    + cache size: 67108864 bytes
    - cache size: 67108864 bytes
    + xbzrle transferred: 3127 kbytes
    - xbzrle transferred: 630 kbytes
    
    ...and more compressed pages sent - good.
    
    + xbzrle pages: 117811 pages
    - xbzrle pages: 21527 pages
    + xbzrle cache miss: 18750
    - xbzrle cache miss: 179589
    
    And very good improvement on the cache miss rate.
    
    + xbzrle overflow : 0
    - xbzrle overflow : 0
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index a522735..e1af898 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -466,7 +466,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
                     acct_info.skipped_pages++;
                     bytes_sent = 0;
                 }
-            } else if (migrate_use_xbzrle()) {
+            } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
                 current_addr = block->offset + offset;
                 bytes_sent = save_xbzrle_page(f, p, current_addr, block,
                                               offset, cont, last_stage);
commit 70c8652bf3c1fea79b7b68864e86926715c49261
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:38 2013 +0100

    migration: do not search dirty pages in bulk stage
    
    avoid searching for dirty pages just increment the
    page offset. all pages are dirty anyway.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 3a0d02e..a522735 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -340,7 +340,13 @@ ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
     unsigned long nr = base + (start >> TARGET_PAGE_BITS);
     unsigned long size = base + (int128_get64(mr->size) >> TARGET_PAGE_BITS);
 
-    unsigned long next = find_next_bit(migration_bitmap, size, nr);
+    unsigned long next;
+
+    if (ram_bulk_stage && nr > base) {
+        next = nr + 1;
+    } else {
+        next = find_next_bit(migration_bitmap, size, nr);
+    }
 
     if (next < size) {
         clear_bit(next, migration_bitmap);
commit f1c72795af573b24a7da5eb52375c9aba8a37972
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:37 2013 +0100

    migration: do not sent zero pages in bulk stage
    
    during bulk stage of ram migration if a page is a
    zero page do not send it at all.
    the memory at the destination reads as zero anyway.
    
    even if there is an madvise with QEMU_MADV_DONTNEED
    at the target upon receipt of a zero page I have observed
    that the target starts swapping if the memory is overcommitted.
    it seems that the pages are dropped asynchronously.
    
    this patch also updates QMP to return the number of
    skipped pages in MigrationStats.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 1291bd2..3a0d02e 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -183,6 +183,7 @@ int64_t xbzrle_cache_resize(int64_t new_size)
 /* accounting for migration statistics */
 typedef struct AccountingInfo {
     uint64_t dup_pages;
+    uint64_t skipped_pages;
     uint64_t norm_pages;
     uint64_t iterations;
     uint64_t xbzrle_bytes;
@@ -208,6 +209,16 @@ uint64_t dup_mig_pages_transferred(void)
     return acct_info.dup_pages;
 }
 
+uint64_t skipped_mig_bytes_transferred(void)
+{
+    return acct_info.skipped_pages * TARGET_PAGE_SIZE;
+}
+
+uint64_t skipped_mig_pages_transferred(void)
+{
+    return acct_info.skipped_pages;
+}
+
 uint64_t norm_mig_bytes_transferred(void)
 {
     return acct_info.norm_pages * TARGET_PAGE_SIZE;
@@ -440,10 +451,15 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
             bytes_sent = -1;
             if (is_zero_page(p)) {
                 acct_info.dup_pages++;
-                bytes_sent = save_block_hdr(f, block, offset, cont,
-                                            RAM_SAVE_FLAG_COMPRESS);
-                qemu_put_byte(f, 0);
-                bytes_sent++;
+                if (!ram_bulk_stage) {
+                    bytes_sent = save_block_hdr(f, block, offset, cont,
+                                                RAM_SAVE_FLAG_COMPRESS);
+                    qemu_put_byte(f, 0);
+                    bytes_sent++;
+                } else {
+                    acct_info.skipped_pages++;
+                    bytes_sent = 0;
+                }
             } else if (migrate_use_xbzrle()) {
                 current_addr = block->offset + offset;
                 bytes_sent = save_xbzrle_page(f, p, current_addr, block,
diff --git a/hmp.c b/hmp.c
index b0a861c..e3e833e 100644
--- a/hmp.c
+++ b/hmp.c
@@ -173,6 +173,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
                        info->ram->total >> 10);
         monitor_printf(mon, "duplicate: %" PRIu64 " pages\n",
                        info->ram->duplicate);
+        monitor_printf(mon, "skipped: %" PRIu64 " pages\n",
+                       info->ram->skipped);
         monitor_printf(mon, "normal: %" PRIu64 " pages\n",
                        info->ram->normal);
         monitor_printf(mon, "normal bytes: %" PRIu64 " kbytes\n",
diff --git a/include/migration/migration.h b/include/migration/migration.h
index bb617fd..e2acec6 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -96,6 +96,8 @@ extern SaveVMHandlers savevm_ram_handlers;
 
 uint64_t dup_mig_bytes_transferred(void);
 uint64_t dup_mig_pages_transferred(void);
+uint64_t skipped_mig_bytes_transferred(void);
+uint64_t skipped_mig_pages_transferred(void);
 uint64_t norm_mig_bytes_transferred(void);
 uint64_t norm_mig_pages_transferred(void);
 uint64_t xbzrle_mig_bytes_transferred(void);
diff --git a/migration.c b/migration.c
index 185d112..7fb2147 100644
--- a/migration.c
+++ b/migration.c
@@ -197,11 +197,11 @@ MigrationInfo *qmp_query_migrate(Error **errp)
         info->ram->remaining = ram_bytes_remaining();
         info->ram->total = ram_bytes_total();
         info->ram->duplicate = dup_mig_pages_transferred();
+        info->ram->skipped = skipped_mig_pages_transferred();
         info->ram->normal = norm_mig_pages_transferred();
         info->ram->normal_bytes = norm_mig_bytes_transferred();
         info->ram->dirty_pages_rate = s->dirty_pages_rate;
 
-
         if (blk_mig_active()) {
             info->has_disk = true;
             info->disk = g_malloc0(sizeof(*info->disk));
@@ -227,6 +227,7 @@ MigrationInfo *qmp_query_migrate(Error **errp)
         info->ram->remaining = 0;
         info->ram->total = ram_bytes_total();
         info->ram->duplicate = dup_mig_pages_transferred();
+        info->ram->skipped = skipped_mig_pages_transferred();
         info->ram->normal = norm_mig_pages_transferred();
         info->ram->normal_bytes = norm_mig_bytes_transferred();
         break;
diff --git a/qapi-schema.json b/qapi-schema.json
index 088f4e1..6c4966b 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -496,7 +496,9 @@
 #
 # @total: total amount of bytes involved in the migration process
 #
-# @duplicate: number of duplicate pages (since 1.2)
+# @duplicate: number of duplicate (zero) pages (since 1.2)
+#
+# @skipped: number of skipped zero pages (since 1.5)
 #
 # @normal : number of normal pages (since 1.2)
 #
@@ -509,8 +511,8 @@
 ##
 { 'type': 'MigrationStats',
   'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,
-           'duplicate': 'int', 'normal': 'int', 'normal-bytes': 'int',
-           'dirty-pages-rate' : 'int' } }
+           'duplicate': 'int', 'skipped': 'int', 'normal': 'int',
+           'normal-bytes': 'int', 'dirty-pages-rate' : 'int' } }
 
 ##
 # @XBZRLECacheStats
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5e847b1..fdc4048 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2445,6 +2445,7 @@ The main json-object contains the following:
          - "duplicate": number of pages filled entirely with the same
             byte (json-int)
             These are sent over the wire much more efficiently.
+         - "skipped": number of skipped zero pages (json-int)
          - "normal" : number of whole pages transfered.  I.e. they
             were not sent as duplicate or xbzrle pages (json-int)
          - "normal-bytes" : number of bytes transferred in whole
commit 78d07ae7ac74bcc7f79aeefbaff17fb142f44b4d
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:36 2013 +0100

    migration: add an indicator for bulk state of ram migration
    
    the first round of ram transfer is special since all pages
    are dirty and thus all memory pages are transferred to
    the target. this patch adds a boolean variable to track
    this stage.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index dd5deff..1291bd2 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -319,6 +319,7 @@ static ram_addr_t last_offset;
 static unsigned long *migration_bitmap;
 static uint64_t migration_dirty_pages;
 static uint32_t last_version;
+static bool ram_bulk_stage;
 
 static inline
 ram_addr_t migration_bitmap_find_and_reset_dirty(MemoryRegion *mr,
@@ -426,6 +427,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
             if (!block) {
                 block = QTAILQ_FIRST(&ram_list.blocks);
                 complete_round = true;
+                ram_bulk_stage = false;
             }
         } else {
             uint8_t *p;
@@ -529,6 +531,7 @@ static void reset_ram_globals(void)
     last_sent_block = NULL;
     last_offset = 0;
     last_version = ram_list.version;
+    ram_bulk_stage = true;
 }
 
 #define MAX_WAIT 50 /* ms, half buffered_file limit */
commit 3edcd7e6ebae3ef0ac178eed5f4225803159562d
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:35 2013 +0100

    migration: search for zero instead of dup pages
    
    virtually all dup pages are zero pages. remove
    the special is_dup_page() function and use the
    optimized buffer_find_nonzero_offset() function
    instead.
    
    here buffer_find_nonzero_offset() is used directly
    to avoid the unnecssary additional checks in
    buffer_is_zero().
    
    raw performace gain checking 1 GByte zeroed memory
    over is_dup_page() is approx. 10-12% with SSE2
    and 8-10% with unsigned long arithmedtic.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index 35974c2..dd5deff 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -146,19 +146,10 @@ int qemu_read_default_config_files(bool userconfig)
     return 0;
 }
 
-static int is_dup_page(uint8_t *page)
+static inline bool is_zero_page(uint8_t *p)
 {
-    VECTYPE *p = (VECTYPE *)page;
-    VECTYPE val = SPLAT(page);
-    int i;
-
-    for (i = 0; i < TARGET_PAGE_SIZE / sizeof(VECTYPE); i++) {
-        if (!ALL_EQ(val, p[i])) {
-            return 0;
-        }
-    }
-
-    return 1;
+    return buffer_find_nonzero_offset(p, TARGET_PAGE_SIZE) ==
+        TARGET_PAGE_SIZE;
 }
 
 /* struct contains XBZRLE cache and a static page
@@ -445,12 +436,12 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
 
             /* In doubt sent page as normal */
             bytes_sent = -1;
-            if (is_dup_page(p)) {
+            if (is_zero_page(p)) {
                 acct_info.dup_pages++;
                 bytes_sent = save_block_hdr(f, block, offset, cont,
                                             RAM_SAVE_FLAG_COMPRESS);
-                qemu_put_byte(f, *p);
-                bytes_sent += 1;
+                qemu_put_byte(f, 0);
+                bytes_sent++;
             } else if (migrate_use_xbzrle()) {
                 current_addr = block->offset + offset;
                 bytes_sent = save_xbzrle_page(f, p, current_addr, block,
commit 49f676a00ab540fac1d2008be26434cf85607722
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:34 2013 +0100

    bitops: unroll while loop in find_next_bit()
    
    this patch adopts the loop unrolling idea of bitmap_is_zero() to
    speed up the skipping of large areas with zeros in find_next_bit().
    
    this routine is extensively used to find dirty pages in
    live migration.
    
    testing only the find_next_bit performance on a zeroed bitfield
    the loop onrolling decreased executing time by approx. 50% on x86_64.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/util/bitops.c b/util/bitops.c
index e72237a..227c38b 100644
--- a/util/bitops.c
+++ b/util/bitops.c
@@ -42,7 +42,23 @@ unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
         size -= BITS_PER_LONG;
         result += BITS_PER_LONG;
     }
-    while (size & ~(BITS_PER_LONG-1)) {
+    while (size >= 4*BITS_PER_LONG) {
+        unsigned long d1, d2, d3;
+        tmp = *p;
+        d1 = *(p+1);
+        d2 = *(p+2);
+        d3 = *(p+3);
+        if (tmp) {
+            goto found_middle;
+        }
+        if (d1 | d2 | d3) {
+            break;
+        }
+        p += 4;
+        result += 4*BITS_PER_LONG;
+        size -= 4*BITS_PER_LONG;
+    }
+    while (size >= BITS_PER_LONG) {
         if ((tmp = *(p++))) {
             goto found_middle;
         }
commit 56ded708ec38e4cb75a7c7357480ca34c0dc6875
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:33 2013 +0100

    buffer_is_zero: use vector optimizations if possible
    
    performance gain on SSE2 is approx. 20-25%. altivec
    is not tested. performance for unsigned long arithmetic
    is unchanged.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Orit Wasserman <owasserm at redhat.com>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/util/cutils.c b/util/cutils.c
index 0696a3b..5024253 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -215,6 +215,11 @@ bool buffer_is_zero(const void *buf, size_t len)
     long d0, d1, d2, d3;
     const long * const data = buf;
 
+    /* use vector optimized zero check if possible */
+    if (can_use_buffer_find_nonzero_offset(buf, len)) {
+        return buffer_find_nonzero_offset(buf, len) == len;
+    }
+
     assert(len % (4 * sizeof(long)) == 0);
     len /= sizeof(long);
 
commit 41a259bd2b1796ddabdae600ee539269a7ddb6a5
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:32 2013 +0100

    cutils: add a function to find non-zero content in a buffer
    
    this adds buffer_find_nonzero_offset() which is a SSE2/Altivec
    optimized function that searches for non-zero content in a
    buffer.
    
    the function starts full unrolling only after the first few chunks have
    been checked one by one. analyzing real memory page data has revealed
    that non-zero pages are non-zero within the first 256-512 bits in
    most cases. as this function is also heavily used to check for zero memory
    pages this tweak has been made to avoid the high setup costs of the fully
    unrolled check for non-zero pages.
    
    due to the optimizations used in the function there are restrictions
    on buffer address and search length. the function
    can_use_buffer_find_nonzero_content() can be used to check if
    the function can be used safely.
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/qemu-common.h b/include/qemu-common.h
index d7ad3a7..31fff22 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -469,4 +469,14 @@ void hexdump(const char *buf, FILE *fp, const char *prefix, size_t size);
 #define ALL_EQ(v1, v2) ((v1) == (v2))
 #endif
 
+#define BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR 8
+static inline bool
+can_use_buffer_find_nonzero_offset(const void *buf, size_t len)
+{
+    return (len % (BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR
+                   * sizeof(VECTYPE)) == 0
+            && ((uintptr_t) buf) % sizeof(VECTYPE) == 0);
+}
+size_t buffer_find_nonzero_offset(const void *buf, size_t len);
+
 #endif
diff --git a/util/cutils.c b/util/cutils.c
index 1439da4..0696a3b 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -143,6 +143,61 @@ int qemu_fdatasync(int fd)
 }
 
 /*
+ * Searches for an area with non-zero content in a buffer
+ *
+ * Attention! The len must be a multiple of
+ * BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR * sizeof(VECTYPE)
+ * and addr must be a multiple of sizeof(VECTYPE) due to
+ * restriction of optimizations in this function.
+ *
+ * can_use_buffer_find_nonzero_offset() can be used to check
+ * these requirements.
+ *
+ * The return value is the offset of the non-zero area rounded
+ * down to a multiple of sizeof(VECTYPE) for the first
+ * BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR chunks and down to
+ * BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR * sizeof(VECTYPE)
+ * afterwards.
+ *
+ * If the buffer is all zero the return value is equal to len.
+ */
+
+size_t buffer_find_nonzero_offset(const void *buf, size_t len)
+{
+    const VECTYPE *p = buf;
+    const VECTYPE zero = (VECTYPE){0};
+    size_t i;
+
+    assert(can_use_buffer_find_nonzero_offset(buf, len));
+
+    if (!len) {
+        return 0;
+    }
+
+    for (i = 0; i < BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR; i++) {
+        if (!ALL_EQ(p[i], zero)) {
+            return i * sizeof(VECTYPE);
+        }
+    }
+
+    for (i = BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR;
+         i < len / sizeof(VECTYPE);
+         i += BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR) {
+        VECTYPE tmp0 = p[i + 0] | p[i + 1];
+        VECTYPE tmp1 = p[i + 2] | p[i + 3];
+        VECTYPE tmp2 = p[i + 4] | p[i + 5];
+        VECTYPE tmp3 = p[i + 6] | p[i + 7];
+        VECTYPE tmp01 = tmp0 | tmp1;
+        VECTYPE tmp23 = tmp2 | tmp3;
+        if (!ALL_EQ(tmp01 | tmp23, zero)) {
+            break;
+        }
+    }
+
+    return i * sizeof(VECTYPE);
+}
+
+/*
  * Checks if a buffer is all zeroes
  *
  * Attention! The len must be a multiple of 4 * sizeof(long) due to
commit c61ca00ada744eb24825be2ba4d6ba8fe3a870a4
Author: Peter Lieven <pl at kamp.de>
Date:   Tue Mar 26 10:58:30 2013 +0100

    move vector definitions to qemu-common.h
    
    vector optimizations will now be used at various places
    not just in is_dup_page() in arch_init.c
    
    Signed-off-by: Peter Lieven <pl at kamp.de>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/arch_init.c b/arch_init.c
index e8ade9e..35974c2 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -116,26 +116,6 @@ const uint32_t arch_type = QEMU_ARCH;
 #define RAM_SAVE_FLAG_CONTINUE 0x20
 #define RAM_SAVE_FLAG_XBZRLE   0x40
 
-#ifdef __ALTIVEC__
-#include <altivec.h>
-#define VECTYPE        vector unsigned char
-#define SPLAT(p)       vec_splat(vec_ld(0, p), 0)
-#define ALL_EQ(v1, v2) vec_all_eq(v1, v2)
-/* altivec.h may redefine the bool macro as vector type.
- * Reset it to POSIX semantics. */
-#undef bool
-#define bool _Bool
-#elif defined __SSE2__
-#include <emmintrin.h>
-#define VECTYPE        __m128i
-#define SPLAT(p)       _mm_set1_epi8(*(p))
-#define ALL_EQ(v1, v2) (_mm_movemask_epi8(_mm_cmpeq_epi8(v1, v2)) == 0xFFFF)
-#else
-#define VECTYPE        unsigned long
-#define SPLAT(p)       (*(p) * (~0UL / 255))
-#define ALL_EQ(v1, v2) ((v1) == (v2))
-#endif
-
 
 static struct defconfig_file {
     const char *filename;
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 2371132..d7ad3a7 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -448,4 +448,25 @@ int uleb128_decode_small(const uint8_t *in, uint32_t *n);
 
 void hexdump(const char *buf, FILE *fp, const char *prefix, size_t size);
 
+/* vector definitions */
+#ifdef __ALTIVEC__
+#include <altivec.h>
+#define VECTYPE        vector unsigned char
+#define SPLAT(p)       vec_splat(vec_ld(0, p), 0)
+#define ALL_EQ(v1, v2) vec_all_eq(v1, v2)
+/* altivec.h may redefine the bool macro as vector type.
+ * Reset it to POSIX semantics. */
+#undef bool
+#define bool _Bool
+#elif defined __SSE2__
+#include <emmintrin.h>
+#define VECTYPE        __m128i
+#define SPLAT(p)       _mm_set1_epi8(*(p))
+#define ALL_EQ(v1, v2) (_mm_movemask_epi8(_mm_cmpeq_epi8(v1, v2)) == 0xFFFF)
+#else
+#define VECTYPE        unsigned long
+#define SPLAT(p)       (*(p) * (~0UL / 255))
+#define ALL_EQ(v1, v2) ((v1) == (v2))
+#endif
+
 #endif
commit 377e2cb96b76c2b0023c1acc7230bf3a9e9f9f40
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 14:06:04 2013 +1100

    savevm: Fix bugs in the VMSTATE_VBUFFER_MULTIPLY definition
    
    The VMSTATE_BUFFER_MULTIPLY macro is misnamed - it actually specifies
    a variably sized buffer with VMS_VBUFFER, so should be named
    VMSTATE_VBUFFER_MULTIPLY.  This patch fixes this (the macro had no current
    users under either name).
    
    In addition, unlike the other VMSTATE_VBUFFER variants, this macro did not
    specify VMS_POINTER.  This patch fixes this bug as well.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index d8af9f2..65918a9 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -393,14 +393,14 @@ extern const VMStateInfo vmstate_info_bitmap;
     .offset       = vmstate_offset_buffer(_state, _field) + _start,  \
 }
 
-#define VMSTATE_BUFFER_MULTIPLY(_field, _state, _version, _test, _start, _field_size, _multiply) { \
+#define VMSTATE_VBUFFER_MULTIPLY(_field, _state, _version, _test, _start, _field_size, _multiply) { \
     .name         = (stringify(_field)),                             \
     .version_id   = (_version),                                      \
     .field_exists = (_test),                                         \
     .size_offset  = vmstate_offset_value(_state, _field_size, uint32_t),\
     .size         = (_multiply),                                      \
     .info         = &vmstate_info_buffer,                            \
-    .flags        = VMS_VBUFFER|VMS_MULTIPLY,                        \
+    .flags        = VMS_VBUFFER|VMS_POINTER|VMS_MULTIPLY,            \
     .offset       = offsetof(_state, _field),                        \
     .start        = (_start),                                        \
 }
commit 8474a9dd6757be064bf4b35f422b4640d1cca0a5
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 14:06:03 2013 +1100

    savevm: Add VMSTATE_STRUCT_VARRAY_POINTER_UINT32
    
    Currently the savevm code contains a VMSTATE_STRUCT_VARRAY_POINTER_INT32
    helper (a variably sized array with the number of elements in an int32_t),
    but not VMSTATE_STRUCT_VARRAY_POINTER_UINT32 (... with the number of
    elements in a uint32_t).  This patch (trivially) fixes the deficiency.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 5c31ff1..d8af9f2 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -343,6 +343,16 @@ extern const VMStateInfo vmstate_info_bitmap;
     .offset     = vmstate_offset_pointer(_state, _field, _type),     \
 }
 
+#define VMSTATE_STRUCT_VARRAY_POINTER_UINT32(_field, _state, _field_num, _vmsd, _type) { \
+    .name       = (stringify(_field)),                               \
+    .version_id = 0,                                                 \
+    .num_offset = vmstate_offset_value(_state, _field_num, uint32_t),\
+    .size       = sizeof(_type),                                     \
+    .vmsd       = &(_vmsd),                                          \
+    .flags      = VMS_POINTER | VMS_VARRAY_INT32 | VMS_STRUCT,       \
+    .offset     = vmstate_offset_pointer(_state, _field, _type),     \
+}
+
 #define VMSTATE_STRUCT_VARRAY_POINTER_UINT16(_field, _state, _field_num, _vmsd, _type) { \
     .name       = (stringify(_field)),                               \
     .version_id = 0,                                                 \
commit 213945e4d753b5f214468ff746d65fa76e21dbd1
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 14:06:02 2013 +1100

    savevm: Add VMSTATE_FLOAT64 helpers
    
    The current savevm code includes VMSTATE helpers for a number of commonly
    used data types, but not for the float64 type used by the internal floating
    point emulation code.  This patch fixes the deficiency.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 294d455..5c31ff1 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -157,6 +157,8 @@ extern const VMStateInfo vmstate_info_uint16;
 extern const VMStateInfo vmstate_info_uint32;
 extern const VMStateInfo vmstate_info_uint64;
 
+extern const VMStateInfo vmstate_info_float64;
+
 extern const VMStateInfo vmstate_info_timer;
 extern const VMStateInfo vmstate_info_buffer;
 extern const VMStateInfo vmstate_info_unused_buffer;
@@ -543,6 +545,13 @@ extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_UINT32_TEST(_f, _s, _t)                                  \
     VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_info_uint32, uint32_t)
 
+
+#define VMSTATE_FLOAT64_V(_f, _s, _v)                                 \
+    VMSTATE_SINGLE(_f, _s, _v, vmstate_info_float64, float64)
+
+#define VMSTATE_FLOAT64(_f, _s)                                       \
+    VMSTATE_FLOAT64_V(_f, _s, 0)
+
 #define VMSTATE_TIMER_TEST(_f, _s, _test)                             \
     VMSTATE_POINTER_TEST(_f, _s, _test, vmstate_info_timer, QEMUTimer *)
 
@@ -609,6 +618,12 @@ extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_INT64_ARRAY(_f, _s, _n)                               \
     VMSTATE_INT64_ARRAY_V(_f, _s, _n, 0)
 
+#define VMSTATE_FLOAT64_ARRAY_V(_f, _s, _n, _v)                       \
+    VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_float64, float64)
+
+#define VMSTATE_FLOAT64_ARRAY(_f, _s, _n)                             \
+    VMSTATE_FLOAT64_ARRAY_V(_f, _s, _n, 0)
+
 #define VMSTATE_BUFFER_V(_f, _s, _v)                                  \
     VMSTATE_STATIC_BUFFER(_f, _s, _v, NULL, 0, sizeof(typeof_field(_s, _f)))
 
diff --git a/savevm.c b/savevm.c
index cd98b0d..8f1344a 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1133,6 +1133,29 @@ const VMStateInfo vmstate_info_uint16_equal = {
     .put  = put_uint16,
 };
 
+/* floating point */
+
+static int get_float64(QEMUFile *f, void *pv, size_t size)
+{
+    float64 *v = pv;
+
+    *v = make_float64(qemu_get_be64(f));
+    return 0;
+}
+
+static void put_float64(QEMUFile *f, void *pv, size_t size)
+{
+    uint64_t *v = pv;
+
+    qemu_put_be64(f, float64_val(*v));
+}
+
+const VMStateInfo vmstate_info_float64 = {
+    .name = "float64",
+    .get  = get_float64,
+    .put  = put_float64,
+};
+
 /* timers  */
 
 static int get_timer(QEMUFile *f, void *pv, size_t size)
commit d58f5598342ffebe6c6278d8b90792060fca4792
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 14:06:01 2013 +1100

    savevm: Add VMSTATE_UINTTL_EQUAL helper
    
    This adds an _EQUAL VMSTATE helper for target_ulongs, defined in terms of
    VMSTATE_UINT32_EQUAL or VMSTATE_UINT64_EQUAL as appropriate.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/hw/hw.h b/hw/hw.h
index 1553e54..1fb9afa 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -52,16 +52,22 @@ int qemu_boot_set(const char *boot_devices);
 #if TARGET_LONG_BITS == 64
 #define VMSTATE_UINTTL_V(_f, _s, _v)                                  \
     VMSTATE_UINT64_V(_f, _s, _v)
+#define VMSTATE_UINTTL_EQUAL_V(_f, _s, _v)                            \
+    VMSTATE_UINT64_EQUAL_V(_f, _s, _v)
 #define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v)                        \
     VMSTATE_UINT64_ARRAY_V(_f, _s, _n, _v)
 #else
 #define VMSTATE_UINTTL_V(_f, _s, _v)                                  \
     VMSTATE_UINT32_V(_f, _s, _v)
+#define VMSTATE_UINTTL_EQUAL_V(_f, _s, _v)                            \
+    VMSTATE_UINT32_EQUAL_V(_f, _s, _v)
 #define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v)                        \
     VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v)
 #endif
 #define VMSTATE_UINTTL(_f, _s)                                        \
     VMSTATE_UINTTL_V(_f, _s, 0)
+#define VMSTATE_UINTTL_EQUAL(_f, _s)                                  \
+    VMSTATE_UINTTL_EQUAL_V(_f, _s, 0)
 #define VMSTATE_UINTTL_ARRAY(_f, _s, _n)                              \
     VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, 0)
 
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index f12ad79..294d455 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -519,8 +519,11 @@ extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_INT32_EQUAL(_f, _s)                                   \
     VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_equal, int32_t)
 
-#define VMSTATE_UINT32_EQUAL(_f, _s)                                   \
-    VMSTATE_SINGLE(_f, _s, 0, vmstate_info_uint32_equal, uint32_t)
+#define VMSTATE_UINT32_EQUAL_V(_f, _s, _v)                            \
+    VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint32_equal, uint32_t)
+
+#define VMSTATE_UINT32_EQUAL(_f, _s)                                  \
+    VMSTATE_UINT32_EQUAL_V(_f, _s, 0)
 
 #define VMSTATE_UINT64_EQUAL_V(_f, _s, _v)                            \
     VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64_equal, uint64_t)
commit e344b8a16de429ada3d9126f26e2a96d71348356
Author: David Gibson <david at gibson.dropbear.id.au>
Date:   Tue Mar 12 14:06:00 2013 +1100

    savevm: Add VMSTATE_UINT64_EQUAL helpers
    
    The savevm code already includes a number of *_EQUAL helpers which act as
    sanity checks verifying that the configuration of the saved state matches
    that of the machine we're loading into to work.  Variants already exist
    for 8 bit 16 bit and 32 bit integers, but not 64 bit integers.  This patch
    fills that hole, adding a UINT64 version.
    
    Signed-off-by: David Gibson <david at gibson.dropbear.id.au>
    Signed-off-by: Juan Quintela <quintela at redhat.com>

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 6666d27..f12ad79 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -149,6 +149,7 @@ extern const VMStateInfo vmstate_info_uint8_equal;
 extern const VMStateInfo vmstate_info_uint16_equal;
 extern const VMStateInfo vmstate_info_int32_equal;
 extern const VMStateInfo vmstate_info_uint32_equal;
+extern const VMStateInfo vmstate_info_uint64_equal;
 extern const VMStateInfo vmstate_info_int32_le;
 
 extern const VMStateInfo vmstate_info_uint8;
@@ -521,6 +522,12 @@ extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_UINT32_EQUAL(_f, _s)                                   \
     VMSTATE_SINGLE(_f, _s, 0, vmstate_info_uint32_equal, uint32_t)
 
+#define VMSTATE_UINT64_EQUAL_V(_f, _s, _v)                            \
+    VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64_equal, uint64_t)
+
+#define VMSTATE_UINT64_EQUAL(_f, _s)                                  \
+    VMSTATE_UINT64_EQUAL_V(_f, _s, 0)
+
 #define VMSTATE_INT32_LE(_f, _s)                                   \
     VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t)
 
diff --git a/savevm.c b/savevm.c
index 35c8d1e..cd98b0d 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1072,6 +1072,27 @@ const VMStateInfo vmstate_info_uint64 = {
     .put  = put_uint64,
 };
 
+/* 64 bit unsigned int. See that the received value is the same than the one
+   in the field */
+
+static int get_uint64_equal(QEMUFile *f, void *pv, size_t size)
+{
+    uint64_t *v = pv;
+    uint64_t v2;
+    qemu_get_be64s(f, &v2);
+
+    if (*v == v2) {
+        return 0;
+    }
+    return -EINVAL;
+}
+
+const VMStateInfo vmstate_info_uint64_equal = {
+    .name = "int64 equal",
+    .get  = get_uint64_equal,
+    .put  = put_uint64,
+};
+
 /* 8 bit int. See that the received value is the same than the one
    in the field */
 
commit 817c60457f41e8643b612d451b3737433e9c7e0a
Author: Juan Quintela <quintela at redhat.com>
Date:   Mon Feb 11 15:11:10 2013 +0100

    migration: Improve QMP documentation
    
    Signed-off-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>

diff --git a/qmp-commands.hx b/qmp-commands.hx
index b370060..5e847b1 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -644,7 +644,7 @@ EQMP
 
 SQMP
 migrate-set-cache-size
----------------------
+----------------------
 
 Set cache size to be used by XBZRLE migration, the cache size will be rounded
 down to the nearest power of 2
@@ -667,7 +667,7 @@ EQMP
 
 SQMP
 query-migrate-cache-size
----------------------
+------------------------
 
 Show cache size to be used by XBZRLE migration
 
@@ -2431,32 +2431,42 @@ The main json-object contains the following:
      - Possible values: "active", "completed", "failed", "cancelled"
 - "total-time": total amount of ms since migration started.  If
                 migration has ended, it returns the total migration
-		 time (json-int)
+                time (json-int)
 - "downtime": only present when migration has finished correctly
               total amount in ms for downtime that happened (json-int)
 - "expected-downtime": only present while migration is active
                 total amount in ms for downtime that was calculated on
-		the last bitmap round (json-int)
+                the last bitmap round (json-int)
 - "ram": only present if "status" is "active", it is a json-object with the
-  following RAM information (in bytes):
-         - "transferred": amount transferred (json-int)
-         - "remaining": amount remaining (json-int)
-         - "total": total (json-int)
-         - "duplicate": number of duplicated pages (json-int)
-         - "normal" : number of normal pages transferred (json-int)
-         - "normal-bytes" : number of normal bytes transferred (json-int)
+  following RAM information:
+         - "transferred": amount transferred in bytes (json-int)
+         - "remaining": amount remaining to transfer in bytes (json-int)
+         - "total": total amount of memory in bytes (json-int)
+         - "duplicate": number of pages filled entirely with the same
+            byte (json-int)
+            These are sent over the wire much more efficiently.
+         - "normal" : number of whole pages transfered.  I.e. they
+            were not sent as duplicate or xbzrle pages (json-int)
+         - "normal-bytes" : number of bytes transferred in whole
+            pages. This is just normal pages times size of one page,
+            but this way upper levels don't need to care about page
+            size (json-int)
 - "disk": only present if "status" is "active" and it is a block migration,
-  it is a json-object with the following disk information (in bytes):
-         - "transferred": amount transferred (json-int)
-         - "remaining": amount remaining (json-int)
-         - "total": total (json-int)
+  it is a json-object with the following disk information:
+         - "transferred": amount transferred in bytes (json-int)
+         - "remaining": amount remaining to transfer in bytes json-int)
+         - "total": total disk size in bytes (json-int)
 - "xbzrle-cache": only present if XBZRLE is active.
   It is a json-object with the following XBZRLE information:
-         - "cache-size": XBZRLE cache size
-         - "bytes": total XBZRLE bytes transferred
+         - "cache-size": XBZRLE cache size in bytes
+         - "bytes": number of bytes transferred for XBZRLE compressed pages
          - "pages": number of XBZRLE compressed pages
-         - "cache-miss": number of cache misses
-         - "overflow": number of XBZRLE overflows
+         - "cache-miss": number of XBRZRLE page cache misses
+         - "overflow": number of times XBZRLE overflows.  This means
+           that the XBZRLE encoding was bigger than just sent the
+           whole page, and then we sent the whole page instead (as as
+           normal page).
+
 Examples:
 
 1. Before the first migration
@@ -2567,11 +2577,11 @@ EQMP
 
 SQMP
 migrate-set-capabilities
--------
+------------------------
 
 Enable/Disable migration capabilities
 
-- "xbzrle": xbzrle support
+- "xbzrle": XBZRLE support
 
 Arguments:
 
@@ -2590,7 +2600,7 @@ EQMP
     },
 SQMP
 query-migrate-capabilities
--------
+--------------------------
 
 Query current migration capabilities
 
commit 4d700430a20b3d53b7b15bc5f6666f7e570e3f2c
Author: Michal Novotny <minovotn at redhat.com>
Date:   Mon Mar 25 17:31:33 2013 +0100

    New QMP command query-cpu-max and HMP command cpu_max
    
    These commands return the maximum number of CPUs supported by the
    currently running emulator instance, as defined in its QEMUMachine
    struct.
    
    Signed-off-by: Michal Novotny <minovotn at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index df44906..3d98604 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1643,6 +1643,8 @@ show qdev device model list
 show roms
 @item info tpm
 show the TPM device
+ at item info cpu_max
+show the number of CPUs supported by the machine being emulated.
 @end table
 ETEXI
 
diff --git a/hmp.c b/hmp.c
index d319897..c12c495 100644
--- a/hmp.c
+++ b/hmp.c
@@ -748,6 +748,14 @@ void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
     g_free(data);
 }
 
+void hmp_query_cpu_max(Monitor *mon, const QDict *qdict)
+{
+    int cpu_max;
+
+    cpu_max = qmp_query_cpu_max(NULL);
+    monitor_printf(mon, "Maximum number of CPUs is %d\n", cpu_max);
+}
+
 static void hmp_cont_cb(void *opaque, int err)
 {
     if (!err) {
diff --git a/hmp.h b/hmp.h
index 95fe76e..80e8b41 100644
--- a/hmp.h
+++ b/hmp.h
@@ -42,6 +42,7 @@ void hmp_stop(Monitor *mon, const QDict *qdict);
 void hmp_system_reset(Monitor *mon, const QDict *qdict);
 void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
 void hmp_cpu(Monitor *mon, const QDict *qdict);
+void hmp_query_cpu_max(Monitor *mon, const QDict *qdict);
 void hmp_memsave(Monitor *mon, const QDict *qdict);
 void hmp_pmemsave(Monitor *mon, const QDict *qdict);
 void hmp_ringbuf_write(Monitor *mon, const QDict *qdict);
diff --git a/monitor.c b/monitor.c
index 2d9e887..e450919 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2746,6 +2746,13 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.cmd = hmp_info_tpm,
     },
     {
+        .name       = "cpu_max",
+        .args_type  = "",
+        .params     = "",
+        .help       = "Get maximum number of VCPUs supported by machine",
+        .mhandler.cmd = hmp_query_cpu_max,
+    },
+    {
         .name       = NULL,
     },
 };
diff --git a/qapi-schema.json b/qapi-schema.json
index 0d16d14..af499bd 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1832,6 +1832,17 @@
 { 'command': 'query-migrate-cache-size', 'returns': 'int' }
 
 ##
+## @query-cpu-max
+##
+## query maximum number of CPUs supported by machine
+##
+## Returns: number of CPUs
+##
+## Since: 1.5
+###
+{ 'command': 'query-cpu-max', 'returns': 'int' }
+
+##
 # @ObjectPropertyInfo:
 #
 # @name: the name of the property
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 3aa6bd1..2051fcb 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -385,6 +385,28 @@ Note: CPUs' indexes are obtained with the 'query-cpus' command.
 EQMP
 
     {
+        .name       = "query-cpu-max",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_cpu_max,
+    },
+
+SQMP
+query-cpu-max
+-------------
+
+Get the maximum CPUs supported by the machine being currently
+emulated.
+
+Returns json-int.
+
+Example:
+
+-> { "execute": "query-cpu-max" }
+<- { "return": 255 }
+
+EQMP
+
+    {
         .name       = "memsave",
         .args_type  = "val:l,size:i,filename:s,cpu:i?",
         .mhandler.cmd_new = qmp_marshal_input_memsave,
diff --git a/vl.c b/vl.c
index aeed7f4..7643f16 100644
--- a/vl.c
+++ b/vl.c
@@ -662,6 +662,11 @@ StatusInfo *qmp_query_status(Error **errp)
     return info;
 }
 
+int64_t qmp_query_cpu_max(Error **errp)
+{
+    return current_machine->max_cpus;
+}
+
 /***********************************************************/
 /* real time host monotonic timer */
 
commit e5ecec7bad7b679aa11ab788424bc0e1705be15b
Author: Igor Mammedov <imammedo at redhat.com>
Date:   Mon Mar 25 15:48:46 2013 +0100

    qmp: fix handling of boolean values in qmp-shell
    
    qmp-shell converts only integer arguments and the rest
    is assumed to be strings which are faithfully sent as
    quoted strings by json. But QEMU refuses to accept qmp
    command with boolean argument whose value is escaped
    as string.
    
    Fix it by special-casing true/false keywords and store
    value as corresponding boolean.
    
    Signed-off-by: Igor Mammedov <imammedo at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/QMP/qmp-shell b/QMP/qmp-shell
index 24b665c..d126e63 100755
--- a/QMP/qmp-shell
+++ b/QMP/qmp-shell
@@ -101,7 +101,12 @@ class QMPShell(qmp.QEMUMonitorProtocol):
             try:
                 value = int(opt[1])
             except ValueError:
-                value = opt[1]
+                if opt[1] == 'true':
+                    value = True
+                elif opt[1] == 'false':
+                    value = False
+                else:
+                    value = opt[1]
             qmpcmd['arguments'][opt[0]] = value
         return qmpcmd
 
commit 28c4fa32bd76268320d44db5d82e0d18fbc7c864
Author: Corey Bryant <coreyb at linux.vnet.ibm.com>
Date:   Wed Mar 20 12:34:49 2013 -0400

    QMP: TPM QMP and man page documentation updates
    
    Signed-off-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/qemu-options.hx b/qemu-options.hx
index d7afeab..c40ba55 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2241,7 +2241,8 @@ Backend type must be:
 @option{passthrough}.
 
 The specific backend type will determine the applicable options.
-The @code{-tpmdev} option requires a @code{-device} option.
+The @code{-tpmdev} option creates the TPM backend and requires a
+ at code{-device} option that specifies the TPM frontend interface model.
 
 Options to each backend are described below.
 
diff --git a/qmp-commands.hx b/qmp-commands.hx
index b370060..3aa6bd1 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2721,18 +2721,76 @@ EQMP
         .mhandler.cmd_new = qmp_marshal_input_query_tpm,
     },
 
+SQMP
+query-tpm
+---------
+
+Return information about the TPM device.
+
+Arguments: None
+
+Example:
+
+-> { "execute": "query-tpm" }
+<- { "return":
+     [
+       { "model": "tpm-tis",
+         "options":
+           { "type": "passthrough",
+             "data":
+               { "cancel-path": "/sys/class/misc/tpm0/device/cancel",
+                 "path": "/dev/tpm0"
+               }
+           },
+         "id": "tpm0"
+       }
+     ]
+   }
+
+EQMP
+
     {
         .name       = "query-tpm-models",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_query_tpm_models,
     },
 
+SQMP
+query-tpm-models
+----------------
+
+Return a list of supported TPM models.
+
+Arguments: None
+
+Example:
+
+-> { "execute": "query-tpm-models" }
+<- { "return": [ "tpm-tis" ] }
+
+EQMP
+
     {
         .name       = "query-tpm-types",
         .args_type  = "",
         .mhandler.cmd_new = qmp_marshal_input_query_tpm_types,
     },
 
+SQMP
+query-tpm-types
+---------------
+
+Return a list of supported TPM types.
+
+Arguments: None
+
+Example:
+
+-> { "execute": "query-tpm-types" }
+<- { "return": [ "passthrough" ] }
+
+EQMP
+
     {
         .name       = "chardev-add",
         .args_type  = "id:s,backend:q",
commit 88ca7bcff1806594c80782ad19ba50db47086b23
Author: Corey Bryant <coreyb at linux.vnet.ibm.com>
Date:   Wed Mar 20 12:34:48 2013 -0400

    QMP: Remove duplicate TPM type from query-tpm
    
    Signed-off-by: Corey Bryant <coreyb at linux.vnet.ibm.com>
    Reviewed-by: Eric Blake <eblake at redhat.com>
    Reviewed-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>

diff --git a/hmp.c b/hmp.c
index b0a861c..d319897 100644
--- a/hmp.c
+++ b/hmp.c
@@ -631,11 +631,11 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
                        c, TpmModel_lookup[ti->model]);
 
         monitor_printf(mon, "  \\ %s: type=%s",
-                       ti->id, TpmType_lookup[ti->type]);
+                       ti->id, TpmTypeOptionsKind_lookup[ti->options->kind]);
 
-        switch (ti->tpm_options->kind) {
-        case TPM_TYPE_OPTIONS_KIND_TPM_PASSTHROUGH_OPTIONS:
-            tpo = ti->tpm_options->tpm_passthrough_options;
+        switch (ti->options->kind) {
+        case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:
+            tpo = ti->options->passthrough;
             monitor_printf(mon, "%s%s%s%s",
                            tpo->has_path ? ",path=" : "",
                            tpo->has_path ? tpo->path : "",
diff --git a/qapi-schema.json b/qapi-schema.json
index 088f4e1..0d16d14 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3403,13 +3403,12 @@
 #
 # A union referencing different TPM backend types' configuration options
 #
-# @tpm-passthough-options: TPMPassthroughOptions describing the TPM
-#                          passthrough configuration options
+# @passthrough: The configuration options for the TPM passthrough type
 #
 # Since: 1.5
 ##
 { 'union': 'TpmTypeOptions',
-   'data': { 'tpm-passthrough-options' : 'TPMPassthroughOptions' } }
+   'data': { 'passthrough' : 'TPMPassthroughOptions' } }
 
 ##
 # @TpmInfo:
@@ -3420,17 +3419,14 @@
 #
 # @model: The TPM frontend model
 #
-# @type: The TPM (backend) type being used
-#
-# @tpm-options: The TPM (backend) type configuration options
+# @options: The TPM (backend) type configuration options
 #
 # Since: 1.5
 ##
 { 'type': 'TPMInfo',
   'data': {'id': 'str',
            'model': 'TpmModel',
-           'type': 'TpmType',
-           'tpm-options': 'TpmTypeOptions' } }
+           'options': 'TpmTypeOptions' } }
 
 ##
 # @query-tpm:
diff --git a/tpm/tpm.c b/tpm/tpm.c
index ffd2495..ae00eae 100644
--- a/tpm/tpm.c
+++ b/tpm/tpm.c
@@ -257,14 +257,13 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)
 
     res->id = g_strdup(drv->id);
     res->model = drv->fe_model;
-    res->type = drv->ops->type;
-    res->tpm_options = g_new0(TpmTypeOptions, 1);
+    res->options = g_new0(TpmTypeOptions, 1);
 
-    switch (res->type) {
+    switch (drv->ops->type) {
     case TPM_TYPE_PASSTHROUGH:
-        res->tpm_options->kind = TPM_TYPE_OPTIONS_KIND_TPM_PASSTHROUGH_OPTIONS;
+        res->options->kind = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
         tpo = g_new0(TPMPassthroughOptions, 1);
-        res->tpm_options->tpm_passthrough_options = tpo;
+        res->options->passthrough = tpo;
         if (drv->path) {
             tpo->path = g_strdup(drv->path);
             tpo->has_path = true;
commit dcadaa9b40d6019ac18d6fd7763d43048ef79218
Merge: 4b5805d d32fcad
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 25 13:14:26 2013 -0500

    Merge remote-tracking branch 'stefanha/net' into staging
    
    # By Dmitry Fleytman (5) and others
    # Via Stefan Hajnoczi
    * stefanha/net:
      net: increase buffer size to accommodate Jumbo frame pkts
      VMXNET3 device implementation
      Packet abstraction for VMWARE network devices
      Common definitions for VMWARE devices
      net: iovec checksum calculator
      Checksum-related utility functions
      net: use socket_set_nodelay() for -netdev socket

commit 4b5805de49edec5a81fe810bb612317de6545a38
Merge: d2f38a0 ea804ca
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 25 13:14:20 2013 -0500

    Merge remote-tracking branch 'stefanha/block' into staging
    
    # By Liu Yuan (1) and Stefan Weil (1)
    # Via Stefan Hajnoczi
    * stefanha/block:
      block: Add options QDict to bdrv_file_open() prototypes (fix MinGW build)
      rbd: fix compile error

commit d2f38a0acb0a1c5b7ab7621a32d603d08d513bea
Merge: d63c947 0099cd4
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 25 13:13:53 2013 -0500

    Merge remote-tracking branch 'kraxel/ipxe.3' into staging
    
    # By Gerd Hoffmann
    # Via Gerd Hoffmann
    * kraxel/ipxe.3:
      ipxe: update binaries
      ipxe: disable two second timeout

commit d63c9477e0cc303492325880dc9977f4096d895d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Mar 25 10:23:56 2013 -0500

    glib: add a compatibility interface for g_timeout_add_seconds
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/glib-compat.h b/include/glib-compat.h
new file mode 100644
index 0000000..8aa77af
--- /dev/null
+++ b/include/glib-compat.h
@@ -0,0 +1,27 @@
+/*
+ * GLIB Compatibility Functions
+ *
+ * Copyright IBM, Corp. 2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_GLIB_COMPAT_H
+#define QEMU_GLIB_COMPAT_H
+
+#include <glib.h>
+
+#if !GLIB_CHECK_VERSION(2, 14, 0)
+static inline guint g_timeout_add_seconds(guint interval, GSourceFunc function,
+                                          gpointer data)
+{
+    return g_timeout_add(interval * 1000, function, data);
+}
+#endif
+
+#endif
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 7754ee2..2371132 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -40,7 +40,7 @@
 #include <sys/time.h>
 #include <assert.h>
 #include <signal.h>
-#include <glib.h>
+#include "glib-compat.h"
 
 #ifdef _WIN32
 #include "sysemu/os-win32.h"
commit 6db253caf84203c9fb106b539072699fdd4730fe
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Sun Mar 24 19:10:02 2013 +0100

    gtk: Release modifier when graphic console loses keyboard focus
    
    This solves, e.g., sticky ALT when selecting a GTK menu, switching to a
    different window or selecting a different virtual console.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Message-id: 514F417A.6010908 at web.de
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/gtk.c b/ui/gtk.c
index 305940d..1edfaca 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -98,6 +98,11 @@ static inline void gdk_drawable_get_size(GdkWindow *w, gint *ww, gint *wh)
 #define GDK_KEY_minus GDK_minus
 #endif
 
+static const int modifier_keycode[] = {
+    /* shift, control, alt keys, meta keys, both left & right */
+    0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8, 0xdb, 0xdd,
+};
+
 typedef struct VirtualConsole
 {
     GtkWidget *menu_item;
@@ -157,6 +162,8 @@ typedef struct GtkDisplayState
     gboolean free_scale;
 
     bool external_pause_update;
+
+    bool modifier_pressed[ARRAY_SIZE(modifier_keycode)];
 } GtkDisplayState;
 
 static GtkDisplayState *global_state;
@@ -263,6 +270,26 @@ static void gd_update_full_redraw(GtkDisplayState *s)
     gtk_widget_queue_draw_area(s->drawing_area, 0, 0, ww, wh);
 }
 
+static void gtk_release_modifiers(GtkDisplayState *s)
+{
+    int i, keycode;
+
+    if (!gd_on_vga(s)) {
+        return;
+    }
+    for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) {
+        keycode = modifier_keycode[i];
+        if (!s->modifier_pressed[i]) {
+            continue;
+        }
+        if (keycode & SCANCODE_GREY) {
+            kbd_put_keycode(SCANCODE_EMUL0);
+        }
+        kbd_put_keycode(keycode | SCANCODE_UP);
+        s->modifier_pressed[i] = false;
+    }
+}
+
 /** DisplayState Callbacks **/
 
 static void gd_update(DisplayChangeListener *dcl,
@@ -393,8 +420,9 @@ static gboolean gd_window_key_event(GtkWidget *widget, GdkEventKey *key, void *o
     if (!handled && propagate_accel) {
         handled = gtk_window_activate_key(GTK_WINDOW(widget), key);
     }
-
-    if (!handled) {
+    if (handled) {
+        gtk_release_modifiers(s);
+    } else {
         handled = gtk_window_propagate_key_event(GTK_WINDOW(widget), key);
     }
 
@@ -624,8 +652,10 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
 
 static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
 {
+    GtkDisplayState *s = opaque;
     int gdk_keycode;
     int qemu_keycode;
+    int i;
 
     gdk_keycode = key->hardware_keycode;
 
@@ -647,6 +677,12 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
             gdk_keycode, qemu_keycode,
             (key->type == GDK_KEY_PRESS) ? "down" : "up");
 
+    for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) {
+        if (qemu_keycode == modifier_keycode[i]) {
+            s->modifier_pressed[i] = (key->type == GDK_KEY_PRESS);
+        }
+    }
+
     if (qemu_keycode & SCANCODE_GREY) {
         kbd_put_keycode(SCANCODE_EMUL0);
     }
@@ -702,6 +738,7 @@ static void gd_menu_switch_vc(GtkMenuItem *item, void *opaque)
     } else {
         int i;
 
+        gtk_release_modifiers(s);
         for (i = 0; i < s->nb_vcs; i++) {
             if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(s->vc[i].menu_item))) {
                 gtk_notebook_set_current_page(GTK_NOTEBOOK(s->notebook), i + 1);
@@ -1002,6 +1039,16 @@ static gboolean gd_leave_event(GtkWidget *widget, GdkEventCrossing *crossing, gp
     return TRUE;
 }
 
+static gboolean gd_focus_out_event(GtkWidget *widget,
+                                   GdkEventCrossing *crossing, gpointer data)
+{
+    GtkDisplayState *s = data;
+
+    gtk_release_modifiers(s);
+
+    return TRUE;
+}
+
 /** Virtual Console Callbacks **/
 
 static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
@@ -1185,6 +1232,8 @@ static void gd_connect_signals(GtkDisplayState *s)
                      G_CALLBACK(gd_enter_event), s);
     g_signal_connect(s->drawing_area, "leave-notify-event",
                      G_CALLBACK(gd_leave_event), s);
+    g_signal_connect(s->drawing_area, "focus-out-event",
+                     G_CALLBACK(gd_focus_out_event), s);
 }
 
 static void gd_create_menus(GtkDisplayState *s)
commit d32fcad366e5f45d33dab2ee4de0e5729439680b
Author: Scott Feldman <sfeldma at cumulusnetworks.com>
Date:   Mon Mar 18 11:43:44 2013 -0700

    net: increase buffer size to accommodate Jumbo frame pkts
    
    Socket buffer sizes were hard-coded to 4K for VDE and socket netdevs.  Bump this
    up to 68K (ala tap netdev) to handle maximum GSO packet size (64k) plus plenty
    of room for the ethernet and virtio_net headers.
    
    Originally, ran into this limitation when using -netdev UDP sockets to connect
    VM-to-VM, where VM interface is configure with MTU=9000.  (Using virtio_net
    NIC model).  Test is simple: ping -M do -s 8500 <target>.  This test will
    attempt to ping with unfragmented packet of given size.  Without patch, size
    is limited to < 4K (minus protocol hdrs).  With patch, ping test works with pkt
    size up to 9000 (again, minus protocol hdrs).
    
    v2: per Stefan, increase buf size to (4096+65536) as done in tap and apply
        to vde and socket netdevs.
    v1: increase buf size to 12K just for -netdev UDP sockets
    
    Signed-off-by: Scott Feldman <sfeldma at cumulusnetworks.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/include/net/net.h b/include/net/net.h
index cb049a1..43d85a1 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -11,6 +11,11 @@
 
 #define MAX_QUEUE_NUM 1024
 
+/* Maximum GSO packet size (64k) plus plenty of room for
+ * the ethernet and virtio_net headers
+ */
+#define NET_BUFSIZE (4096 + 65536)
+
 struct MACAddr {
     uint8_t a[6];
 };
diff --git a/net/net.c b/net/net.c
index f3d67f8..7869161 100644
--- a/net/net.c
+++ b/net/net.c
@@ -497,7 +497,7 @@ ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
 static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
                                int iovcnt)
 {
-    uint8_t buffer[4096];
+    uint8_t buffer[NET_BUFSIZE];
     size_t offset;
 
     offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer));
diff --git a/net/socket.c b/net/socket.c
index b0c83e0..6c3752b 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -40,7 +40,7 @@ typedef struct NetSocketState {
     unsigned int index;
     unsigned int packet_len;
     unsigned int send_index;      /* number of bytes sent (only SOCK_STREAM) */
-    uint8_t buf[4096];
+    uint8_t buf[NET_BUFSIZE];
     struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
     IOHandler *send_fn;           /* differs between SOCK_STREAM/SOCK_DGRAM */
     bool read_poll;               /* waiting to receive data? */
@@ -146,7 +146,7 @@ static void net_socket_send(void *opaque)
     NetSocketState *s = opaque;
     int size, err;
     unsigned l;
-    uint8_t buf1[4096];
+    uint8_t buf1[NET_BUFSIZE];
     const uint8_t *buf;
 
     size = qemu_recv(s->fd, buf1, sizeof(buf1), 0);
diff --git a/net/tap.c b/net/tap.c
index ce79699..e7c8481 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -44,17 +44,12 @@
 
 #include "hw/vhost_net.h"
 
-/* Maximum GSO packet size (64k) plus plenty of room for
- * the ethernet and virtio_net headers
- */
-#define TAP_BUFSIZE (4096 + 65536)
-
 typedef struct TAPState {
     NetClientState nc;
     int fd;
     char down_script[1024];
     char down_script_arg[128];
-    uint8_t buf[TAP_BUFSIZE];
+    uint8_t buf[NET_BUFSIZE];
     bool read_poll;
     bool write_poll;
     bool using_vnet_hdr;
diff --git a/net/vde.c b/net/vde.c
index 4dea32d..2a619fb 100644
--- a/net/vde.c
+++ b/net/vde.c
@@ -39,7 +39,7 @@ typedef struct VDEState {
 static void vde_to_qemu(void *opaque)
 {
     VDEState *s = opaque;
-    uint8_t buf[4096];
+    uint8_t buf[NET_BUFSIZE];
     int size;
 
     size = vde_recv(s->vde, (char *)buf, sizeof(buf), 0);
commit 786fd2b0f87baded8c9e55307b99719eea3e016e
Author: Dmitry Fleytman <dmitry at daynix.com>
Date:   Sat Mar 9 11:21:06 2013 +0200

    VMXNET3 device implementation
    
    Signed-off-by: Dmitry Fleytman <dmitry at daynix.com>
    Signed-off-by: Yan Vugenfirer <yan at daynix.com>
    Signed-off-by: Stefan Hajnoczi <stefanha at redhat.com>

diff --git a/default-configs/pci.mak b/default-configs/pci.mak
index ee2d18d..ce56d58 100644
--- a/default-configs/pci.mak
+++ b/default-configs/pci.mak
@@ -13,6 +13,7 @@ CONFIG_LSI_SCSI_PCI=y
 CONFIG_MEGASAS_SCSI_PCI=y
 CONFIG_RTL8139_PCI=y
 CONFIG_E1000_PCI=y
+CONFIG_VMXNET3_PCI=y
 CONFIG_IDE_CORE=y
 CONFIG_IDE_QDEV=y
 CONFIG_IDE_PCI=y
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 1a988ca..d0b2ecb 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -120,6 +120,7 @@ common-obj-$(CONFIG_PCNET_COMMON) += pcnet.o
 common-obj-$(CONFIG_E1000_PCI) += e1000.o
 common-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o
 common-obj-$(CONFIG_VMXNET3_PCI) += vmxnet_tx_pkt.o vmxnet_rx_pkt.o
+common-obj-$(CONFIG_VMXNET3_PCI) += vmxnet3.o
 
 common-obj-$(CONFIG_SMC91C111) += smc91c111.o
 common-obj-$(CONFIG_LAN9118) += lan9118.o
diff --git a/hw/pci/pci.h b/hw/pci/pci.h
index f340fe5..3beb70b 100644
--- a/hw/pci/pci.h
+++ b/hw/pci/pci.h
@@ -60,6 +60,7 @@
 #define PCI_DEVICE_ID_VMWARE_NET         0x0720
 #define PCI_DEVICE_ID_VMWARE_SCSI        0x0730
 #define PCI_DEVICE_ID_VMWARE_IDE         0x1729
+#define PCI_DEVICE_ID_VMWARE_VMXNET3     0x07B0
 
 /* Intel (0x8086) */
 #define PCI_DEVICE_ID_INTEL_82551IT      0x1209
diff --git a/hw/vmxnet3.c b/hw/vmxnet3.c
new file mode 100644
index 0000000..925be80
--- /dev/null
+++ b/hw/vmxnet3.c
@@ -0,0 +1,2461 @@
+/*
+ * QEMU VMWARE VMXNET3 paravirtual NIC
+ *
+ * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com)
+ *
+ * Developed by Daynix Computing LTD (http://www.daynix.com)
+ *
+ * Authors:
+ * Dmitry Fleytman <dmitry at daynix.com>
+ * Tamir Shomer <tamirs at daynix.com>
+ * Yan Vugenfirer <yan at daynix.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "hw.h"
+#include "pci/pci.h"
+#include "net/net.h"
+#include "virtio-net.h"
+#include "net/tap.h"
+#include "net/checksum.h"
+#include "sysemu/sysemu.h"
+#include "qemu-common.h"
+#include "qemu/bswap.h"
+#include "pci/msix.h"
+#include "pci/msi.h"
+
+#include "vmxnet3.h"
+#include "vmxnet_debug.h"
+#include "vmware_utils.h"
+#include "vmxnet_tx_pkt.h"
+#include "vmxnet_rx_pkt.h"
+
+#define PCI_DEVICE_ID_VMWARE_VMXNET3_REVISION 0x1
+#define VMXNET3_MSIX_BAR_SIZE 0x2000
+
+#define VMXNET3_BAR0_IDX      (0)
+#define VMXNET3_BAR1_IDX      (1)
+#define VMXNET3_MSIX_BAR_IDX  (2)
+
+#define VMXNET3_OFF_MSIX_TABLE (0x000)
+#define VMXNET3_OFF_MSIX_PBA   (0x800)
+
+/* Link speed in Mbps should be shifted by 16 */
+#define VMXNET3_LINK_SPEED      (1000 << 16)
+
+/* Link status: 1 - up, 0 - down. */
+#define VMXNET3_LINK_STATUS_UP  0x1
+
+/* Least significant bit should be set for revision and version */
+#define VMXNET3_DEVICE_VERSION    0x1
+#define VMXNET3_DEVICE_REVISION   0x1
+
+/* Macros for rings descriptors access */
+#define VMXNET3_READ_TX_QUEUE_DESCR8(dpa, field) \
+    (vmw_shmem_ld8(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
+
+#define VMXNET3_WRITE_TX_QUEUE_DESCR8(dpa, field, value) \
+    (vmw_shmem_st8(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field, value)))
+
+#define VMXNET3_READ_TX_QUEUE_DESCR32(dpa, field) \
+    (vmw_shmem_ld32(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
+
+#define VMXNET3_WRITE_TX_QUEUE_DESCR32(dpa, field, value) \
+    (vmw_shmem_st32(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field), value))
+
+#define VMXNET3_READ_TX_QUEUE_DESCR64(dpa, field) \
+    (vmw_shmem_ld64(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
+
+#define VMXNET3_WRITE_TX_QUEUE_DESCR64(dpa, field, value) \
+    (vmw_shmem_st64(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field), value))
+
+#define VMXNET3_READ_RX_QUEUE_DESCR64(dpa, field) \
+    (vmw_shmem_ld64(dpa + offsetof(struct Vmxnet3_RxQueueDesc, field)))
+
+#define VMXNET3_READ_RX_QUEUE_DESCR32(dpa, field) \
+    (vmw_shmem_ld32(dpa + offsetof(struct Vmxnet3_RxQueueDesc, field)))
+
+#define VMXNET3_WRITE_RX_QUEUE_DESCR64(dpa, field, value) \
+    (vmw_shmem_st64(dpa + offsetof(struct Vmxnet3_RxQueueDesc, field), value))
+
+#define VMXNET3_WRITE_RX_QUEUE_DESCR8(dpa, field, value) \
+    (vmw_shmem_st8(dpa + offsetof(struct Vmxnet3_RxQueueDesc, field), value))
+
+/* Macros for guest driver shared area access */
+#define VMXNET3_READ_DRV_SHARED64(shpa, field) \
+    (vmw_shmem_ld64(shpa + offsetof(struct Vmxnet3_DriverShared, field)))
+
+#define VMXNET3_READ_DRV_SHARED32(shpa, field) \
+    (vmw_shmem_ld32(shpa + offsetof(struct Vmxnet3_DriverShared, field)))
+
+#define VMXNET3_WRITE_DRV_SHARED32(shpa, field, val) \
+    (vmw_shmem_st32(shpa + offsetof(struct Vmxnet3_DriverShared, field), val))
+
+#define VMXNET3_READ_DRV_SHARED16(shpa, field) \
+    (vmw_shmem_ld16(shpa + offsetof(struct Vmxnet3_DriverShared, field)))
+
+#define VMXNET3_READ_DRV_SHARED8(shpa, field) \
+    (vmw_shmem_ld8(shpa + offsetof(struct Vmxnet3_DriverShared, field)))
+
+#define VMXNET3_READ_DRV_SHARED(shpa, field, b, l) \
+    (vmw_shmem_read(shpa + offsetof(struct Vmxnet3_DriverShared, field), b, l))
+
+#define VMXNET_FLAG_IS_SET(field, flag) (((field) & (flag)) == (flag))
+
+#define TYPE_VMXNET3 "vmxnet3"
+#define VMXNET3(obj) OBJECT_CHECK(VMXNET3State, (obj), TYPE_VMXNET3)
+
+/* Cyclic ring abstraction */
+typedef struct {
+    hwaddr pa;
+    size_t size;
+    size_t cell_size;
+    size_t next;
+    uint8_t gen;
+} Vmxnet3Ring;
+
+static inline void vmxnet3_ring_init(Vmxnet3Ring *ring,
+                                     hwaddr pa,
+                                     size_t size,
+                                     size_t cell_size,
+                                     bool zero_region)
+{
+    ring->pa = pa;
+    ring->size = size;
+    ring->cell_size = cell_size;
+    ring->gen = VMXNET3_INIT_GEN;
+    ring->next = 0;
+
+    if (zero_region) {
+        vmw_shmem_set(pa, 0, size * cell_size);
+    }
+}
+
+#define VMXNET3_RING_DUMP(macro, ring_name, ridx, r)                         \
+    macro("%s#%d: base %" PRIx64 " size %lu cell_size %lu gen %d next %lu",  \
+          (ring_name), (ridx),                                               \
+          (r)->pa, (r)->size, (r)->cell_size, (r)->gen, (r)->next)
+
+static inline void vmxnet3_ring_inc(Vmxnet3Ring *ring)
+{
+    if (++ring->next >= ring->size) {
+        ring->next = 0;
+        ring->gen ^= 1;
+    }
+}
+
+static inline void vmxnet3_ring_dec(Vmxnet3Ring *ring)
+{
+    if (ring->next-- == 0) {
+        ring->next = ring->size - 1;
+        ring->gen ^= 1;
+    }
+}
+
+static inline hwaddr vmxnet3_ring_curr_cell_pa(Vmxnet3Ring *ring)
+{
+    return ring->pa + ring->next * ring->cell_size;
+}
+
+static inline void vmxnet3_ring_read_curr_cell(Vmxnet3Ring *ring, void *buff)
+{
+    vmw_shmem_read(vmxnet3_ring_curr_cell_pa(ring), buff, ring->cell_size);
+}
+
+static inline void vmxnet3_ring_write_curr_cell(Vmxnet3Ring *ring, void *buff)
+{
+    vmw_shmem_write(vmxnet3_ring_curr_cell_pa(ring), buff, ring->cell_size);
+}
+
+static inline size_t vmxnet3_ring_curr_cell_idx(Vmxnet3Ring *ring)
+{
+    return ring->next;
+}
+
+static inline uint8_t vmxnet3_ring_curr_gen(Vmxnet3Ring *ring)
+{
+    return ring->gen;
+}
+
+/* Debug trace-related functions */
+static inline void
+vmxnet3_dump_tx_descr(struct Vmxnet3_TxDesc *descr)
+{
+    VMW_PKPRN("TX DESCR: "
+              "addr %" PRIx64 ", len: %d, gen: %d, rsvd: %d, "
+              "dtype: %d, ext1: %d, msscof: %d, hlen: %d, om: %d, "
+              "eop: %d, cq: %d, ext2: %d, ti: %d, tci: %d",
+              le64_to_cpu(descr->addr), descr->len, descr->gen, descr->rsvd,
+              descr->dtype, descr->ext1, descr->msscof, descr->hlen, descr->om,
+              descr->eop, descr->cq, descr->ext2, descr->ti, descr->tci);
+}
+
+static inline void
+vmxnet3_dump_virt_hdr(struct virtio_net_hdr *vhdr)
+{
+    VMW_PKPRN("VHDR: flags 0x%x, gso_type: 0x%x, hdr_len: %d, gso_size: %d, "
+              "csum_start: %d, csum_offset: %d",
+              vhdr->flags, vhdr->gso_type, vhdr->hdr_len, vhdr->gso_size,
+              vhdr->csum_start, vhdr->csum_offset);
+}
+
+static inline void
+vmxnet3_dump_rx_descr(struct Vmxnet3_RxDesc *descr)
+{
+    VMW_PKPRN("RX DESCR: addr %" PRIx64 ", len: %d, gen: %d, rsvd: %d, "
+              "dtype: %d, ext1: %d, btype: %d",
+              le64_to_cpu(descr->addr), descr->len, descr->gen,
+              descr->rsvd, descr->dtype, descr->ext1, descr->btype);
+}
+
+/* Device state and helper functions */
+#define VMXNET3_RX_RINGS_PER_QUEUE (2)
+
+typedef struct {
+    Vmxnet3Ring tx_ring;
+    Vmxnet3Ring comp_ring;
+
+    uint8_t intr_idx;
+    hwaddr tx_stats_pa;
+    struct UPT1_TxStats txq_stats;
+} Vmxnet3TxqDescr;
+
+typedef struct {
+    Vmxnet3Ring rx_ring[VMXNET3_RX_RINGS_PER_QUEUE];
+    Vmxnet3Ring comp_ring;
+    uint8_t intr_idx;
+    hwaddr rx_stats_pa;
+    struct UPT1_RxStats rxq_stats;
+} Vmxnet3RxqDescr;
+
+typedef struct {
+    bool is_masked;
+    bool is_pending;
+    bool is_asserted;
+} Vmxnet3IntState;
+
+typedef struct {
+        PCIDevice parent_obj;
+        NICState *nic;
+        NICConf conf;
+        MemoryRegion bar0;
+        MemoryRegion bar1;
+        MemoryRegion msix_bar;
+
+        Vmxnet3RxqDescr rxq_descr[VMXNET3_DEVICE_MAX_RX_QUEUES];
+        Vmxnet3TxqDescr txq_descr[VMXNET3_DEVICE_MAX_TX_QUEUES];
+
+        /* Whether MSI-X support was installed successfully */
+        bool msix_used;
+        /* Whether MSI support was installed successfully */
+        bool msi_used;
+        hwaddr drv_shmem;
+        hwaddr temp_shared_guest_driver_memory;
+
+        uint8_t txq_num;
+
+        /* This boolean tells whether RX packet being indicated has to */
+        /* be split into head and body chunks from different RX rings  */
+        bool rx_packets_compound;
+
+        bool rx_vlan_stripping;
+        bool lro_supported;
+
+        uint8_t rxq_num;
+
+        /* Network MTU */
+        uint32_t mtu;
+
+        /* Maximum number of fragments for indicated TX packets */
+        uint32_t max_tx_frags;
+
+        /* Maximum number of fragments for indicated RX packets */
+        uint16_t max_rx_frags;
+
+        /* Index for events interrupt */
+        uint8_t event_int_idx;
+
+        /* Whether automatic interrupts masking enabled */
+        bool auto_int_masking;
+
+        bool peer_has_vhdr;
+
+        /* TX packets to QEMU interface */
+        struct VmxnetTxPkt *tx_pkt;
+        uint32_t offload_mode;
+        uint32_t cso_or_gso_size;
+        uint16_t tci;
+        bool needs_vlan;
+
+        struct VmxnetRxPkt *rx_pkt;
+
+        bool tx_sop;
+        bool skip_current_tx_pkt;
+
+        uint32_t device_active;
+        uint32_t last_command;
+
+        uint32_t link_status_and_speed;
+
+        Vmxnet3IntState interrupt_states[VMXNET3_MAX_INTRS];
+
+        uint32_t temp_mac;   /* To store the low part first */
+
+        MACAddr perm_mac;
+        uint32_t vlan_table[VMXNET3_VFT_SIZE];
+        uint32_t rx_mode;
+        MACAddr *mcast_list;
+        uint32_t mcast_list_len;
+        uint32_t mcast_list_buff_size; /* needed for live migration. */
+} VMXNET3State;
+
+/* Interrupt management */
+
+/*
+ *This function returns sign whether interrupt line is in asserted state
+ * This depends on the type of interrupt used. For INTX interrupt line will
+ * be asserted until explicit deassertion, for MSI(X) interrupt line will
+ * be deasserted automatically due to notification semantics of the MSI(X)
+ * interrupts
+ */
+static bool _vmxnet3_assert_interrupt_line(VMXNET3State *s, uint32_t int_idx)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+
+    if (s->msix_used && msix_enabled(d)) {
+        VMW_IRPRN("Sending MSI-X notification for vector %u", int_idx);
+        msix_notify(d, int_idx);
+        return false;
+    }
+    if (s->msi_used && msi_enabled(d)) {
+        VMW_IRPRN("Sending MSI notification for vector %u", int_idx);
+        msi_notify(d, int_idx);
+        return false;
+    }
+
+    VMW_IRPRN("Asserting line for interrupt %u", int_idx);
+    qemu_set_irq(d->irq[int_idx], 1);
+    return true;
+}
+
+static void _vmxnet3_deassert_interrupt_line(VMXNET3State *s, int lidx)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+
+    /*
+     * This function should never be called for MSI(X) interrupts
+     * because deassertion never required for message interrupts
+     */
+    assert(!s->msix_used || !msix_enabled(d));
+    /*
+     * This function should never be called for MSI(X) interrupts
+     * because deassertion never required for message interrupts
+     */
+    assert(!s->msi_used || !msi_enabled(d));
+
+    VMW_IRPRN("Deasserting line for interrupt %u", lidx);
+    qemu_set_irq(d->irq[lidx], 0);
+}
+
+static void vmxnet3_update_interrupt_line_state(VMXNET3State *s, int lidx)
+{
+    if (!s->interrupt_states[lidx].is_pending &&
+       s->interrupt_states[lidx].is_asserted) {
+        VMW_IRPRN("New interrupt line state for index %d is DOWN", lidx);
+        _vmxnet3_deassert_interrupt_line(s, lidx);
+        s->interrupt_states[lidx].is_asserted = false;
+        return;
+    }
+
+    if (s->interrupt_states[lidx].is_pending &&
+       !s->interrupt_states[lidx].is_masked &&
+       !s->interrupt_states[lidx].is_asserted) {
+        VMW_IRPRN("New interrupt line state for index %d is UP", lidx);
+        s->interrupt_states[lidx].is_asserted =
+            _vmxnet3_assert_interrupt_line(s, lidx);
+        s->interrupt_states[lidx].is_pending = false;
+        return;
+    }
+}
+
+static void vmxnet3_trigger_interrupt(VMXNET3State *s, int lidx)
+{
+    PCIDevice *d = PCI_DEVICE(s);
+    s->interrupt_states[lidx].is_pending = true;
+    vmxnet3_update_interrupt_line_state(s, lidx);
+
+    if (s->msix_used && msix_enabled(d) && s->auto_int_masking) {
+        goto do_automask;
+    }
+
+    if (s->msi_used && msi_enabled(d) && s->auto_int_masking) {
+        goto do_automask;
+    }
+
+    return;
+
+do_automask:
+    s->interrupt_states[lidx].is_masked = true;
+    vmxnet3_update_interrupt_line_state(s, lidx);
+}
+
+static bool vmxnet3_interrupt_asserted(VMXNET3State *s, int lidx)
+{
+    return s->interrupt_states[lidx].is_asserted;
+}
+
+static void vmxnet3_clear_interrupt(VMXNET3State *s, int int_idx)
+{
+    s->interrupt_states[int_idx].is_pending = false;
+    if (s->auto_int_masking) {
+        s->interrupt_states[int_idx].is_masked = true;
+    }
+    vmxnet3_update_interrupt_line_state(s, int_idx);
+}
+
+static void
+vmxnet3_on_interrupt_mask_changed(VMXNET3State *s, int lidx, bool is_masked)
+{
+    s->interrupt_states[lidx].is_masked = is_masked;
+    vmxnet3_update_interrupt_line_state(s, lidx);
+}
+
+static bool vmxnet3_verify_driver_magic(hwaddr dshmem)
+{
+    return (VMXNET3_READ_DRV_SHARED32(dshmem, magic) == VMXNET3_REV1_MAGIC);
+}
+
+#define VMXNET3_GET_BYTE(x, byte_num) (((x) >> (byte_num)*8) & 0xFF)
+#define VMXNET3_MAKE_BYTE(byte_num, val) \
+    (((uint32_t)((val) & 0xFF)) << (byte_num)*8)
+
+static void vmxnet3_set_variable_mac(VMXNET3State *s, uint32_t h, uint32_t l)
+{
+    s->conf.macaddr.a[0] = VMXNET3_GET_BYTE(l,  0);
+    s->conf.macaddr.a[1] = VMXNET3_GET_BYTE(l,  1);
+    s->conf.macaddr.a[2] = VMXNET3_GET_BYTE(l,  2);
+    s->conf.macaddr.a[3] = VMXNET3_GET_BYTE(l,  3);
+    s->conf.macaddr.a[4] = VMXNET3_GET_BYTE(h, 0);
+    s->conf.macaddr.a[5] = VMXNET3_GET_BYTE(h, 1);
+
+    VMW_CFPRN("Variable MAC: " VMXNET_MF, VMXNET_MA(s->conf.macaddr.a));
+
+    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+}
+
+static uint64_t vmxnet3_get_mac_low(MACAddr *addr)
+{
+    return VMXNET3_MAKE_BYTE(0, addr->a[0]) |
+           VMXNET3_MAKE_BYTE(1, addr->a[1]) |
+           VMXNET3_MAKE_BYTE(2, addr->a[2]) |
+           VMXNET3_MAKE_BYTE(3, addr->a[3]);
+}
+
+static uint64_t vmxnet3_get_mac_high(MACAddr *addr)
+{
+    return VMXNET3_MAKE_BYTE(0, addr->a[4]) |
+           VMXNET3_MAKE_BYTE(1, addr->a[5]);
+}
+
+static void
+vmxnet3_inc_tx_consumption_counter(VMXNET3State *s, int qidx)
+{
+    vmxnet3_ring_inc(&s->txq_descr[qidx].tx_ring);
+}
+
+static inline void
+vmxnet3_inc_rx_consumption_counter(VMXNET3State *s, int qidx, int ridx)
+{
+    vmxnet3_ring_inc(&s->rxq_descr[qidx].rx_ring[ridx]);
+}
+
+static inline void
+vmxnet3_inc_tx_completion_counter(VMXNET3State *s, int qidx)
+{
+    vmxnet3_ring_inc(&s->txq_descr[qidx].comp_ring);
+}
+
+static void
+vmxnet3_inc_rx_completion_counter(VMXNET3State *s, int qidx)
+{
+    vmxnet3_ring_inc(&s->rxq_descr[qidx].comp_ring);
+}
+
+static void
+vmxnet3_dec_rx_completion_counter(VMXNET3State *s, int qidx)
+{
+    vmxnet3_ring_dec(&s->rxq_descr[qidx].comp_ring);
+}
+
+static void vmxnet3_complete_packet(VMXNET3State *s, int qidx, uint32 tx_ridx)
+{
+    struct Vmxnet3_TxCompDesc txcq_descr;
+
+    VMXNET3_RING_DUMP(VMW_RIPRN, "TXC", qidx, &s->txq_descr[qidx].comp_ring);
+
+    txcq_descr.txdIdx = tx_ridx;
+    txcq_descr.gen = vmxnet3_ring_curr_gen(&s->txq_descr[qidx].comp_ring);
+
+    vmxnet3_ring_write_curr_cell(&s->txq_descr[qidx].comp_ring, &txcq_descr);
+
+    /* Flush changes in TX descriptor before changing the counter value */
+    smp_wmb();
+
+    vmxnet3_inc_tx_completion_counter(s, qidx);
+    vmxnet3_trigger_interrupt(s, s->txq_descr[qidx].intr_idx);
+}
+
+static bool
+vmxnet3_setup_tx_offloads(VMXNET3State *s)
+{
+    switch (s->offload_mode) {
+    case VMXNET3_OM_NONE:
+        vmxnet_tx_pkt_build_vheader(s->tx_pkt, false, false, 0);
+        break;
+
+    case VMXNET3_OM_CSUM:
+        vmxnet_tx_pkt_build_vheader(s->tx_pkt, false, true, 0);
+        VMW_PKPRN("L4 CSO requested\n");
+        break;
+
+    case VMXNET3_OM_TSO:
+        vmxnet_tx_pkt_build_vheader(s->tx_pkt, true, true,
+            s->cso_or_gso_size);
+        vmxnet_tx_pkt_update_ip_checksums(s->tx_pkt);
+        VMW_PKPRN("GSO offload requested.");
+        break;
+
+    default:
+        assert(false);
+        return false;
+    }
+
+    return true;
+}
+
+static void
+vmxnet3_tx_retrieve_metadata(VMXNET3State *s,
+                             const struct Vmxnet3_TxDesc *txd)
+{
+    s->offload_mode = txd->om;
+    s->cso_or_gso_size = txd->msscof;
+    s->tci = txd->tci;
+    s->needs_vlan = txd->ti;
+}
+
+typedef enum {
+    VMXNET3_PKT_STATUS_OK,
+    VMXNET3_PKT_STATUS_ERROR,
+    VMXNET3_PKT_STATUS_DISCARD,/* only for tx */
+    VMXNET3_PKT_STATUS_OUT_OF_BUF /* only for rx */
+} Vmxnet3PktStatus;
+
+static void
+vmxnet3_on_tx_done_update_stats(VMXNET3State *s, int qidx,
+    Vmxnet3PktStatus status)
+{
+    size_t tot_len = vmxnet_tx_pkt_get_total_len(s->tx_pkt);
+    struct UPT1_TxStats *stats = &s->txq_descr[qidx].txq_stats;
+
+    switch (status) {
+    case VMXNET3_PKT_STATUS_OK:
+        switch (vmxnet_tx_pkt_get_packet_type(s->tx_pkt)) {
+        case ETH_PKT_BCAST:
+            stats->bcastPktsTxOK++;
+            stats->bcastBytesTxOK += tot_len;
+            break;
+        case ETH_PKT_MCAST:
+            stats->mcastPktsTxOK++;
+            stats->mcastBytesTxOK += tot_len;
+            break;
+        case ETH_PKT_UCAST:
+            stats->ucastPktsTxOK++;
+            stats->ucastBytesTxOK += tot_len;
+            break;
+        default:
+            assert(false);
+        }
+
+        if (s->offload_mode == VMXNET3_OM_TSO) {
+            /*
+             * According to VMWARE headers this statistic is a number
+             * of packets after segmentation but since we don't have
+             * this information in QEMU model, the best we can do is to
+             * provide number of non-segmented packets
+             */
+            stats->TSOPktsTxOK++;
+            stats->TSOBytesTxOK += tot_len;
+        }
+        break;
+
+    case VMXNET3_PKT_STATUS_DISCARD:
+        stats->pktsTxDiscard++;
+        break;
+
+    case VMXNET3_PKT_STATUS_ERROR:
+        stats->pktsTxError++;
+        break;
+
+    default:
+        assert(false);
+    }
+}
+
+static void
+vmxnet3_on_rx_done_update_stats(VMXNET3State *s,
+                                int qidx,
+                                Vmxnet3PktStatus status)
+{
+    struct UPT1_RxStats *stats = &s->rxq_descr[qidx].rxq_stats;
+    size_t tot_len = vmxnet_rx_pkt_get_total_len(s->rx_pkt);
+
+    switch (status) {
+    case VMXNET3_PKT_STATUS_OUT_OF_BUF:
+        stats->pktsRxOutOfBuf++;
+        break;
+
+    case VMXNET3_PKT_STATUS_ERROR:
+        stats->pktsRxError++;
+        break;
+    case VMXNET3_PKT_STATUS_OK:
+        switch (vmxnet_rx_pkt_get_packet_type(s->rx_pkt)) {
+        case ETH_PKT_BCAST:
+            stats->bcastPktsRxOK++;
+            stats->bcastBytesRxOK += tot_len;
+            break;
+        case ETH_PKT_MCAST:
+            stats->mcastPktsRxOK++;
+            stats->mcastBytesRxOK += tot_len;
+            break;
+        case ETH_PKT_UCAST:
+            stats->ucastPktsRxOK++;
+            stats->ucastBytesRxOK += tot_len;
+            break;
+        default:
+            assert(false);
+        }
+
+        if (tot_len > s->mtu) {
+            stats->LROPktsRxOK++;
+            stats->LROBytesRxOK += tot_len;
+        }
+        break;
+    default:
+        assert(false);
+    }
+}
+
+static inline bool
+vmxnet3_pop_next_tx_descr(VMXNET3State *s,
+                          int qidx,
+                          struct Vmxnet3_TxDesc *txd,
+                          uint32_t *descr_idx)
+{
+    Vmxnet3Ring *ring = &s->txq_descr[qidx].tx_ring;
+
+    vmxnet3_ring_read_curr_cell(ring, txd);
+    if (txd->gen == vmxnet3_ring_curr_gen(ring)) {
+        /* Only read after generation field verification */
+        smp_rmb();
+        /* Re-read to be sure we got the latest version */
+        vmxnet3_ring_read_curr_cell(ring, txd);
+        VMXNET3_RING_DUMP(VMW_RIPRN, "TX", qidx, ring);
+        *descr_idx = vmxnet3_ring_curr_cell_idx(ring);
+        vmxnet3_inc_tx_consumption_counter(s, qidx);
+        return true;
+    }
+
+    return false;
+}
+
+static bool
+vmxnet3_send_packet(VMXNET3State *s, uint32_t qidx)
+{
+    Vmxnet3PktStatus status = VMXNET3_PKT_STATUS_OK;
+
+    if (!vmxnet3_setup_tx_offloads(s)) {
+        status = VMXNET3_PKT_STATUS_ERROR;
+        goto func_exit;
+    }
+
+    /* debug prints */
+    vmxnet3_dump_virt_hdr(vmxnet_tx_pkt_get_vhdr(s->tx_pkt));
+    vmxnet_tx_pkt_dump(s->tx_pkt);
+
+    if (!vmxnet_tx_pkt_send(s->tx_pkt, qemu_get_queue(s->nic))) {
+        status = VMXNET3_PKT_STATUS_DISCARD;
+        goto func_exit;
+    }
+
+func_exit:
+    vmxnet3_on_tx_done_update_stats(s, qidx, status);
+    return (status == VMXNET3_PKT_STATUS_OK);
+}
+
+static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx)
+{
+    struct Vmxnet3_TxDesc txd;
+    uint32_t txd_idx;
+    uint32_t data_len;
+    hwaddr data_pa;
+
+    for (;;) {
+        if (!vmxnet3_pop_next_tx_descr(s, qidx, &txd, &txd_idx)) {
+            break;
+        }
+
+        vmxnet3_dump_tx_descr(&txd);
+
+        if (!s->skip_current_tx_pkt) {
+            data_len = (txd.len > 0) ? txd.len : VMXNET3_MAX_TX_BUF_SIZE;
+            data_pa = le64_to_cpu(txd.addr);
+
+            if (!vmxnet_tx_pkt_add_raw_fragment(s->tx_pkt,
+                                                data_pa,
+                                                data_len)) {
+                s->skip_current_tx_pkt = true;
+            }
+        }
+
+        if (s->tx_sop) {
+            vmxnet3_tx_retrieve_metadata(s, &txd);
+            s->tx_sop = false;
+        }
+
+        if (txd.eop) {
+            if (!s->skip_current_tx_pkt) {
+                vmxnet_tx_pkt_parse(s->tx_pkt);
+
+                if (s->needs_vlan) {
+                    vmxnet_tx_pkt_setup_vlan_header(s->tx_pkt, s->tci);
+                }
+
+                vmxnet3_send_packet(s, qidx);
+            } else {
+                vmxnet3_on_tx_done_update_stats(s, qidx,
+                                                VMXNET3_PKT_STATUS_ERROR);
+            }
+
+            vmxnet3_complete_packet(s, qidx, txd_idx);
+            s->tx_sop = true;
+            s->skip_current_tx_pkt = false;
+            vmxnet_tx_pkt_reset(s->tx_pkt);
+        }
+    }
+}
+
+static inline void
+vmxnet3_read_next_rx_descr(VMXNET3State *s, int qidx, int ridx,
+                           struct Vmxnet3_RxDesc *dbuf, uint32_t *didx)
+{
+    Vmxnet3Ring *ring = &s->rxq_descr[qidx].rx_ring[ridx];
+    *didx = vmxnet3_ring_curr_cell_idx(ring);
+    vmxnet3_ring_read_curr_cell(ring, dbuf);
+}
+
+static inline uint8_t
+vmxnet3_get_rx_ring_gen(VMXNET3State *s, int qidx, int ridx)
+{
+    return s->rxq_descr[qidx].rx_ring[ridx].gen;
+}
+
+static inline hwaddr
+vmxnet3_pop_rxc_descr(VMXNET3State *s, int qidx, uint32_t *descr_gen)
+{
+    uint8_t ring_gen;
+    struct Vmxnet3_RxCompDesc rxcd;
+
+    hwaddr daddr =
+        vmxnet3_ring_curr_cell_pa(&s->rxq_descr[qidx].comp_ring);
+
+    cpu_physical_memory_read(daddr, &rxcd, sizeof(struct Vmxnet3_RxCompDesc));
+    ring_gen = vmxnet3_ring_curr_gen(&s->rxq_descr[qidx].comp_ring);
+
+    if (rxcd.gen != ring_gen) {
+        *descr_gen = ring_gen;
+        vmxnet3_inc_rx_completion_counter(s, qidx);
+        return daddr;
+    }
+
+    return 0;
+}
+
+static inline void
+vmxnet3_revert_rxc_descr(VMXNET3State *s, int qidx)
+{
+    vmxnet3_dec_rx_completion_counter(s, qidx);
+}
+
+#define RXQ_IDX      (0)
+#define RX_HEAD_BODY_RING (0)
+#define RX_BODY_ONLY_RING (1)
+
+static bool
+vmxnet3_get_next_head_rx_descr(VMXNET3State *s,
+                               struct Vmxnet3_RxDesc *descr_buf,
+                               uint32_t *descr_idx,
+                               uint32_t *ridx)
+{
+    for (;;) {
+        uint32_t ring_gen;
+        vmxnet3_read_next_rx_descr(s, RXQ_IDX, RX_HEAD_BODY_RING,
+                                   descr_buf, descr_idx);
+
+        /* If no more free descriptors - return */
+        ring_gen = vmxnet3_get_rx_ring_gen(s, RXQ_IDX, RX_HEAD_BODY_RING);
+        if (descr_buf->gen != ring_gen) {
+            return false;
+        }
+
+        /* Only read after generation field verification */
+        smp_rmb();
+        /* Re-read to be sure we got the latest version */
+        vmxnet3_read_next_rx_descr(s, RXQ_IDX, RX_HEAD_BODY_RING,
+                                   descr_buf, descr_idx);
+
+        /* Mark current descriptor as used/skipped */
+        vmxnet3_inc_rx_consumption_counter(s, RXQ_IDX, RX_HEAD_BODY_RING);
+
+        /* If this is what we are looking for - return */
+        if (descr_buf->btype == VMXNET3_RXD_BTYPE_HEAD) {
+            *ridx = RX_HEAD_BODY_RING;
+            return true;
+        }
+    }
+}
+
+static bool
+vmxnet3_get_next_body_rx_descr(VMXNET3State *s,
+                               struct Vmxnet3_RxDesc *d,
+                               uint32_t *didx,
+                               uint32_t *ridx)
+{
+    vmxnet3_read_next_rx_descr(s, RXQ_IDX, RX_HEAD_BODY_RING, d, didx);
+
+    /* Try to find corresponding descriptor in head/body ring */
+    if (d->gen == vmxnet3_get_rx_ring_gen(s, RXQ_IDX, RX_HEAD_BODY_RING)) {
+        /* Only read after generation field verification */
+        smp_rmb();
+        /* Re-read to be sure we got the latest version */
+        vmxnet3_read_next_rx_descr(s, RXQ_IDX, RX_HEAD_BODY_RING, d, didx);
+        if (d->btype == VMXNET3_RXD_BTYPE_BODY) {
+            vmxnet3_inc_rx_consumption_counter(s, RXQ_IDX, RX_HEAD_BODY_RING);
+            *ridx = RX_HEAD_BODY_RING;
+            return true;
+        }
+    }
+
+    /*
+     * If there is no free descriptors on head/body ring or next free
+     * descriptor is a head descriptor switch to body only ring
+     */
+    vmxnet3_read_next_rx_descr(s, RXQ_IDX, RX_BODY_ONLY_RING, d, didx);
+
+    /* If no more free descriptors - return */
+    if (d->gen == vmxnet3_get_rx_ring_gen(s, RXQ_IDX, RX_BODY_ONLY_RING)) {
+        /* Only read after generation field verification */
+        smp_rmb();
+        /* Re-read to be sure we got the latest version */
+        vmxnet3_read_next_rx_descr(s, RXQ_IDX, RX_BODY_ONLY_RING, d, didx);
+        assert(d->btype == VMXNET3_RXD_BTYPE_BODY);
+        *ridx = RX_BODY_ONLY_RING;
+        vmxnet3_inc_rx_consumption_counter(s, RXQ_IDX, RX_BODY_ONLY_RING);
+        return true;
+    }
+
+    return false;
+}
+
+static inline bool
+vmxnet3_get_next_rx_descr(VMXNET3State *s, bool is_head,
+                          struct Vmxnet3_RxDesc *descr_buf,
+                          uint32_t *descr_idx,
+                          uint32_t *ridx)
+{
+    if (is_head || !s->rx_packets_compound) {
+        return vmxnet3_get_next_head_rx_descr(s, descr_buf, descr_idx, ridx);
+    } else {
+        return vmxnet3_get_next_body_rx_descr(s, descr_buf, descr_idx, ridx);
+    }
+}
+
+static void vmxnet3_rx_update_descr(struct VmxnetRxPkt *pkt,
+    struct Vmxnet3_RxCompDesc *rxcd)
+{
+    int csum_ok, is_gso;
+    bool isip4, isip6, istcp, isudp;
+    struct virtio_net_hdr *vhdr;
+    uint8_t offload_type;
+
+    if (vmxnet_rx_pkt_is_vlan_stripped(pkt)) {
+        rxcd->ts = 1;
+        rxcd->tci = vmxnet_rx_pkt_get_vlan_tag(pkt);
+    }
+
+    if (!vmxnet_rx_pkt_has_virt_hdr(pkt)) {
+        goto nocsum;
+    }
+
+    vhdr = vmxnet_rx_pkt_get_vhdr(pkt);
+    /*
+     * Checksum is valid when lower level tell so or when lower level
+     * requires checksum offload telling that packet produced/bridged
+     * locally and did travel over network after last checksum calculation
+     * or production
+     */
+    csum_ok = VMXNET_FLAG_IS_SET(vhdr->flags, VIRTIO_NET_HDR_F_DATA_VALID) ||
+              VMXNET_FLAG_IS_SET(vhdr->flags, VIRTIO_NET_HDR_F_NEEDS_CSUM);
+
+    offload_type = vhdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN;
+    is_gso = (offload_type != VIRTIO_NET_HDR_GSO_NONE) ? 1 : 0;
+
+    if (!csum_ok && !is_gso) {
+        goto nocsum;
+    }
+
+    vmxnet_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
+    if ((!istcp && !isudp) || (!isip4 && !isip6)) {
+        goto nocsum;
+    }
+
+    rxcd->cnc = 0;
+    rxcd->v4 = isip4 ? 1 : 0;
+    rxcd->v6 = isip6 ? 1 : 0;
+    rxcd->tcp = istcp ? 1 : 0;
+    rxcd->udp = isudp ? 1 : 0;
+    rxcd->fcs = rxcd->tuc = rxcd->ipc = 1;
+    return;
+
+nocsum:
+    rxcd->cnc = 1;
+    return;
+}
+
+static void
+vmxnet3_physical_memory_writev(const struct iovec *iov,
+                               size_t start_iov_off,
+                               hwaddr target_addr,
+                               size_t bytes_to_copy)
+{
+    size_t curr_off = 0;
+    size_t copied = 0;
+
+    while (bytes_to_copy) {
+        if (start_iov_off < (curr_off + iov->iov_len)) {
+            size_t chunk_len =
+                MIN((curr_off + iov->iov_len) - start_iov_off, bytes_to_copy);
+
+            cpu_physical_memory_write(target_addr + copied,
+                                      iov->iov_base + start_iov_off - curr_off,
+                                      chunk_len);
+
+            copied += chunk_len;
+            start_iov_off += chunk_len;
+            curr_off = start_iov_off;
+            bytes_to_copy -= chunk_len;
+        } else {
+            curr_off += iov->iov_len;
+        }
+        iov++;
+    }
+}
+
+static bool
+vmxnet3_indicate_packet(VMXNET3State *s)
+{
+    struct Vmxnet3_RxDesc rxd;
+    bool is_head = true;
+    uint32_t rxd_idx;
+    uint32_t rx_ridx;
+
+    struct Vmxnet3_RxCompDesc rxcd;
+    uint32_t new_rxcd_gen = VMXNET3_INIT_GEN;
+    hwaddr new_rxcd_pa = 0;
+    hwaddr ready_rxcd_pa = 0;
+    struct iovec *data = vmxnet_rx_pkt_get_iovec(s->rx_pkt);
+    size_t bytes_copied = 0;
+    size_t bytes_left = vmxnet_rx_pkt_get_total_len(s->rx_pkt);
+    uint16_t num_frags = 0;
+    size_t chunk_size;
+
+    vmxnet_rx_pkt_dump(s->rx_pkt);
+
+    while (bytes_left > 0) {
+
+        /* cannot add more frags to packet */
+        if (num_frags == s->max_rx_frags) {
+            break;
+        }
+
+        new_rxcd_pa = vmxnet3_pop_rxc_descr(s, RXQ_IDX, &new_rxcd_gen);
+        if (!new_rxcd_pa) {
+            break;
+        }
+
+        if (!vmxnet3_get_next_rx_descr(s, is_head, &rxd, &rxd_idx, &rx_ridx)) {
+            break;
+        }
+
+        chunk_size = MIN(bytes_left, rxd.len);
+        vmxnet3_physical_memory_writev(data, bytes_copied,
+                                       le64_to_cpu(rxd.addr), chunk_size);
+        bytes_copied += chunk_size;
+        bytes_left -= chunk_size;
+
+        vmxnet3_dump_rx_descr(&rxd);
+
+        if (0 != ready_rxcd_pa) {
+            cpu_physical_memory_write(ready_rxcd_pa, &rxcd, sizeof(rxcd));
+        }
+
+        memset(&rxcd, 0, sizeof(struct Vmxnet3_RxCompDesc));
+        rxcd.rxdIdx = rxd_idx;
+        rxcd.len = chunk_size;
+        rxcd.sop = is_head;
+        rxcd.gen = new_rxcd_gen;
+        rxcd.rqID = RXQ_IDX + rx_ridx * s->rxq_num;
+
+        if (0 == bytes_left) {
+            vmxnet3_rx_update_descr(s->rx_pkt, &rxcd);
+        }
+
+        VMW_RIPRN("RX Completion descriptor: rxRing: %lu rxIdx %lu len %lu "
+                  "sop %d csum_correct %lu",
+                  (unsigned long) rx_ridx,
+                  (unsigned long) rxcd.rxdIdx,
+                  (unsigned long) rxcd.len,
+                  (int) rxcd.sop,
+                  (unsigned long) rxcd.tuc);
+
+        is_head = false;
+        ready_rxcd_pa = new_rxcd_pa;
+        new_rxcd_pa = 0;
+    }
+
+    if (0 != ready_rxcd_pa) {
+        rxcd.eop = 1;
+        rxcd.err = (0 != bytes_left);
+        cpu_physical_memory_write(ready_rxcd_pa, &rxcd, sizeof(rxcd));
+
+        /* Flush RX descriptor changes */
+        smp_wmb();
+    }
+
+    if (0 != new_rxcd_pa) {
+        vmxnet3_revert_rxc_descr(s, RXQ_IDX);
+    }
+
+    vmxnet3_trigger_interrupt(s, s->rxq_descr[RXQ_IDX].intr_idx);
+
+    if (bytes_left == 0) {
+        vmxnet3_on_rx_done_update_stats(s, RXQ_IDX, VMXNET3_PKT_STATUS_OK);
+        return true;
+    } else if (num_frags == s->max_rx_frags) {
+        vmxnet3_on_rx_done_update_stats(s, RXQ_IDX, VMXNET3_PKT_STATUS_ERROR);
+        return false;
+    } else {
+        vmxnet3_on_rx_done_update_stats(s, RXQ_IDX,
+                                        VMXNET3_PKT_STATUS_OUT_OF_BUF);
+        return false;
+    }
+}
+
+static void
+vmxnet3_io_bar0_write(void *opaque, hwaddr addr,
+                      uint64_t val, unsigned size)
+{
+    VMXNET3State *s = opaque;
+
+    if (VMW_IS_MULTIREG_ADDR(addr, VMXNET3_REG_TXPROD,
+                        VMXNET3_DEVICE_MAX_TX_QUEUES, VMXNET3_REG_ALIGN)) {
+        int tx_queue_idx =
+            VMW_MULTIREG_IDX_BY_ADDR(addr, VMXNET3_REG_TXPROD,
+                                     VMXNET3_REG_ALIGN);
+        assert(tx_queue_idx <= s->txq_num);
+        vmxnet3_process_tx_queue(s, tx_queue_idx);
+        return;
+    }
+
+    if (VMW_IS_MULTIREG_ADDR(addr, VMXNET3_REG_IMR,
+                        VMXNET3_MAX_INTRS, VMXNET3_REG_ALIGN)) {
+        int l = VMW_MULTIREG_IDX_BY_ADDR(addr, VMXNET3_REG_IMR,
+                                         VMXNET3_REG_ALIGN);
+
+        VMW_CBPRN("Interrupt mask for line %d written: 0x%" PRIx64, l, val);
+
+        vmxnet3_on_interrupt_mask_changed(s, l, val);
+        return;
+    }
+
+    if (VMW_IS_MULTIREG_ADDR(addr, VMXNET3_REG_RXPROD,
+                        VMXNET3_DEVICE_MAX_RX_QUEUES, VMXNET3_REG_ALIGN) ||
+       VMW_IS_MULTIREG_ADDR(addr, VMXNET3_REG_RXPROD2,
+                        VMXNET3_DEVICE_MAX_RX_QUEUES, VMXNET3_REG_ALIGN)) {
+        return;
+    }
+
+    VMW_WRPRN("BAR0 unknown write [%" PRIx64 "] = %" PRIx64 ", size %d",
+              (uint64_t) addr, val, size);
+}
+
+static uint64_t
+vmxnet3_io_bar0_read(void *opaque, hwaddr addr, unsigned size)
+{
+    if (VMW_IS_MULTIREG_ADDR(addr, VMXNET3_REG_IMR,
+                        VMXNET3_MAX_INTRS, VMXNET3_REG_ALIGN)) {
+        assert(false);
+    }
+
+    VMW_CBPRN("BAR0 unknown read [%" PRIx64 "], size %d", addr, size);
+    return 0;
+}
+
+static void vmxnet3_reset_interrupt_states(VMXNET3State *s)
+{
+    int i;
+    for (i = 0; i < ARRAY_SIZE(s->interrupt_states); i++) {
+        s->interrupt_states[i].is_asserted = false;
+        s->interrupt_states[i].is_pending = false;
+        s->interrupt_states[i].is_masked = true;
+    }
+}
+
+static void vmxnet3_reset_mac(VMXNET3State *s)
+{
+    memcpy(&s->conf.macaddr.a, &s->perm_mac.a, sizeof(s->perm_mac.a));
+    VMW_CFPRN("MAC address set to: " VMXNET_MF, VMXNET_MA(s->conf.macaddr.a));
+}
+
+static void vmxnet3_deactivate_device(VMXNET3State *s)
+{
+    VMW_CBPRN("Deactivating vmxnet3...");
+    s->device_active = false;
+}
+
+static void vmxnet3_reset(VMXNET3State *s)
+{
+    VMW_CBPRN("Resetting vmxnet3...");
+
+    vmxnet3_deactivate_device(s);
+    vmxnet3_reset_interrupt_states(s);
+    vmxnet_tx_pkt_reset(s->tx_pkt);
+    s->drv_shmem = 0;
+    s->tx_sop = true;
+    s->skip_current_tx_pkt = false;
+}
+
+static void vmxnet3_update_rx_mode(VMXNET3State *s)
+{
+    s->rx_mode = VMXNET3_READ_DRV_SHARED32(s->drv_shmem,
+                                           devRead.rxFilterConf.rxMode);
+    VMW_CFPRN("RX mode: 0x%08X", s->rx_mode);
+}
+
+static void vmxnet3_update_vlan_filters(VMXNET3State *s)
+{
+    int i;
+
+    /* Copy configuration from shared memory */
+    VMXNET3_READ_DRV_SHARED(s->drv_shmem,
+                            devRead.rxFilterConf.vfTable,
+                            s->vlan_table,
+                            sizeof(s->vlan_table));
+
+    /* Invert byte order when needed */
+    for (i = 0; i < ARRAY_SIZE(s->vlan_table); i++) {
+        s->vlan_table[i] = le32_to_cpu(s->vlan_table[i]);
+    }
+
+    /* Dump configuration for debugging purposes */
+    VMW_CFPRN("Configured VLANs:");
+    for (i = 0; i < sizeof(s->vlan_table) * 8; i++) {
+        if (VMXNET3_VFTABLE_ENTRY_IS_SET(s->vlan_table, i)) {
+            VMW_CFPRN("\tVLAN %d is present", i);
+        }
+    }
+}
+
+static void vmxnet3_update_mcast_filters(VMXNET3State *s)
+{
+    uint16_t list_bytes =
+        VMXNET3_READ_DRV_SHARED16(s->drv_shmem,
+                                  devRead.rxFilterConf.mfTableLen);
+
+    s->mcast_list_len = list_bytes / sizeof(s->mcast_list[0]);
+
+    s->mcast_list = g_realloc(s->mcast_list, list_bytes);
+    if (NULL == s->mcast_list) {
+        if (0 == s->mcast_list_len) {
+            VMW_CFPRN("Current multicast list is empty");
+        } else {
+            VMW_ERPRN("Failed to allocate multicast list of %d elements",
+                      s->mcast_list_len);
+        }
+        s->mcast_list_len = 0;
+    } else {
+        int i;
+        hwaddr mcast_list_pa =
+            VMXNET3_READ_DRV_SHARED64(s->drv_shmem,
+                                      devRead.rxFilterConf.mfTablePA);
+
+        cpu_physical_memory_read(mcast_list_pa, s->mcast_list, list_bytes);
+        VMW_CFPRN("Current multicast list len is %d:", s->mcast_list_len);
+        for (i = 0; i < s->mcast_list_len; i++) {
+            VMW_CFPRN("\t" VMXNET_MF, VMXNET_MA(s->mcast_list[i].a));
+        }
+    }
+}
+
+static void vmxnet3_setup_rx_filtering(VMXNET3State *s)
+{
+    vmxnet3_update_rx_mode(s);
+    vmxnet3_update_vlan_filters(s);
+    vmxnet3_update_mcast_filters(s);
+}
+
+static uint32_t vmxnet3_get_interrupt_config(VMXNET3State *s)
+{
+    uint32_t interrupt_mode = VMXNET3_IT_AUTO | (VMXNET3_IMM_AUTO << 2);
+    VMW_CFPRN("Interrupt config is 0x%X", interrupt_mode);
+    return interrupt_mode;
+}
+
+static void vmxnet3_fill_stats(VMXNET3State *s)
+{
+    int i;
+    for (i = 0; i < s->txq_num; i++) {
+        cpu_physical_memory_write(s->txq_descr[i].tx_stats_pa,
+                                  &s->txq_descr[i].txq_stats,
+                                  sizeof(s->txq_descr[i].txq_stats));
+    }
+
+    for (i = 0; i < s->rxq_num; i++) {
+        cpu_physical_memory_write(s->rxq_descr[i].rx_stats_pa,
+                                  &s->rxq_descr[i].rxq_stats,
+                                  sizeof(s->rxq_descr[i].rxq_stats));
+    }
+}
+
+static void vmxnet3_adjust_by_guest_type(VMXNET3State *s)
+{
+    struct Vmxnet3_GOSInfo gos;
+
+    VMXNET3_READ_DRV_SHARED(s->drv_shmem, devRead.misc.driverInfo.gos,
+                            &gos, sizeof(gos));
+    s->rx_packets_compound =
+        (gos.gosType == VMXNET3_GOS_TYPE_WIN) ? false : true;
+
+    VMW_CFPRN("Guest type specifics: RXCOMPOUND: %d", s->rx_packets_compound);
+}
+
+static void
+vmxnet3_dump_conf_descr(const char *name,
+                        struct Vmxnet3_VariableLenConfDesc *pm_descr)
+{
+    VMW_CFPRN("%s descriptor dump: Version %u, Length %u",
+              name, pm_descr->confVer, pm_descr->confLen);
+
+};
+
+static void vmxnet3_update_pm_state(VMXNET3State *s)
+{
+    struct Vmxnet3_VariableLenConfDesc pm_descr;
+
+    pm_descr.confLen =
+        VMXNET3_READ_DRV_SHARED32(s->drv_shmem, devRead.pmConfDesc.confLen);
+    pm_descr.confVer =
+        VMXNET3_READ_DRV_SHARED32(s->drv_shmem, devRead.pmConfDesc.confVer);
+    pm_descr.confPA =
+        VMXNET3_READ_DRV_SHARED64(s->drv_shmem, devRead.pmConfDesc.confPA);
+
+    vmxnet3_dump_conf_descr("PM State", &pm_descr);
+}
+
+static void vmxnet3_update_features(VMXNET3State *s)
+{
+    uint32_t guest_features;
+    int rxcso_supported;
+
+    guest_features = VMXNET3_READ_DRV_SHARED32(s->drv_shmem,
+                                               devRead.misc.uptFeatures);
+
+    rxcso_supported = VMXNET_FLAG_IS_SET(guest_features, UPT1_F_RXCSUM);
+    s->rx_vlan_stripping = VMXNET_FLAG_IS_SET(guest_features, UPT1_F_RXVLAN);
+    s->lro_supported = VMXNET_FLAG_IS_SET(guest_features, UPT1_F_LRO);
+
+    VMW_CFPRN("Features configuration: LRO: %d, RXCSUM: %d, VLANSTRIP: %d",
+              s->lro_supported, rxcso_supported,
+              s->rx_vlan_stripping);
+    if (s->peer_has_vhdr) {
+        tap_set_offload(qemu_get_queue(s->nic)->peer,
+                        rxcso_supported,
+                        s->lro_supported,
+                        s->lro_supported,
+                        0,
+                        0);
+    }
+}
+
+static void vmxnet3_activate_device(VMXNET3State *s)
+{
+    int i;
+    static const uint32_t VMXNET3_DEF_TX_THRESHOLD = 1;
+    hwaddr qdescr_table_pa;
+    uint64_t pa;
+    uint32_t size;
+
+    /* Verify configuration consistency */
+    if (!vmxnet3_verify_driver_magic(s->drv_shmem)) {
+        VMW_ERPRN("Device configuration received from driver is invalid");
+        return;
+    }
+
+    vmxnet3_adjust_by_guest_type(s);
+    vmxnet3_update_features(s);
+    vmxnet3_update_pm_state(s);
+    vmxnet3_setup_rx_filtering(s);
+    /* Cache fields from shared memory */
+    s->mtu = VMXNET3_READ_DRV_SHARED32(s->drv_shmem, devRead.misc.mtu);
+    VMW_CFPRN("MTU is %u", s->mtu);
+
+    s->max_rx_frags =
+        VMXNET3_READ_DRV_SHARED16(s->drv_shmem, devRead.misc.maxNumRxSG);
+
+    VMW_CFPRN("Max RX fragments is %u", s->max_rx_frags);
+
+    s->event_int_idx =
+        VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.intrConf.eventIntrIdx);
+    VMW_CFPRN("Events interrupt line is %u", s->event_int_idx);
+
+    s->auto_int_masking =
+        VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.intrConf.autoMask);
+    VMW_CFPRN("Automatic interrupt masking is %d", (int)s->auto_int_masking);
+
+    s->txq_num =
+        VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.misc.numTxQueues);
+    s->rxq_num =
+        VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.misc.numRxQueues);
+
+    VMW_CFPRN("Number of TX/RX queues %u/%u", s->txq_num, s->rxq_num);
+    assert(s->txq_num <= VMXNET3_DEVICE_MAX_TX_QUEUES);
+
+    qdescr_table_pa =
+        VMXNET3_READ_DRV_SHARED64(s->drv_shmem, devRead.misc.queueDescPA);
+    VMW_CFPRN("TX queues descriptors table is at 0x%" PRIx64, qdescr_table_pa);
+
+    /*
+     * Worst-case scenario is a packet that holds all TX rings space so
+     * we calculate total size of all TX rings for max TX fragments number
+     */
+    s->max_tx_frags = 0;
+
+    /* TX queues */
+    for (i = 0; i < s->txq_num; i++) {
+        hwaddr qdescr_pa =
+            qdescr_table_pa + i * sizeof(struct Vmxnet3_TxQueueDesc);
+
+        /* Read interrupt number for this TX queue */
+        s->txq_descr[i].intr_idx =
+            VMXNET3_READ_TX_QUEUE_DESCR8(qdescr_pa, conf.intrIdx);
+
+        VMW_CFPRN("TX Queue %d interrupt: %d", i, s->txq_descr[i].intr_idx);
+
+        /* Read rings memory locations for TX queues */
+        pa = VMXNET3_READ_TX_QUEUE_DESCR64(qdescr_pa, conf.txRingBasePA);
+        size = VMXNET3_READ_TX_QUEUE_DESCR32(qdescr_pa, conf.txRingSize);
+
+        vmxnet3_ring_init(&s->txq_descr[i].tx_ring, pa, size,
+                          sizeof(struct Vmxnet3_TxDesc), false);
+        VMXNET3_RING_DUMP(VMW_CFPRN, "TX", i, &s->txq_descr[i].tx_ring);
+
+        s->max_tx_frags += size;
+
+        /* TXC ring */
+        pa = VMXNET3_READ_TX_QUEUE_DESCR64(qdescr_pa, conf.compRingBasePA);
+        size = VMXNET3_READ_TX_QUEUE_DESCR32(qdescr_pa, conf.compRingSize);
+        vmxnet3_ring_init(&s->txq_descr[i].comp_ring, pa, size,
+                          sizeof(struct Vmxnet3_TxCompDesc), true);
+        VMXNET3_RING_DUMP(VMW_CFPRN, "TXC", i, &s->txq_descr[i].comp_ring);
+
+        s->txq_descr[i].tx_stats_pa =
+            qdescr_pa + offsetof(struct Vmxnet3_TxQueueDesc, stats);
+
+        memset(&s->txq_descr[i].txq_stats, 0,
+               sizeof(s->txq_descr[i].txq_stats));
+
+        /* Fill device-managed parameters for queues */
+        VMXNET3_WRITE_TX_QUEUE_DESCR32(qdescr_pa,
+                                       ctrl.txThreshold,
+                                       VMXNET3_DEF_TX_THRESHOLD);
+    }
+
+    /* Preallocate TX packet wrapper */
+    VMW_CFPRN("Max TX fragments is %u", s->max_tx_frags);
+    vmxnet_tx_pkt_init(&s->tx_pkt, s->max_tx_frags, s->peer_has_vhdr);
+    vmxnet_rx_pkt_init(&s->rx_pkt, s->peer_has_vhdr);
+
+    /* Read rings memory locations for RX queues */
+    for (i = 0; i < s->rxq_num; i++) {
+        int j;
+        hwaddr qd_pa =
+            qdescr_table_pa + s->txq_num * sizeof(struct Vmxnet3_TxQueueDesc) +
+            i * sizeof(struct Vmxnet3_RxQueueDesc);
+
+        /* Read interrupt number for this RX queue */
+        s->rxq_descr[i].intr_idx =
+            VMXNET3_READ_TX_QUEUE_DESCR8(qd_pa, conf.intrIdx);
+
+        VMW_CFPRN("RX Queue %d interrupt: %d", i, s->rxq_descr[i].intr_idx);
+
+        /* Read rings memory locations */
+        for (j = 0; j < VMXNET3_RX_RINGS_PER_QUEUE; j++) {
+            /* RX rings */
+            pa = VMXNET3_READ_RX_QUEUE_DESCR64(qd_pa, conf.rxRingBasePA[j]);
+            size = VMXNET3_READ_RX_QUEUE_DESCR32(qd_pa, conf.rxRingSize[j]);
+            vmxnet3_ring_init(&s->rxq_descr[i].rx_ring[j], pa, size,
+                              sizeof(struct Vmxnet3_RxDesc), false);
+            VMW_CFPRN("RX queue %d:%d: Base: %" PRIx64 ", Size: %d",
+                      i, j, pa, size);
+        }
+
+        /* RXC ring */
+        pa = VMXNET3_READ_RX_QUEUE_DESCR64(qd_pa, conf.compRingBasePA);
+        size = VMXNET3_READ_RX_QUEUE_DESCR32(qd_pa, conf.compRingSize);
+        vmxnet3_ring_init(&s->rxq_descr[i].comp_ring, pa, size,
+                          sizeof(struct Vmxnet3_RxCompDesc), true);
+        VMW_CFPRN("RXC queue %d: Base: %" PRIx64 ", Size: %d", i, pa, size);
+
+        s->rxq_descr[i].rx_stats_pa =
+            qd_pa + offsetof(struct Vmxnet3_RxQueueDesc, stats);
+        memset(&s->rxq_descr[i].rxq_stats, 0,
+               sizeof(s->rxq_descr[i].rxq_stats));
+    }
+
+    /* Make sure everything is in place before device activation */
+    smp_wmb();
+
+    vmxnet3_reset_mac(s);
+
+    s->device_active = true;
+}
+
+static void vmxnet3_handle_command(VMXNET3State *s, uint64_t cmd)
+{
+    s->last_command = cmd;
+
+    switch (cmd) {
+    case VMXNET3_CMD_GET_PERM_MAC_HI:
+        VMW_CBPRN("Set: Get upper part of permanent MAC");
+        break;
+
+    case VMXNET3_CMD_GET_PERM_MAC_LO:
+        VMW_CBPRN("Set: Get lower part of permanent MAC");
+        break;
+
+    case VMXNET3_CMD_GET_STATS:
+        VMW_CBPRN("Set: Get device statistics");
+        vmxnet3_fill_stats(s);
+        break;
+
+    case VMXNET3_CMD_ACTIVATE_DEV:
+        VMW_CBPRN("Set: Activating vmxnet3 device");
+        vmxnet3_activate_device(s);
+        break;
+
+    case VMXNET3_CMD_UPDATE_RX_MODE:
+        VMW_CBPRN("Set: Update rx mode");
+        vmxnet3_update_rx_mode(s);
+        break;
+
+    case VMXNET3_CMD_UPDATE_VLAN_FILTERS:
+        VMW_CBPRN("Set: Update VLAN filters");
+        vmxnet3_update_vlan_filters(s);
+        break;
+
+    case VMXNET3_CMD_UPDATE_MAC_FILTERS:
+        VMW_CBPRN("Set: Update MAC filters");
+        vmxnet3_update_mcast_filters(s);
+        break;
+
+    case VMXNET3_CMD_UPDATE_FEATURE:
+        VMW_CBPRN("Set: Update features");
+        vmxnet3_update_features(s);
+        break;
+
+    case VMXNET3_CMD_UPDATE_PMCFG:
+        VMW_CBPRN("Set: Update power management config");
+        vmxnet3_update_pm_state(s);
+        break;
+
+    case VMXNET3_CMD_GET_LINK:
+        VMW_CBPRN("Set: Get link");
+        break;
+
+    case VMXNET3_CMD_RESET_DEV:
+        VMW_CBPRN("Set: Reset device");
+        vmxnet3_reset(s);
+        break;
+
+    case VMXNET3_CMD_QUIESCE_DEV:
+        VMW_CBPRN("Set: VMXNET3_CMD_QUIESCE_DEV - pause the device");
+        vmxnet3_deactivate_device(s);
+        break;
+
+    case VMXNET3_CMD_GET_CONF_INTR:
+        VMW_CBPRN("Set: VMXNET3_CMD_GET_CONF_INTR - interrupt configuration");
+        break;
+
+    default:
+        VMW_CBPRN("Received unknown command: %" PRIx64, cmd);
+        break;
+    }
+}
+
+static uint64_t vmxnet3_get_command_status(VMXNET3State *s)
+{
+    uint64_t ret;
+
+    switch (s->last_command) {
+    case VMXNET3_CMD_ACTIVATE_DEV:
+        ret = (s->device_active) ? 0 : -1;
+        VMW_CFPRN("Device active: %" PRIx64, ret);
+        break;
+
+    case VMXNET3_CMD_GET_LINK:
+        ret = s->link_status_and_speed;
+        VMW_CFPRN("Link and speed: %" PRIx64, ret);
+        break;
+
+    case VMXNET3_CMD_GET_PERM_MAC_LO:
+        ret = vmxnet3_get_mac_low(&s->perm_mac);
+        break;
+
+    case VMXNET3_CMD_GET_PERM_MAC_HI:
+        ret = vmxnet3_get_mac_high(&s->perm_mac);
+        break;
+
+    case VMXNET3_CMD_GET_CONF_INTR:
+        ret = vmxnet3_get_interrupt_config(s);
+        break;
+
+    default:
+        VMW_WRPRN("Received request for unknown command: %x", s->last_command);
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
+static void vmxnet3_set_events(VMXNET3State *s, uint32_t val)
+{
+    uint32_t events;
+
+    VMW_CBPRN("Setting events: 0x%x", val);
+    events = VMXNET3_READ_DRV_SHARED32(s->drv_shmem, ecr) | val;
+    VMXNET3_WRITE_DRV_SHARED32(s->drv_shmem, ecr, events);
+}
+
+static void vmxnet3_ack_events(VMXNET3State *s, uint32_t val)
+{
+    uint32_t events;
+
+    VMW_CBPRN("Clearing events: 0x%x", val);
+    events = VMXNET3_READ_DRV_SHARED32(s->drv_shmem, ecr) & ~val;
+    VMXNET3_WRITE_DRV_SHARED32(s->drv_shmem, ecr, events);
+}
+
+static void
+vmxnet3_io_bar1_write(void *opaque,
+                      hwaddr addr,
+                      uint64_t val,
+                      unsigned size)
+{
+    VMXNET3State *s = opaque;
+
+    switch (addr) {
+    /* Vmxnet3 Revision Report Selection */
+    case VMXNET3_REG_VRRS:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_VRRS] = %" PRIx64 ", size %d",
+                  val, size);
+        break;
+
+    /* UPT Version Report Selection */
+    case VMXNET3_REG_UVRS:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_UVRS] = %" PRIx64 ", size %d",
+                  val, size);
+        break;
+
+    /* Driver Shared Address Low */
+    case VMXNET3_REG_DSAL:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_DSAL] = %" PRIx64 ", size %d",
+                  val, size);
+        /*
+         * Guest driver will first write the low part of the shared
+         * memory address. We save it to temp variable and set the
+         * shared address only after we get the high part
+         */
+        if (0 == val) {
+            s->device_active = false;
+        }
+        s->temp_shared_guest_driver_memory = val;
+        s->drv_shmem = 0;
+        break;
+
+    /* Driver Shared Address High */
+    case VMXNET3_REG_DSAH:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_DSAH] = %" PRIx64 ", size %d",
+                  val, size);
+        /*
+         * Set the shared memory between guest driver and device.
+         * We already should have low address part.
+         */
+        s->drv_shmem = s->temp_shared_guest_driver_memory | (val << 32);
+        break;
+
+    /* Command */
+    case VMXNET3_REG_CMD:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_CMD] = %" PRIx64 ", size %d",
+                  val, size);
+        vmxnet3_handle_command(s, val);
+        break;
+
+    /* MAC Address Low */
+    case VMXNET3_REG_MACL:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_MACL] = %" PRIx64 ", size %d",
+                  val, size);
+        s->temp_mac = val;
+        break;
+
+    /* MAC Address High */
+    case VMXNET3_REG_MACH:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_MACH] = %" PRIx64 ", size %d",
+                  val, size);
+        vmxnet3_set_variable_mac(s, val, s->temp_mac);
+        break;
+
+    /* Interrupt Cause Register */
+    case VMXNET3_REG_ICR:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_ICR] = %" PRIx64 ", size %d",
+                  val, size);
+        assert(false);
+        break;
+
+    /* Event Cause Register */
+    case VMXNET3_REG_ECR:
+        VMW_CBPRN("Write BAR1 [VMXNET3_REG_ECR] = %" PRIx64 ", size %d",
+                  val, size);
+        vmxnet3_ack_events(s, val);
+        break;
+
+    default:
+        VMW_CBPRN("Unknown Write to BAR1 [%" PRIx64 "] = %" PRIx64 ", size %d",
+                  addr, val, size);
+        break;
+    }
+}
+
+static uint64_t
+vmxnet3_io_bar1_read(void *opaque, hwaddr addr, unsigned size)
+{
+        VMXNET3State *s = opaque;
+        uint64_t ret = 0;
+
+        switch (addr) {
+        /* Vmxnet3 Revision Report Selection */
+        case VMXNET3_REG_VRRS:
+            VMW_CBPRN("Read BAR1 [VMXNET3_REG_VRRS], size %d", size);
+            ret = VMXNET3_DEVICE_REVISION;
+            break;
+
+        /* UPT Version Report Selection */
+        case VMXNET3_REG_UVRS:
+            VMW_CBPRN("Read BAR1 [VMXNET3_REG_UVRS], size %d", size);
+            ret = VMXNET3_DEVICE_VERSION;
+            break;
+
+        /* Command */
+        case VMXNET3_REG_CMD:
+            VMW_CBPRN("Read BAR1 [VMXNET3_REG_CMD], size %d", size);
+            ret = vmxnet3_get_command_status(s);
+            break;
+
+        /* MAC Address Low */
+        case VMXNET3_REG_MACL:
+            VMW_CBPRN("Read BAR1 [VMXNET3_REG_MACL], size %d", size);
+            ret = vmxnet3_get_mac_low(&s->conf.macaddr);
+            break;
+
+        /* MAC Address High */
+        case VMXNET3_REG_MACH:
+            VMW_CBPRN("Read BAR1 [VMXNET3_REG_MACH], size %d", size);
+            ret = vmxnet3_get_mac_high(&s->conf.macaddr);
+            break;
+
+        /*
+         * Interrupt Cause Register
+         * Used for legacy interrupts only so interrupt index always 0
+         */
+        case VMXNET3_REG_ICR:
+            VMW_CBPRN("Read BAR1 [VMXNET3_REG_ICR], size %d", size);
+            if (vmxnet3_interrupt_asserted(s, 0)) {
+                vmxnet3_clear_interrupt(s, 0);
+                ret = true;
+            } else {
+                ret = false;
+            }
+            break;
+
+        default:
+            VMW_CBPRN("Unknow read BAR1[%" PRIx64 "], %d bytes", addr, size);
+            break;
+        }
+
+        return ret;
+}
+
+static int
+vmxnet3_can_receive(NetClientState *nc)
+{
+    VMXNET3State *s = qemu_get_nic_opaque(nc);
+    return s->device_active &&
+           VMXNET_FLAG_IS_SET(s->link_status_and_speed, VMXNET3_LINK_STATUS_UP);
+}
+
+static inline bool
+vmxnet3_is_registered_vlan(VMXNET3State *s, const void *data)
+{
+    uint16_t vlan_tag = eth_get_pkt_tci(data) & VLAN_VID_MASK;
+    if (IS_SPECIAL_VLAN_ID(vlan_tag)) {
+        return true;
+    }
+
+    return VMXNET3_VFTABLE_ENTRY_IS_SET(s->vlan_table, vlan_tag);
+}
+
+static bool
+vmxnet3_is_allowed_mcast_group(VMXNET3State *s, const uint8_t *group_mac)
+{
+    int i;
+    for (i = 0; i < s->mcast_list_len; i++) {
+        if (!memcmp(group_mac, s->mcast_list[i].a, sizeof(s->mcast_list[i]))) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static bool
+vmxnet3_rx_filter_may_indicate(VMXNET3State *s, const void *data,
+    size_t size)
+{
+    struct eth_header *ehdr = PKT_GET_ETH_HDR(data);
+
+    if (VMXNET_FLAG_IS_SET(s->rx_mode, VMXNET3_RXM_PROMISC)) {
+        return true;
+    }
+
+    if (!vmxnet3_is_registered_vlan(s, data)) {
+        return false;
+    }
+
+    switch (vmxnet_rx_pkt_get_packet_type(s->rx_pkt)) {
+    case ETH_PKT_UCAST:
+        if (!VMXNET_FLAG_IS_SET(s->rx_mode, VMXNET3_RXM_UCAST)) {
+            return false;
+        }
+        if (memcmp(s->conf.macaddr.a, ehdr->h_dest, ETH_ALEN)) {
+            return false;
+        }
+        break;
+
+    case ETH_PKT_BCAST:
+        if (!VMXNET_FLAG_IS_SET(s->rx_mode, VMXNET3_RXM_BCAST)) {
+            return false;
+        }
+        break;
+
+    case ETH_PKT_MCAST:
+        if (VMXNET_FLAG_IS_SET(s->rx_mode, VMXNET3_RXM_ALL_MULTI)) {
+            return true;
+        }
+        if (!VMXNET_FLAG_IS_SET(s->rx_mode, VMXNET3_RXM_MCAST)) {
+            return false;
+        }
+        if (!vmxnet3_is_allowed_mcast_group(s, ehdr->h_dest)) {
+            return false;
+        }
+        break;
+
+    default:
+        assert(false);
+    }
+
+    return true;
+}
+
+static ssize_t
+vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size)
+{
+    VMXNET3State *s = qemu_get_nic_opaque(nc);
+    size_t bytes_indicated;
+
+    if (!vmxnet3_can_receive(nc)) {
+        VMW_PKPRN("Cannot receive now");
+        return -1;
+    }
+
+    if (s->peer_has_vhdr) {
+        vmxnet_rx_pkt_set_vhdr(s->rx_pkt, (struct virtio_net_hdr *)buf);
+        buf += sizeof(struct virtio_net_hdr);
+        size -= sizeof(struct virtio_net_hdr);
+    }
+
+    vmxnet_rx_pkt_set_packet_type(s->rx_pkt,
+        get_eth_packet_type(PKT_GET_ETH_HDR(buf)));
+
+    if (vmxnet3_rx_filter_may_indicate(s, buf, size)) {
+        vmxnet_rx_pkt_attach_data(s->rx_pkt, buf, size, s->rx_vlan_stripping);
+        bytes_indicated = vmxnet3_indicate_packet(s) ? size : -1;
+        if (bytes_indicated < size) {
+            VMW_PKPRN("RX: %lu of %lu bytes indicated", bytes_indicated, size);
+        }
+    } else {
+        VMW_PKPRN("Packet dropped by RX filter");
+        bytes_indicated = size;
+    }
+
+    assert(size > 0);
+    assert(bytes_indicated != 0);
+    return bytes_indicated;
+}
+
+static void vmxnet3_cleanup(NetClientState *nc)
+{
+    VMXNET3State *s = qemu_get_nic_opaque(nc);
+    s->nic = NULL;
+}
+
+static void vmxnet3_set_link_status(NetClientState *nc)
+{
+    VMXNET3State *s = qemu_get_nic_opaque(nc);
+
+    if (nc->link_down) {
+        s->link_status_and_speed &= ~VMXNET3_LINK_STATUS_UP;
+    } else {
+        s->link_status_and_speed |= VMXNET3_LINK_STATUS_UP;
+    }
+
+    vmxnet3_set_events(s, VMXNET3_ECR_LINK);
+    vmxnet3_trigger_interrupt(s, s->event_int_idx);
+}
+
+static NetClientInfo net_vmxnet3_info = {
+        .type = NET_CLIENT_OPTIONS_KIND_NIC,
+        .size = sizeof(NICState),
+        .can_receive = vmxnet3_