[Spice-commits] Branch 'kvm' - 1436 commits - .gitignore .gitmodules CODING_STYLE HACKING MAINTAINERS Makefile Makefile.objs Makefile.target QMP/README QMP/qmp-events.txt QMP/qmp-shell QMP/qmp.py QMP/vm-info VERSION alpha-dis.c arch_init.c arch_init.h arm-dis.c arm-semi.c audio/alsaaudio.c audio/audio.c audio/audio.h audio/audio_int.h audio/audio_pt_int.c audio/audio_template.h audio/dsoundaudio.c audio/esdaudio.c audio/fmodaudio.c audio/mixeng.c audio/mixeng.h audio/mixeng_template.h audio/noaudio.c audio/ossaudio.c audio/paaudio.c audio/spiceaudio.c audio/winwaveaudio.c balloon.c block-migration.c block.c block.h block/blkdebug.c block/blkverify.c block/cow.c block/nbd.c block/qcow.c block/qcow2-cache.c block/qcow2-cluster.c block/qcow2-refcount.c block/qcow2-snapshot.c block/qcow2.c block/qcow2.h block/qed-check.c block/qed-cluster.c block/qed-gencb.c block/qed-l2-cache.c block/qed-table.c block/qed.c block/qed.h block/raw-posix.c block/raw-win32.c block/raw.c block/rbd.c block/r bd_types.h block/sheepdog.c block/vdi.c block/vmdk.c block/vpc.c block/vvfat.c block_int.h blockdev.c blockdev.h bsd-user/bsdload.c bsd-user/elfload.c bsd-user/main.c bsd-user/qemu.h bswap.h buffered_file.c cache-utils.c cache-utils.h check-qjson.c cmd.h configure console.c console.h cpu-all.h cpu-common.h cpu-exec.c cpus.c cpus.h create_config cris-dis.c cutils.c darwin-user/machload.c darwin-user/qemu.h default-configs/arm-softmmu.mak default-configs/cris-softmmu.mak default-configs/i386-softmmu.mak default-configs/m68k-softmmu.mak default-configs/microblaze-softmmu.mak default-configs/mips-softmmu.mak default-configs/mips64-softmmu.mak default-configs/mips64el-softmmu.mak default-configs/mipsel-softmmu.mak default-configs/pci.mak default-configs/ppc-softmmu.mak default-configs/ppc64-softmmu.mak default-configs/ppcemb-softmmu.mak default-configs/s390x-softmmu.mak default-configs/sh4-softmmu.mak default-configs/sh4eb-softmmu.mak default-configs/sparc-softmmu.mak default-con figs/sparc64-softmmu.mak default-configs/x86_64-softmmu.mak dis-asm.h disas.c disas.h docs/blkverify.txt docs/bootindex.txt docs/migration.txt docs/qdev-device-use.txt docs/specs docs/tracing.txt dyngen-exec.h elf.h envlist.h exec-all.h exec.c feature_to_c.sh fpu/softfloat-native.c fpu/softfloat-native.h fpu/softfloat-specialize.h fpu/softfloat.c fpu/softfloat.h fsdev/qemu-fsdev.c fsdev/qemu-fsdev.h gdbstub.c gdbstub.h hmp-commands.hx hw/acpi.c hw/acpi_piix4.c hw/apb_pci.c hw/apic.c hw/arm_gic.c hw/arm_sysctl.c hw/arm_timer.c hw/armv7m.c hw/audiodev.h hw/axis_dev88.c hw/bonito.c hw/bt-sdp.c hw/cirrus_vga.c hw/cirrus_vga_rop.h hw/cirrus_vga_rop2.h hw/cs4231.c hw/cs4231a.c hw/cuda.c hw/dec_pci.c hw/device-assignment.c hw/device-assignment.h hw/device-hotplug.c hw/dp8393x.c hw/ds1225y.c hw/e1000.c hw/ecc.c hw/eccmemctl.c hw/eepro100.c hw/elf_ops.h hw/empty_slot.c hw/escc.c hw/esp.c hw/esp.h hw/etraxfs_dma.c hw/etraxfs_eth.c hw/etraxfs_pic.c hw/etraxfs_ser.c hw/etraxfs_timer.c h w/fdc.c hw/file-op-9p.h hw/flash.h hw/fmopl.c hw/fw_cfg.c hw/fw_cfg.h 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/hda-audio.c hw/heathrow_pic.c hw/hpet.c hw/hw.h hw/i8259.c hw/ide hw/ide.h hw/integratorcp.c hw/intel-hda-defs.h hw/intel-hda.c hw/intel-hda.h hw/ioapic.c hw/ioapic.h hw/ioh3420.c hw/ioh3420.h hw/ipf.c hw/isa-bus.c hw/isa.h hw/isa_mmio.c hw/ivshmem.c hw/jazz_led.c hw/lan9118.c hw/lance.c hw/leon3.c hw/loader.c hw/loader.h hw/lsi53c895a.c hw/m48t59.c hw/mac_dbdma.c hw/mac_nvram.c hw/mainstone.c hw/marvell_88w8618_audio.c hw/mc146818rtc.c hw/mcf5206.c hw/mcf5208.c hw/mcf_fec.c hw/mcf_intc.c hw/mcf_uart.c hw/mips.h hw/mips_fulong2e.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/mpcore.c hw/msi.c hw/msi.h hw/msix.c hw/msix.h hw/mst_fpga.c hw/multiboot.c hw/musicpal.c hw/ne2000-isa.c hw/ne2000.c hw/nseries.c hw/omap.h hw/omap1.c hw /omap2.c hw/omap_dma.c hw/omap_dss.c hw/omap_gpio.c hw/omap_gpmc.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_sx1.c hw/omap_uart.c hw/onenand.c hw/openpic.c hw/palm.c hw/parallel.c hw/pc.c hw/pc.h hw/pc_piix.c hw/pci-hotplug.c hw/pci-stub.c hw/pci.c hw/pci.h hw/pci_bridge.c hw/pci_bridge.h hw/pci_host.c hw/pci_host.h hw/pci_ids.h hw/pci_internals.h hw/pcie.c hw/pcie.h hw/pcie_aer.c hw/pcie_aer.h hw/pcie_host.c hw/pcie_port.c hw/pcie_port.h hw/pcie_regs.h hw/pckbd.c hw/pcnet-pci.c hw/pcnet.c hw/pcnet.h 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/pl050.c hw/pl061.c hw/pl080.c hw/pl110.c hw/pl181.c hw/pl190.c hw/ppc.c hw/ppc.h hw/ppc405_boards.c hw/ppc405_uc.c hw/ppc440.c hw/ppc4xx_devs.c hw/ppc4xx_pci.c hw/ppc_mac.h hw/ppc_newworld.c hw/ppc_oldworld.c hw/ppc_prep.c hw/ppce500_mpc8544ds.c hw/ppce500_pci.c hw/prep_pci.c hw/pxa.h 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/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/s390-virtio-bus.c hw/s390-virtio-bus.h hw/s390-virtio.c hw/sb16.c hw/sbi.c hw/scsi-bus.c hw/scsi-defs.h hw/scsi-disk.c hw/scsi-generic.c hw/scsi.h hw/sd.c hw/serial.c hw/sh7750.c hw/sh_intc.c hw/sh_pci.c hw/sh_pci.h hw/sh_serial.c hw/sh_timer.c hw/sharpsl.h hw/slavio_intctl.c hw/slavio_misc.c hw/slavio_timer.c hw/sm501.c hw/smc91c111.c hw/soc_dma.c hw/sparc32_dma.c hw/spitz.c hw/ssi-sd.c hw/stellaris.c hw/stellaris_enet.c hw/sun4c_intctl.c hw/sun4m.c hw/sun4m_iommu.c hw/sun4u.c hw/syborg_fb.c hw/syborg_interrupt.c hw/syborg_keyboard.c hw/syborg_pointer.c hw/syborg_rtc.c hw/syborg_serial.c hw/syborg_timer.c hw/syborg_virtio.c hw/sysbus.c hw/sysbus.h hw/tc6393xb.c hw/tc6393xb_template.h hw/tcx.c hw/testdev.c hw/tosa.c hw/tusb6010.c hw/unin_ pci.c hw/usb-bt.c hw/usb-bus.c hw/usb-desc.c hw/usb-desc.h hw/usb-hid.c hw/usb-hub.c hw/usb-msd.c hw/usb-musb.c hw/usb-net.c hw/usb-ohci.c hw/usb-serial.c hw/usb-uhci.c hw/usb-wacom.c hw/usb.c hw/usb.h hw/versatile_pci.c hw/versatilepb.c hw/vga-isa-mm.c hw/vga-pci.c hw/vga.c hw/vga_int.h hw/vhost.c hw/vhost.h hw/vhost_net.c hw/vhost_net.h hw/virtex_ml507.c hw/virtio-9p-debug.c hw/virtio-9p-debug.h hw/virtio-9p-local.c hw/virtio-9p-posix-acl.c hw/virtio-9p-xattr-user.c hw/virtio-9p-xattr.c hw/virtio-9p-xattr.h hw/virtio-9p.c hw/virtio-9p.h hw/virtio-balloon.c hw/virtio-blk.c hw/virtio-console.c hw/virtio-net.c hw/virtio-net.h hw/virtio-pci.c hw/virtio-serial-bus.c hw/virtio-serial.h hw/virtio.c hw/virtio.h hw/vmmouse.c hw/vmware_vga.c hw/watchdog.h hw/wdt_i6300esb.c hw/wdt_ib700.c hw/wm8750.c hw/xen_backend.h hw/xen_disk.c hw/xilinx_ethlite.c hw/xilinx_intc.c hw/xilinx_timer.c hw/xilinx_uartlite.c hw/xio3130_downstream.c hw/xio3130_downstream.h hw/xio3130_upstream.c hw/xio313 0_upstream.h hw/zaurus.c hxtool ioport.c ioport.h iorange.h json-parser.c kvm-all.c kvm-stub.c kvm-tpr-opt.c kvm.h kvm/doxygen.conf kvm/kvm_stat kvm/libkvm kvm/scripts linux-user/arm linux-user/elfload.c linux-user/flatload.c linux-user/ioctls.h linux-user/linuxload.c linux-user/m68k-sim.c linux-user/main.c linux-user/mips linux-user/mmap.c linux-user/ppc linux-user/qemu.h linux-user/signal.c linux-user/strace.c linux-user/strace.list linux-user/syscall.c linux-user/syscall_defs.h linux-user/syscall_types.h linux-user/target_flat.h m68k-dis.c m68k-semi.c microblaze-dis.c migration.c migration.h mips-dis.c monitor.c monitor.h nbd.c nbd.h net.c net.h net/socket.c net/tap-aix.c net/tap-bsd.c net/tap-haiku.c net/tap-linux.c net/tap-linux.h net/tap-solaris.c net/tap-win32.c net/tap.c net/tap.h os-posix.c os-win32.c osdep.c osdep.h oslib-posix.c oslib-win32.c path.c pc-bios/README pc-bios/bios.bin pc-bios/gpxe-eepro100-80861229.rom pc-bios/keymaps pc-bios/openbios-ppc pc-bios/open bios-sparc32 pc-bios/openbios-sparc64 pc-bios/optionrom pc-bios/vgabios-cirrus.bin pc-bios/vgabios-qxl.bin pc-bios/vgabios-stdvga.bin pc-bios/vgabios-vmware.bin pc-bios/vgabios.bin pc-bios/video.x pflib.c pflib.h posix-aio-compat.c qemu-binfmt-conf.sh qemu-char.c qemu-char.h qemu-common.h qemu-config.c qemu-config.h qemu-doc.texi qemu-error.h qemu-img-cmds.hx qemu-img.c qemu-img.texi qemu-io.c qemu-kvm-helper.c qemu-kvm-x86.c qemu-kvm.c qemu-kvm.h qemu-lock.h qemu-malloc.c qemu-monitor.hx qemu-nbd.c qemu-option.c qemu-options.hx qemu-os-posix.h qemu-os-win32.h qemu-tech.texi qemu-timer-common.c qemu-timer.c qemu-timer.h qemu-tool.c qemu_socket.h qerror.c qerror.h qjson.c qjson.h qmp-commands.hx range.h roms/seabios roms/vgabios rules.mak rwhandler.c rwhandler.h savevm.c scripts/checkpatch.pl scripts/create_config scripts/feature_to_c.sh scripts/hxtool scripts/make_device_config.sh scripts/qemu-binfmt-conf.sh scripts/signrom.sh scripts/simpletrace.py scripts/texi2pod.pl scrip ts/tracetool sh4-dis.c simpletrace.c simpletrace.h slirp/bootp.c slirp/ip_input.c slirp/misc.c slirp/slirp.c slirp/slirp.h slirp/slirp_config.h slirp/tftp.c spice-qemu-char.c sysemu.h target-alpha/helper.c target-alpha/op_helper.c target-arm/cpu.h target-arm/helper.c target-arm/helpers.h target-arm/neon_helper.c target-arm/op_helper.c target-arm/translate.c target-cris/cpu.h target-cris/exec.h target-cris/helper.c target-cris/mmu.c target-cris/op_helper.c target-cris/translate.c target-cris/translate_v10.c target-i386/cpu.h target-i386/cpuid.c target-i386/fake-exec.c target-i386/helper.c target-i386/kvm.c target-i386/kvm_x86.h target-i386/machine.c target-i386/op_helper.c target-i386/translate.c target-m68k/cpu.h target-m68k/helper.c target-m68k/translate.c target-microblaze/cpu.h target-microblaze/exec.h target-microblaze/helper.h target-microblaze/op_helper.c target-microblaze/translate.c target-mips/cpu.h target-mips/exec.h target-mips/helper.h target-mips/op_helper.c tar get-mips/translate.c target-mips/translate_init.c target-ppc/cpu.h target-ppc/exec.h target-ppc/helper.c target-ppc/kvm.c target-ppc/kvm_ppc.h target-ppc/op_helper.c target-ppc/translate.c target-ppc/translate_init.c target-s390x/cpu.h target-s390x/kvm.c target-s390x/translate.c target-sh4/cpu.h target-sh4/helper.c target-sh4/helper.h target-sh4/op_helper.c target-sh4/translate.c target-sparc/cpu.h target-sparc/helper.c target-sparc/helper.h target-sparc/op_helper.c target-sparc/translate.c tcg/README tcg/arm tcg/ia64 tcg/mips tcg/tcg-op.h tcg/tcg-opc.h tcg/tcg.c tcg/tcg.h tests/Makefile tests/cris tests/hello-i386.c tests/runcom.c tests/test-i386.c tests/test_path.c texi2pod.pl trace-events ui/cocoa.m ui/curses.c ui/curses_keys.h ui/d3des.h ui/qemu-spice.h ui/sdl.c ui/spice-core.c ui/spice-display.c ui/spice-display.h ui/spice-input.c ui/vnc-auth-sasl.c ui/vnc-enc-tight.c ui/vnc-jobs-async.c ui/vnc.c ui/vnc.h ui/x_keymap.h usb-bsd.c usb-linux.c version.rc vl.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Fri Jun 17 08:47:02 PDT 2011


 .gitignore                             |    6 
 .gitmodules                            |    2 
 CODING_STYLE                           |    6 
 HACKING                                |  125 +
 MAINTAINERS                            |  553 +++++-
 Makefile                               |  109 -
 Makefile.objs                          |   85 
 Makefile.target                        |   84 
 QMP/README                             |    9 
 QMP/qmp-events.txt                     |   66 
 QMP/qmp-shell                          |  254 ++
 QMP/qmp.py                             |  157 +
 QMP/vm-info                            |   33 
 VERSION                                |    2 
 alpha-dis.c                            |    3 
 arch_init.c                            |   85 
 arch_init.h                            |    1 
 arm-dis.c                              |   38 
 arm-semi.c                             |   79 
 audio/alsaaudio.c                      |   63 
 audio/audio.c                          |   38 
 audio/audio.h                          |    8 
 audio/audio_int.h                      |   11 
 audio/audio_pt_int.c                   |    3 
 audio/audio_template.h                 |    4 
 audio/dsoundaudio.c                    |    4 
 audio/esdaudio.c                       |    3 
 audio/fmodaudio.c                      |    4 
 audio/mixeng.c                         |   25 
 audio/mixeng.h                         |    4 
 audio/mixeng_template.h                |   39 
 audio/noaudio.c                        |    5 
 audio/ossaudio.c                       |   23 
 audio/paaudio.c                        |   44 
 audio/spiceaudio.c                     |  345 +++
 audio/winwaveaudio.c                   |    3 
 balloon.c                              |    2 
 block-migration.c                      |   95 +
 block.c                                |  378 +++-
 block.h                                |   16 
 block/blkdebug.c                       |    8 
 block/blkverify.c                      |  383 ++++
 block/cow.c                            |    4 
 block/nbd.c                            |   64 
 block/qcow.c                           |    5 
 block/qcow2-cache.c                    |  314 +++
 block/qcow2-cluster.c                  |  337 ++-
 block/qcow2-refcount.c                 |  276 +--
 block/qcow2-snapshot.c                 |   41 
 block/qcow2.c                          |  696 ++++---
 block/qcow2.h                          |   42 
 block/qed-check.c                      |  210 ++
 block/qed-cluster.c                    |  154 +
 block/qed-gencb.c                      |   32 
 block/qed-l2-cache.c                   |  173 +
 block/qed-table.c                      |  319 +++
 block/qed.c                            | 1365 +++++++++++++++
 block/qed.h                            |  301 +++
 block/raw-posix.c                      |  153 +
 block/raw-win32.c                      |   11 
 block/raw.c                            |  140 -
 block/rbd.c                            | 1059 ++++++++++++
 block/rbd_types.h                      |   71 
 block/sheepdog.c                       |   27 
 block/vdi.c                            |    9 
 block/vmdk.c                           |    5 
 block/vpc.c                            |   70 
 block/vvfat.c                          |   30 
 block_int.h                            |   22 
 blockdev.c                             |  371 +++-
 blockdev.h                             |   32 
 bsd-user/bsdload.c                     |    2 
 bsd-user/elfload.c                     |   37 
 bsd-user/main.c                        |    6 
 bsd-user/qemu.h                        |    3 
 bswap.h                                |   15 
 buffered_file.c                        |    9 
 cache-utils.c                          |    2 
 cache-utils.h                          |    2 
 check-qjson.c                          |    4 
 cmd.h                                  |   36 
 configure                              |  815 ++++++---
 console.c                              |   87 
 console.h                              |    4 
 cpu-all.h                              |   18 
 cpu-common.h                           |   15 
 cpu-exec.c                             |   12 
 cpus.c                                 |  169 +
 cpus.h                                 |    3 
 create_config                          |  103 -
 cris-dis.c                             |   13 
 cutils.c                               |  145 +
 darwin-user/machload.c                 |    2 
 darwin-user/qemu.h                     |    4 
 default-configs/arm-softmmu.mak        |    4 
 default-configs/cris-softmmu.mak       |    1 
 default-configs/i386-softmmu.mak       |    7 
 default-configs/m68k-softmmu.mak       |    2 
 default-configs/microblaze-softmmu.mak |    1 
 default-configs/mips-softmmu.mak       |    6 
 default-configs/mips64-softmmu.mak     |    6 
 default-configs/mips64el-softmmu.mak   |    6 
 default-configs/mipsel-softmmu.mak     |    6 
 default-configs/pci.mak                |   16 
 default-configs/ppc-softmmu.mak        |    8 
 default-configs/ppc64-softmmu.mak      |    8 
 default-configs/ppcemb-softmmu.mak     |    8 
 default-configs/s390x-softmmu.mak      |    1 
 default-configs/sh4-softmmu.mak        |    4 
 default-configs/sh4eb-softmmu.mak      |    4 
 default-configs/sparc-softmmu.mak      |    2 
 default-configs/sparc64-softmmu.mak    |    5 
 default-configs/x86_64-softmmu.mak     |    7 
 dev/null                               |binary
 dis-asm.h                              |   96 -
 disas.c                                |   17 
 disas.h                                |    3 
 docs/blkverify.txt                     |   69 
 docs/bootindex.txt                     |   43 
 docs/migration.txt                     |   56 
 docs/qdev-device-use.txt               |   21 
 docs/specs/acpi_pci_hotplug.txt        |   37 
 docs/specs/qed_spec.txt                |  130 +
 docs/tracing.txt                       |  189 ++
 dyngen-exec.h                          |   23 
 elf.h                                  |   19 
 envlist.h                              |   14 
 exec-all.h                             |   12 
 exec.c                                 |  216 ++
 feature_to_c.sh                        |   76 
 fpu/softfloat-native.c                 |    6 
 fpu/softfloat-native.h                 |    6 
 fpu/softfloat-specialize.h             |  436 +++-
 fpu/softfloat.c                        |  240 ++
 fpu/softfloat.h                        |   64 
 fsdev/qemu-fsdev.c                     |   57 
 fsdev/qemu-fsdev.h                     |    4 
 gdbstub.c                              |    7 
 gdbstub.h                              |    3 
 hmp-commands.hx                        | 1382 +++++++++++++++
 hw/acpi.c                              |   28 
 hw/acpi_piix4.c                        |  162 +
 hw/apb_pci.c                           |   65 
 hw/apic.c                              |   74 
 hw/arm_gic.c                           |    3 
 hw/arm_sysctl.c                        |   20 
 hw/arm_timer.c                         |    5 
 hw/armv7m.c                            |    2 
 hw/audiodev.h                          |    3 
 hw/axis_dev88.c                        |    6 
 hw/bonito.c                            |   19 
 hw/bt-sdp.c                            |   20 
 hw/cirrus_vga.c                        |  222 --
 hw/cirrus_vga_rop.h                    |   38 
 hw/cirrus_vga_rop2.h                   |   12 
 hw/cs4231.c                            |   23 
 hw/cs4231a.c                           |    1 
 hw/cuda.c                              |    3 
 hw/dec_pci.c                           |   52 
 hw/device-assignment.c                 |  697 +++++--
 hw/device-assignment.h                 |   20 
 hw/device-hotplug.c                    |    5 
 hw/dp8393x.c                           |    3 
 hw/ds1225y.c                           |    6 
 hw/e1000.c                             |   58 
 hw/ecc.c                               |   27 
 hw/eccmemctl.c                         |   52 
 hw/eepro100.c                          |   60 
 hw/elf_ops.h                           |    5 
 hw/empty_slot.c                        |    3 
 hw/escc.c                              |   11 
 hw/esp.c                               |   56 
 hw/esp.h                               |    3 
 hw/etraxfs_dma.c                       |    2 
 hw/etraxfs_eth.c                       |    3 
 hw/etraxfs_pic.c                       |    3 
 hw/etraxfs_ser.c                       |    3 
 hw/etraxfs_timer.c                     |    7 
 hw/fdc.c                               |   18 
 hw/file-op-9p.h                        |   44 
 hw/flash.h                             |    3 
 hw/fmopl.c                             |    6 
 hw/fw_cfg.c                            |   36 
 hw/fw_cfg.h                            |    4 
 hw/g364fb.c                            |    3 
 hw/grackle_pci.c                       |    6 
 hw/grlib.h                             |  126 +
 hw/grlib_apbuart.c                     |  187 ++
 hw/grlib_gptimer.c                     |  395 ++++
 hw/grlib_irqmp.c                       |  376 ++++
 hw/gt64xxx.c                           |  125 -
 hw/gumstix.c                           |    4 
 hw/gus.c                               |    4 
 hw/hda-audio.c                         |  926 ++++++++++
 hw/heathrow_pic.c                      |    5 
 hw/hpet.c                              |    3 
 hw/hw.h                                |   67 
 hw/i8259.c                             |    2 
 hw/ide.h                               |    2 
 hw/ide/ahci.c                          | 1152 +++++++++++++
 hw/ide/ahci.h                          |  333 +++
 hw/ide/cmd646.c                        |   26 
 hw/ide/core.c                          | 1232 ++++++-------
 hw/ide/ich.c                           |  148 +
 hw/ide/internal.h                      |   79 
 hw/ide/isa.c                           |    5 
 hw/ide/macio.c                         |    3 
 hw/ide/mmio.c                          |    6 
 hw/ide/pci.c                           |  378 +++-
 hw/ide/pci.h                           |   37 
 hw/ide/piix.c                          |   44 
 hw/ide/qdev.c                          |   22 
 hw/ide/via.c                           |   44 
 hw/integratorcp.c                      |    9 
 hw/intel-hda-defs.h                    |  717 ++++++++
 hw/intel-hda.c                         | 1308 ++++++++++++++
 hw/intel-hda.h                         |   62 
 hw/ioapic.c                            |  224 +-
 hw/ioapic.h                            |   20 
 hw/ioh3420.c                           |  246 ++
 hw/ioh3420.h                           |   10 
 hw/ipf.c                               |    6 
 hw/isa-bus.c                           |   53 
 hw/isa.h                               |    6 
 hw/isa_mmio.c                          |  100 -
 hw/ivshmem.c                           |   13 
 hw/jazz_led.c                          |    3 
 hw/lan9118.c                           |    7 
 hw/lance.c                             |   18 
 hw/leon3.c                             |  217 ++
 hw/loader.c                            |   37 
 hw/loader.h                            |    8 
 hw/lsi53c895a.c                        |   22 
 hw/m48t59.c                            |   15 
 hw/mac_dbdma.c                         |    6 
 hw/mac_nvram.c                         |    3 
 hw/mainstone.c                         |    3 
 hw/marvell_88w8618_audio.c             |    3 
 hw/mc146818rtc.c                       |   16 
 hw/mcf5206.c                           |    3 
 hw/mcf5208.c                           |    6 
 hw/mcf_fec.c                           |    3 
 hw/mcf_intc.c                          |    3 
 hw/mcf_uart.c                          |    3 
 hw/mips.h                              |    4 
 hw/mips_fulong2e.c                     |   23 
 hw/mips_jazz.c                         |   41 
 hw/mips_malta.c                        |   53 
 hw/mips_mipssim.c                      |    6 
 hw/mips_r4k.c                          |   12 
 hw/mips_timer.c                        |   44 
 hw/mipsnet.c                           |    2 
 hw/mpcore.c                            |    3 
 hw/msi.c                               |  344 +++
 hw/msi.h                               |   41 
 hw/msix.c                              |  237 +-
 hw/msix.h                              |    4 
 hw/mst_fpga.c                          |    2 
 hw/multiboot.c                         |   13 
 hw/musicpal.c                          |   24 
 hw/ne2000-isa.c                        |    3 
 hw/ne2000.c                            |    5 
 hw/nseries.c                           |    4 
 hw/omap.h                              |    9 
 hw/omap1.c                             |   59 
 hw/omap2.c                             |   10 
 hw/omap_dma.c                          |    4 
 hw/omap_dss.c                          |    2 
 hw/omap_gpio.c                         |    2 
 hw/omap_gpmc.c                         |    2 
 hw/omap_i2c.c                          |    7 
 hw/omap_intc.c                         |    4 
 hw/omap_l4.c                           |    5 
 hw/omap_lcdc.c                         |    2 
 hw/omap_mmc.c                          |    7 
 hw/omap_sdrc.c                         |    2 
 hw/omap_sx1.c                          |   15 
 hw/omap_uart.c                         |   14 
 hw/onenand.c                           |    3 
 hw/openpic.c                           |   31 
 hw/palm.c                              |   18 
 hw/parallel.c                          |    8 
 hw/pc.c                                |  162 +
 hw/pc.h                                |    6 
 hw/pc_piix.c                           |   55 
 hw/pci-hotplug.c                       |   27 
 hw/pci-stub.c                          |   50 
 hw/pci.c                               |  825 +++++----
 hw/pci.h                               |  204 +-
 hw/pci_bridge.c                        |  275 +++
 hw/pci_bridge.h                        |   66 
 hw/pci_host.c                          |  103 -
 hw/pci_host.h                          |    6 
 hw/pci_ids.h                           |    3 
 hw/pci_internals.h                     |   47 
 hw/pcie.c                              |  544 ++++++
 hw/pcie.h                              |  132 +
 hw/pcie_aer.c                          | 1031 +++++++++++
 hw/pcie_aer.h                          |  106 +
 hw/pcie_host.c                         |    3 
 hw/pcie_port.c                         |  124 +
 hw/pcie_port.h                         |   51 
 hw/pcie_regs.h                         |  156 +
 hw/pckbd.c                             |   23 
 hw/pcnet-pci.c                         |  346 +++
 hw/pcnet.c                             |  316 ---
 hw/pcnet.h                             |    3 
 hw/pflash_cfi01.c                      |    6 
 hw/pflash_cfi02.c                      |    4 
 hw/piix4.c                             |    1 
 hw/piix_pci.c                          |    8 
 hw/pl011.c                             |    3 
 hw/pl022.c                             |    3 
 hw/pl031.c                             |   28 
 hw/pl050.c                             |   38 
 hw/pl061.c                             |    3 
 hw/pl080.c                             |   61 
 hw/pl110.c                             |   47 
 hw/pl181.c                             |   11 
 hw/pl190.c                             |   41 
 hw/ppc.c                               |   27 
 hw/ppc.h                               |    4 
 hw/ppc405_boards.c                     |   34 
 hw/ppc405_uc.c                         |   44 
 hw/ppc440.c                            |    2 
 hw/ppc4xx_devs.c                       |    2 
 hw/ppc4xx_pci.c                        |   19 
 hw/ppc_mac.h                           |    1 
 hw/ppc_newworld.c                      |   52 
 hw/ppc_oldworld.c                      |  115 -
 hw/ppc_prep.c                          |   53 
 hw/ppce500_mpc8544ds.c                 |   15 
 hw/ppce500_pci.c                       |    9 
 hw/prep_pci.c                          |    3 
 hw/pxa.h                               |   10 
 hw/pxa2xx.c                            |   46 
 hw/pxa2xx_dma.c                        |    2 
 hw/pxa2xx_gpio.c                       |  150 -
 hw/pxa2xx_keypad.c                     |    2 
 hw/pxa2xx_lcd.c                        |    6 
 hw/pxa2xx_mmci.c                       |    2 
 hw/pxa2xx_pcmcia.c                     |    6 
 hw/pxa2xx_pic.c                        |    2 
 hw/pxa2xx_timer.c                      |    2 
 hw/qdev.c                              |  162 +
 hw/qdev.h                              |   38 
 hw/qxl-logger.c                        |  248 ++
 hw/qxl-render.c                        |  226 ++
 hw/qxl.c                               | 1531 +++++++++++++++++
 hw/qxl.h                               |  108 +
 hw/r2d.c                               |   34 
 hw/rc4030.c                            |   11 
 hw/realview.c                          |    3 
 hw/realview_gic.c                      |    3 
 hw/rtl8139.c                           |   47 
 hw/s390-virtio-bus.c                   |    8 
 hw/s390-virtio-bus.h                   |   19 
 hw/s390-virtio.c                       |    1 
 hw/sb16.c                              |    4 
 hw/sbi.c                               |    3 
 hw/scsi-bus.c                          |   46 
 hw/scsi-defs.h                         |   21 
 hw/scsi-disk.c                         |  456 +++--
 hw/scsi-generic.c                      |   49 
 hw/scsi.h                              |   15 
 hw/sd.c                                |   10 
 hw/serial.c                            |   33 
 hw/sh7750.c                            |   28 
 hw/sh_intc.c                           |    3 
 hw/sh_pci.c                            |  106 -
 hw/sh_pci.h                            |    9 
 hw/sh_serial.c                         |   62 
 hw/sh_timer.c                          |    3 
 hw/sharpsl.h                           |    7 
 hw/slavio_intctl.c                     |   51 
 hw/slavio_misc.c                       |   75 
 hw/slavio_timer.c                      |   52 
 hw/sm501.c                             |   61 
 hw/smc91c111.c                         |   33 
 hw/soc_dma.c                           |    5 
 hw/sparc32_dma.c                       |   84 
 hw/spitz.c                             |  351 ++-
 hw/ssi-sd.c                            |    7 
 hw/stellaris.c                         |   12 
 hw/stellaris_enet.c                    |    3 
 hw/sun4c_intctl.c                      |    3 
 hw/sun4m.c                             |   57 
 hw/sun4m_iommu.c                       |   36 
 hw/sun4u.c                             |    6 
 hw/syborg_fb.c                         |    3 
 hw/syborg_interrupt.c                  |    3 
 hw/syborg_keyboard.c                   |    3 
 hw/syborg_pointer.c                    |    3 
 hw/syborg_rtc.c                        |    3 
 hw/syborg_serial.c                     |    3 
 hw/syborg_timer.c                      |    3 
 hw/syborg_virtio.c                     |   11 
 hw/sysbus.c                            |   33 
 hw/sysbus.h                            |    9 
 hw/tc6393xb.c                          |    2 
 hw/tc6393xb_template.h                 |    2 
 hw/tcx.c                               |    5 
 hw/testdev.c                           |   19 
 hw/tosa.c                              |   35 
 hw/tusb6010.c                          |    2 
 hw/unin_pci.c                          |   26 
 hw/usb-bt.c                            |  525 ++---
 hw/usb-bus.c                           |  104 +
 hw/usb-desc.c                          |  406 ++++
 hw/usb-desc.h                          |   92 +
 hw/usb-hid.c                           |  808 ++++-----
 hw/usb-hub.c                           |  275 +--
 hw/usb-msd.c                           |  276 +--
 hw/usb-musb.c                          |   44 
 hw/usb-net.c                           |  531 ++----
 hw/usb-ohci.c                          |  100 -
 hw/usb-serial.c                        |  236 --
 hw/usb-uhci.c                          |   98 -
 hw/usb-wacom.c                         |  227 --
 hw/usb.c                               |   34 
 hw/usb.h                               |   59 
 hw/versatile_pci.c                     |   21 
 hw/versatilepb.c                       |   27 
 hw/vga-isa-mm.c                        |    6 
 hw/vga-pci.c                           |   45 
 hw/vga.c                               |   35 
 hw/vga_int.h                           |    4 
 hw/vhost.c                             |   68 
 hw/vhost.h                             |    4 
 hw/vhost_net.c                         |   50 
 hw/vhost_net.h                         |    3 
 hw/virtex_ml507.c                      |  276 +++
 hw/virtio-9p-debug.c                   |  193 +-
 hw/virtio-9p-debug.h                   |    1 
 hw/virtio-9p-local.c                   |  147 +
 hw/virtio-9p-posix-acl.c               |  140 +
 hw/virtio-9p-xattr-user.c              |  109 +
 hw/virtio-9p-xattr.c                   |  159 +
 hw/virtio-9p-xattr.h                   |  102 +
 hw/virtio-9p.c                         | 1973 +++++++++++++++++++---
 hw/virtio-9p.h                         |  261 ++
 hw/virtio-balloon.c                    |   12 
 hw/virtio-blk.c                        |   77 
 hw/virtio-console.c                    |   38 
 hw/virtio-net.c                        |  313 ++-
 hw/virtio-net.h                        |   14 
 hw/virtio-pci.c                        |  329 +++
 hw/virtio-serial-bus.c                 |  136 +
 hw/virtio-serial.h                     |   24 
 hw/virtio.c                            |  123 +
 hw/virtio.h                            |   14 
 hw/vmmouse.c                           |   31 
 hw/vmware_vga.c                        |   95 -
 hw/watchdog.h                          |    8 
 hw/wdt_i6300esb.c                      |   43 
 hw/wdt_ib700.c                         |   22 
 hw/wm8750.c                            |    5 
 hw/xen_backend.h                       |    2 
 hw/xen_disk.c                          |   29 
 hw/xilinx_ethlite.c                    |    2 
 hw/xilinx_intc.c                       |    2 
 hw/xilinx_timer.c                      |    3 
 hw/xilinx_uartlite.c                   |    3 
 hw/xio3130_downstream.c                |  211 ++
 hw/xio3130_downstream.h                |   11 
 hw/xio3130_upstream.c                  |  186 ++
 hw/xio3130_upstream.h                  |   10 
 hw/zaurus.c                            |  115 -
 hxtool                                 |  102 -
 ioport.c                               |   71 
 ioport.h                               |    2 
 iorange.h                              |   30 
 json-parser.c                          |    3 
 kvm-all.c                              |  353 ++--
 kvm-stub.c                             |   52 
 kvm-tpr-opt.c                          |   10 
 kvm.h                                  |   51 
 kvm/doxygen.conf                       | 1252 --------------
 kvm/kvm_stat                           |  313 +++
 kvm/libkvm/libkvm-x86.c                |   39 
 kvm/libkvm/libkvm.h                    |   30 
 kvm/scripts/make-release               |   22 
 linux-user/arm/nwfpe/fpa11.h           |    6 
 linux-user/arm/nwfpe/fpa11_cprt.c      |   14 
 linux-user/arm/nwfpe/fpopcode.h        |    4 
 linux-user/elfload.c                   |   79 
 linux-user/flatload.c                  |   41 
 linux-user/ioctls.h                    |    6 
 linux-user/linuxload.c                 |    2 
 linux-user/m68k-sim.c                  |    6 
 linux-user/main.c                      |   60 
 linux-user/mips/syscall_nr.h           |   38 
 linux-user/mmap.c                      |    6 
 linux-user/ppc/syscall_nr.h            |   30 
 linux-user/qemu.h                      |   18 
 linux-user/signal.c                    |  197 +-
 linux-user/strace.c                    |    6 
 linux-user/strace.list                 |    6 
 linux-user/syscall.c                   |  366 +++-
 linux-user/syscall_defs.h              |    4 
 linux-user/syscall_types.h             |   16 
 linux-user/target_flat.h               |   10 
 m68k-dis.c                             |    2 
 m68k-semi.c                            |    2 
 microblaze-dis.c                       |    2 
 migration.c                            |   44 
 migration.h                            |    5 
 mips-dis.c                             |    2 
 monitor.c                              | 1105 ++++++++++--
 monitor.h                              |   11 
 nbd.c                                  |  149 +
 nbd.h                                  |    7 
 net.c                                  |   69 
 net.h                                  |    5 
 net/socket.c                           |   53 
 net/tap-aix.c                          |    9 
 net/tap-bsd.c                          |   21 
 net/tap-haiku.c                        |   61 
 net/tap-linux.c                        |   42 
 net/tap-linux.h                        |    8 
 net/tap-solaris.c                      |    9 
 net/tap-win32.c                        |   14 
 net/tap.c                              |   62 
 net/tap.h                              |    4 
 os-posix.c                             |   53 
 os-win32.c                             |   30 
 osdep.c                                |  261 --
 osdep.h                                |   46 
 oslib-posix.c                          |  161 +
 oslib-win32.c                          |  121 +
 path.c                                 |   28 
 pc-bios/README                         |    8 
 pc-bios/bios.bin                       |binary
 pc-bios/keymaps/bepo                   |  333 +++
 pc-bios/openbios-ppc                   |binary
 pc-bios/openbios-sparc32               |binary
 pc-bios/openbios-sparc64               |binary
 pc-bios/optionrom/Makefile             |    2 
 pc-bios/optionrom/signrom.sh           |   46 
 pc-bios/optionrom/vapic.S              |   15 
 pc-bios/vgabios-cirrus.bin             |binary
 pc-bios/vgabios-qxl.bin                |binary
 pc-bios/vgabios-stdvga.bin             |binary
 pc-bios/vgabios-vmware.bin             |binary
 pc-bios/vgabios.bin                    |binary
 pflib.c                                |  213 ++
 pflib.h                                |   20 
 posix-aio-compat.c                     |    8 
 qemu-binfmt-conf.sh                    |   62 
 qemu-char.c                            |  138 +
 qemu-char.h                            |   12 
 qemu-common.h                          |   97 -
 qemu-config.c                          |  129 +
 qemu-config.h                          |    1 
 qemu-doc.texi                          |  103 +
 qemu-error.h                           |    9 
 qemu-img-cmds.hx                       |    4 
 qemu-img.c                             |  467 ++---
 qemu-img.texi                          |   45 
 qemu-io.c                              |  154 +
 qemu-kvm-helper.c                      |   35 
 qemu-kvm-x86.c                         | 1266 ++++----------
 qemu-kvm.c                             |  495 +----
 qemu-kvm.h                             |  217 --
 qemu-lock.h                            |   10 
 qemu-malloc.c                          |   25 
 qemu-monitor.hx                        | 2549 ----------------------------
 qemu-nbd.c                             |   19 
 qemu-option.c                          |   13 
 qemu-options.hx                        |  130 +
 qemu-os-posix.h                        |   15 
 qemu-os-win32.h                        |   11 
 qemu-tech.texi                         |    4 
 qemu-timer-common.c                    |   63 
 qemu-timer.c                           |  162 -
 qemu-timer.h                           |   50 
 qemu-tool.c                            |    8 
 qemu_socket.h                          |    1 
 qerror.c                               |   10 
 qerror.h                               |    8 
 qjson.c                                |   55 
 qjson.h                                |    8 
 qmp-commands.hx                        | 1776 ++++++++++++++++++++
 range.h                                |   29 
 roms/seabios                           |    2 
 roms/vgabios                           |    2 
 rules.mak                              |   17 
 rwhandler.c                            |    4 
 rwhandler.h                            |    2 
 savevm.c                               |  171 +
 scripts/checkpatch.pl                  | 2910 +++++++++++++++++++++++++++++++++
 scripts/create_config                  |  103 +
 scripts/feature_to_c.sh                |   78 
 scripts/hxtool                         |  102 +
 scripts/make_device_config.sh          |   28 
 scripts/qemu-binfmt-conf.sh            |   66 
 scripts/signrom.sh                     |   45 
 scripts/simpletrace.py                 |   93 +
 scripts/texi2pod.pl                    |  477 +++++
 scripts/tracetool                      |  629 +++++++
 sh4-dis.c                              |   16 
 simpletrace.c                          |  255 ++
 simpletrace.h                          |   40 
 slirp/bootp.c                          |   34 
 slirp/ip_input.c                       |    2 
 slirp/misc.c                           |   42 
 slirp/slirp.c                          |    3 
 slirp/slirp.h                          |   22 
 slirp/slirp_config.h                   |    6 
 slirp/tftp.c                           |    4 
 spice-qemu-char.c                      |  190 ++
 sysemu.h                               |   36 
 target-alpha/helper.c                  |    3 
 target-alpha/op_helper.c               |    2 
 target-arm/cpu.h                       |   77 
 target-arm/helper.c                    |  169 +
 target-arm/helpers.h                   |   19 
 target-arm/neon_helper.c               |  225 ++
 target-arm/op_helper.c                 |   63 
 target-arm/translate.c                 |  725 +++++---
 target-cris/cpu.h                      |    7 
 target-cris/exec.h                     |    4 
 target-cris/helper.c                   |   10 
 target-cris/mmu.c                      |    4 
 target-cris/op_helper.c                |    4 
 target-cris/translate.c                |  104 -
 target-cris/translate_v10.c            |   15 
 target-i386/cpu.h                      |   34 
 target-i386/cpuid.c                    |   85 
 target-i386/fake-exec.c                |   12 
 target-i386/helper.c                   |  116 +
 target-i386/kvm.c                      | 1000 ++++++++---
 target-i386/kvm_x86.h                  |   25 
 target-i386/machine.c                  |   26 
 target-i386/op_helper.c                |    4 
 target-i386/translate.c                |   34 
 target-m68k/cpu.h                      |    3 
 target-m68k/helper.c                   |    8 
 target-m68k/translate.c                |    3 
 target-microblaze/cpu.h                |    9 
 target-microblaze/exec.h               |    4 
 target-microblaze/helper.h             |   19 
 target-microblaze/op_helper.c          |  289 ++-
 target-microblaze/translate.c          |  492 ++++-
 target-mips/cpu.h                      |   11 
 target-mips/exec.h                     |   18 
 target-mips/helper.h                   |    8 
 target-mips/op_helper.c                |   56 
 target-mips/translate.c                |   69 
 target-mips/translate_init.c           |    2 
 target-ppc/cpu.h                       |   12 
 target-ppc/exec.h                      |    3 
 target-ppc/helper.c                    |  132 -
 target-ppc/kvm.c                       |   49 
 target-ppc/kvm_ppc.h                   |   13 
 target-ppc/op_helper.c                 |  407 ++--
 target-ppc/translate.c                 |   59 
 target-ppc/translate_init.c            |    8 
 target-s390x/cpu.h                     |    6 
 target-s390x/kvm.c                     |    8 
 target-s390x/translate.c               |    5 
 target-sh4/cpu.h                       |   68 
 target-sh4/helper.c                    |  232 ++
 target-sh4/helper.h                    |    3 
 target-sh4/op_helper.c                 |  249 ++
 target-sh4/translate.c                 |  164 +
 target-sparc/cpu.h                     |   50 
 target-sparc/helper.c                  |  121 -
 target-sparc/helper.h                  |    3 
 target-sparc/op_helper.c               |  296 ++-
 target-sparc/translate.c               |   36 
 tcg/README                             |   24 
 tcg/arm/tcg-target.c                   |   72 
 tcg/ia64/tcg-target.c                  |   18 
 tcg/mips/tcg-target.c                  |    6 
 tcg/tcg-op.h                           |   68 
 tcg/tcg-opc.h                          |    6 
 tcg/tcg.c                              |    8 
 tcg/tcg.h                              |    3 
 tests/Makefile                         |  122 -
 tests/cris/check_abs.c                 |    5 
 tests/cris/check_addc.c                |    3 
 tests/cris/check_addcm.c               |    6 
 tests/cris/check_bound.c               |    9 
 tests/cris/check_ftag.c                |   12 
 tests/cris/check_int64.c               |    6 
 tests/cris/check_lz.c                  |    2 
 tests/cris/check_swap.c                |    4 
 tests/cris/crisutils.h                 |   20 
 tests/cris/sys.h                       |    4 
 tests/hello-i386.c                     |    4 
 tests/runcom.c                         |   11 
 tests/test-i386.c                      |    5 
 tests/test_path.c                      |   13 
 texi2pod.pl                            |  477 -----
 trace-events                           |  256 ++
 ui/cocoa.m                             |    6 
 ui/curses.c                            |    9 
 ui/curses_keys.h                       |    1 
 ui/d3des.h                             |    8 
 ui/qemu-spice.h                        |   57 
 ui/sdl.c                               |   14 
 ui/spice-core.c                        |  672 +++++++
 ui/spice-display.c                     |  412 ++++
 ui/spice-display.h                     |   68 
 ui/spice-input.c                       |  217 ++
 ui/vnc-auth-sasl.c                     |   14 
 ui/vnc-enc-tight.c                     |   20 
 ui/vnc-jobs-async.c                    |    4 
 ui/vnc.c                               |   93 -
 ui/vnc.h                               |    1 
 ui/x_keymap.h                          |    4 
 usb-bsd.c                              |   71 
 usb-linux.c                            |   75 
 version.rc                             |   28 
 vl.c                                   |  437 +++-
 716 files changed, 55164 insertions(+), 19070 deletions(-)

New commits:
commit 671d89d6411655bb4f8058ce6eb86bb0bb8ec978
Merge: 080b695... ac7a1d0...
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Feb 13 16:56:08 2011 +0200

    Merge branch 'upstream-merge' into next
    
    * upstream-merge: (55 commits)
      microblaze: Handle singlestepping over direct jmps
      target-arm: implement vsli.64, vsri.64
      target-arm: fix VSHLL Neon instruction.
      [PATCH] [MIPS] Clear softfpu exception state for round, trunc, ceil and floor
      target-arm: Fix 32 bit signed saturating narrow
      target-arm: Fix VQMOVUN Neon instruction.
      linux-user: fix for loopmount ioctl
      linux-user: fix build errors for mmap2-only ports
      user: speed up init_paths a bit
      linux-user: implement sched_{g,s}etaffinity
      linux-user/FLAT: allow targets to override FLAT processing
      linux-user/FLAT: fix auto-stack sizing
      linux-user: decode MAP_{UNINITIALIZED,EXECUTABLE} in strace
      linux-user: add ppoll syscall support
      linux-user/elfload: add FDPIC support
      linux-user: fix sizeof handling for getsockopt
      linux-user: Fix possible realloc memory leak
      linux-user: Add support for -version option
      cris, microblaze: use cpu_has_work
      x86: Fix MCA broadcast parameters for TCG case
      ...
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

commit ac7a1d055d8407c26bf00a0fe41a57aa90e4352c
Merge: a90c0e6... 6c5f738...
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Feb 13 16:54:50 2011 +0200

    Merge commit '6c5f738daec123020d32543fe90a6633a4f6643e' into upstream-merge
    
    * commit '6c5f738daec123020d32543fe90a6633a4f6643e': (44 commits)
      microblaze: Handle singlestepping over direct jmps
      target-arm: implement vsli.64, vsri.64
      target-arm: fix VSHLL Neon instruction.
      [PATCH] [MIPS] Clear softfpu exception state for round, trunc, ceil and floor
      target-arm: Fix 32 bit signed saturating narrow
      target-arm: Fix VQMOVUN Neon instruction.
      linux-user: fix for loopmount ioctl
      linux-user: fix build errors for mmap2-only ports
      user: speed up init_paths a bit
      linux-user: implement sched_{g,s}etaffinity
      linux-user/FLAT: allow targets to override FLAT processing
      linux-user/FLAT: fix auto-stack sizing
      linux-user: decode MAP_{UNINITIALIZED,EXECUTABLE} in strace
      linux-user: add ppoll syscall support
      linux-user/elfload: add FDPIC support
      linux-user: fix sizeof handling for getsockopt
      linux-user: Fix possible realloc memory leak
      linux-user: Add support for -version option
      cris, microblaze: use cpu_has_work
      x86: Fix MCA broadcast parameters for TCG case
      ...
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

commit a90c0e680d83d4e8f34f46566cd559c72c4ef2b6
Merge: 2d24961... 1f5e71a...
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Feb 13 16:51:51 2011 +0200

    Merge commit '1f5e71a8e6b24dce74b156472ff9253b9bd33a11' into upstream-merge
    
    * commit '1f5e71a8e6b24dce74b156472ff9253b9bd33a11':
      ioapic: Style & magics cleanup
    
    Conflicts:
    	hw/ioapic.c
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --cc hw/ioapic.c
index 5c8b835,569327d..8fab34f
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@@ -41,23 -37,50 +41,51 @@@
  #define DPRINTF(fmt, ...)
  #endif
  
 +#define IOAPIC_DEFAULT_BASE_ADDRESS  0xfec00000
  #define MAX_IOAPICS                     1
  
- #define IOAPIC_LVT_MASKED               (1 << 16)
- #define IOAPIC_LVT_REMOTE_IRR           (1 << 14)
+ #define IOAPIC_VERSION                  0x11
  
- #define IOAPIC_TRIGGER_EDGE		0
- #define IOAPIC_TRIGGER_LEVEL		1
+ #define IOAPIC_LVT_DEST_SHIFT           56
+ #define IOAPIC_LVT_MASKED_SHIFT         16
+ #define IOAPIC_LVT_TRIGGER_MODE_SHIFT   15
+ #define IOAPIC_LVT_REMOTE_IRR_SHIFT     14
+ #define IOAPIC_LVT_POLARITY_SHIFT       13
+ #define IOAPIC_LVT_DELIV_STATUS_SHIFT   12
+ #define IOAPIC_LVT_DEST_MODE_SHIFT      11
+ #define IOAPIC_LVT_DELIV_MODE_SHIFT     8
+ 
+ #define IOAPIC_LVT_MASKED               (1 << IOAPIC_LVT_MASKED_SHIFT)
+ #define IOAPIC_LVT_REMOTE_IRR           (1 << IOAPIC_LVT_REMOTE_IRR_SHIFT)
+ 
+ #define IOAPIC_TRIGGER_EDGE             0
+ #define IOAPIC_TRIGGER_LEVEL            1
  
  /*io{apic,sapic} delivery mode*/
- #define IOAPIC_DM_FIXED			0x0
- #define IOAPIC_DM_LOWEST_PRIORITY	0x1
- #define IOAPIC_DM_PMI			0x2
- #define IOAPIC_DM_NMI			0x4
- #define IOAPIC_DM_INIT			0x5
- #define IOAPIC_DM_SIPI			0x5
- #define IOAPIC_DM_EXTINT		0x7
+ #define IOAPIC_DM_FIXED                 0x0
+ #define IOAPIC_DM_LOWEST_PRIORITY       0x1
+ #define IOAPIC_DM_PMI                   0x2
+ #define IOAPIC_DM_NMI                   0x4
+ #define IOAPIC_DM_INIT                  0x5
+ #define IOAPIC_DM_SIPI                  0x6
+ #define IOAPIC_DM_EXTINT                0x7
+ #define IOAPIC_DM_MASK                  0x7
+ 
+ #define IOAPIC_VECTOR_MASK              0xff
+ 
+ #define IOAPIC_IOREGSEL                 0x00
+ #define IOAPIC_IOWIN                    0x10
+ 
+ #define IOAPIC_REG_ID                   0x00
+ #define IOAPIC_REG_VER                  0x01
+ #define IOAPIC_REG_ARB                  0x02
+ #define IOAPIC_REG_REDTBL_BASE          0x10
+ #define IOAPIC_ID                       0x00
+ 
+ #define IOAPIC_ID_SHIFT                 24
+ #define IOAPIC_ID_MASK                  0xf
+ 
+ #define IOAPIC_VER_ENTRIES_SHIFT        16
  
  typedef struct IOAPICState IOAPICState;
  
@@@ -65,8 -88,6 +93,7 @@@ struct IOAPICState 
      SysBusDevice busdev;
      uint8_t id;
      uint8_t ioregsel;
 +    uint64_t base_address;
- 
      uint32_t irr;
      uint64_t ioredtbl[IOAPIC_NUM_PINS];
  };
@@@ -120,11 -142,10 +148,10 @@@ static void ioapic_set_irq(void *opaque
       * to GSI 2.  GSI maps to ioapic 1-1.  This is not
       * the cleanest way of doing it but it should work. */
  
-     DPRINTF("%s: %s vec %x\n", __func__, level? "raise" : "lower", vector);
+     DPRINTF("%s: %s vec %x\n", __func__, level ? "raise" : "lower", vector);
 -    if (vector == 0) {
 +    if (vector == 0 && irq0override) {
          vector = 2;
      }
- 
      if (vector >= 0 && vector < IOAPIC_NUM_PINS) {
          uint32_t mask = 1 << vector;
          uint64_t entry = s->ioredtbl[vector];
@@@ -322,12 -284,10 +357,12 @@@ static const VMStateDescription vmstate
      .post_load = ioapic_post_load,
      .minimum_version_id = 1,
      .minimum_version_id_old = 1,
 +    .pre_load = ioapic_pre_load,
 +    .pre_save = ioapic_pre_save,
-     .fields      = (VMStateField []) {
+     .fields = (VMStateField[]) {
          VMSTATE_UINT8(id, IOAPICState),
          VMSTATE_UINT8(ioregsel, IOAPICState),
 -        VMSTATE_UNUSED_V(2, 8), /* to account for qemu-kvm's v2 format */
 +        VMSTATE_UINT64_V(base_address, IOAPICState, 2),
          VMSTATE_UINT32_V(irr, IOAPICState, 2),
          VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICState, IOAPIC_NUM_PINS),
          VMSTATE_END_OF_LIST()
@@@ -343,13 -302,9 +378,14 @@@ static void ioapic_reset(DeviceState *d
      s->id = 0;
      s->ioregsel = 0;
      s->irr = 0;
-     for(i = 0; i < IOAPIC_NUM_PINS; i++)
-         s->ioredtbl[i] = 1 << 16; /* mask LVT */
+     for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+         s->ioredtbl[i] = 1 << IOAPIC_LVT_MASKED_SHIFT;
+     }
 +#ifdef KVM_CAP_IRQCHIP
 +    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 +        kvm_kernel_ioapic_load_from_user(s);
 +    }
 +#endif
  }
  
  static CPUReadMemoryFunc * const ioapic_mem_read[3] = {
commit 2d24961d3bba8ac38c38af27816f462d5deb2d51
Merge: 53d6be9... 5dce499...
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Feb 13 16:48:24 2011 +0200

    Merge commit '5dce499948e4a4abe62f010baf4a7ed3d49e53cb' into upstream-merge
    
    * commit '5dce499948e4a4abe62f010baf4a7ed3d49e53cb':
      ioapic: Add support for qemu-kvm's vmstate v2
    
    Conflicts:
    	hw/ioapic.c
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

commit 53d6be977096cbeb9f3941437e1c36a6d47b3ed3
Merge: e806014... 35a74c5...
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Feb 13 16:47:59 2011 +0200

    Merge commit '35a74c5c5941b474d8b985237e1bde0b8cd2a20f' into upstream-merge
    
    * commit '35a74c5c5941b474d8b985237e1bde0b8cd2a20f':
      ioapic: Save/restore irr
    
    Conflicts:
    	hw/ioapic.c
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --cc hw/ioapic.c
index afdf9b5,8c46c1d..7027b3e
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@@ -304,20 -235,19 +304,26 @@@ static int ioapic_post_load(void *opaqu
  {
      IOAPICState *s = opaque;
  
+     if (version_id == 1) {
+         /* set sane value */
+         s->irr = 0;
+     }
++
 +    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 +        kvm_kernel_ioapic_load_from_user(s);
 +    }
++
      return 0;
  }
  
  static const VMStateDescription vmstate_ioapic = {
      .name = "ioapic",
      .version_id = 2,
+     .post_load = ioapic_post_load,
      .minimum_version_id = 1,
      .minimum_version_id_old = 1,
 +    .pre_load = ioapic_pre_load,
-     .post_load = ioapic_post_load,
 +    .pre_save = ioapic_pre_save,
      .fields      = (VMStateField []) {
          VMSTATE_UINT8(id, IOAPICState),
          VMSTATE_UINT8(ioregsel, IOAPICState),
commit e80601494369f8b3f542185d75139a77d0e66853
Merge: 080b695... 0280b57...
Author: Avi Kivity <avi at redhat.com>
Date:   Sun Feb 13 16:46:53 2011 +0200

    Merge commit '0280b571c1a153f8926612d8c8d7359242d596f5' into upstream-merge
    
    * commit '0280b571c1a153f8926612d8c8d7359242d596f5':
      ioapic: Implement EOI handling for level-triggered IRQs
      vnc: qemu can die if the client is disconnected while updating screen
      virtio-serial: Make sure virtqueue is ready before discarding data
      ui/sdl: Fix handling of caps lock and num lock keys
      Unify alarm deadline computation
      Correct alarm deadline computation
      use nanoseconds everywhere for timeout computation
      savevm: fix corruption in vmstate_subsection_load().
    
    Conflicts:
    	hw/ioapic.c
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --cc hw/ioapic.c
index aeb3653,8bc31f7..afdf9b5
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@@ -23,8 -23,7 +23,9 @@@
  #include "hw.h"
  #include "pc.h"
  #include "apic.h"
 +#include "sysemu.h"
 +#include "apic.h"
+ #include "ioapic.h"
  #include "qemu-timer.h"
  #include "host-utils.h"
  #include "sysbus.h"
@@@ -40,8 -37,10 +41,11 @@@
  #define DPRINTF(fmt, ...)
  #endif
  
 +#define IOAPIC_DEFAULT_BASE_ADDRESS  0xfec00000
- #define IOAPIC_LVT_MASKED 		(1<<16)
+ #define MAX_IOAPICS                     1
+ 
+ #define IOAPIC_LVT_MASKED               (1 << 16)
+ #define IOAPIC_LVT_REMOTE_IRR           (1 << 14)
  
  #define IOAPIC_TRIGGER_EDGE		0
  #define IOAPIC_TRIGGER_LEVEL		1
commit 080b695d7ce5d21f9db7f4ad87f1d1f5bcf37660
Author: Avi Kivity <avi at redhat.com>
Date:   Wed Feb 9 13:46:48 2011 +0200

    Close all block drivers on quit
    
    Following 2bc93fed76c89f7adaa0e5bb3, close all block drivers on quit.
    Fixes qcow2 data loss after quit due to qcowcache being volatile.
    
    Signed-off-by: Avi Kivity <avi at redhat.com>

diff --git a/qemu-kvm.c b/qemu-kvm.c
index 4974179..49cd683 100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@ -1606,6 +1606,7 @@ int kvm_main_loop(void)
         }
     }
 
+    bdrv_close_all();
     pause_all_threads();
     pthread_mutex_unlock(&qemu_mutex);
 
commit 6c5f738daec123020d32543fe90a6633a4f6643e
Author: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
Date:   Thu Feb 10 00:46:09 2011 +0100

    microblaze: Handle singlestepping over direct jmps
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>

diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 2207431..fdb2b40 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1715,9 +1715,13 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
     t_sync_flags(dc);
 
     if (unlikely(env->singlestep_enabled)) {
-        t_gen_raise_exception(dc, EXCP_DEBUG);
-        if (dc->is_jmp == DISAS_NEXT)
+        TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
+
+        if (dc->is_jmp != DISAS_JUMP) {
             tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
+        }
+        gen_helper_raise_exception(tmp);
+        tcg_temp_free_i32(tmp);
     } else {
         switch(dc->is_jmp) {
             case DISAS_NEXT:
commit 1c0de9fa509c48aeeb6ef2465307d603abc9ee4e
Merge: 923e650... 898b1be...
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Feb 9 19:53:36 2011 +0100

    Merge branch 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu
    
    * 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu:
      linux-user: fix for loopmount ioctl
      linux-user: fix build errors for mmap2-only ports
      user: speed up init_paths a bit
      linux-user: implement sched_{g,s}etaffinity
      linux-user/FLAT: allow targets to override FLAT processing
      linux-user/FLAT: fix auto-stack sizing
      linux-user: decode MAP_{UNINITIALIZED,EXECUTABLE} in strace
      linux-user: add ppoll syscall support
      linux-user/elfload: add FDPIC support
      linux-user: fix sizeof handling for getsockopt
      linux-user: Fix possible realloc memory leak
      linux-user: Add support for -version option

commit 923e65097d2101a78f716f7932f4291315d88bbf
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Tue Feb 8 18:39:02 2011 +0100

    target-arm: implement vsli.64, vsri.64
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index ef3f369..3087a5d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4698,7 +4698,19 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
                         } else if (op == 4 || (op == 5 && u)) {
                             /* Insert */
-                            cpu_abort(env, "VS[LR]I.64 not implemented");
+                            neon_load_reg64(cpu_V1, rd + pass);
+                            uint64_t mask;
+                            if (shift < -63 || shift > 63) {
+                                mask = 0;
+                            } else {
+                                if (op == 4) {
+                                    mask = 0xffffffffffffffffull >> -shift;
+                                } else {
+                                    mask = 0xffffffffffffffffull << shift;
+                                }
+                            }
+                            tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
+                            tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
                         }
                         neon_store_reg64(cpu_V0, rd + pass);
                     } else { /* size < 3 */
commit acdf01effa1851780a731ca5ffeab79a474a6335
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Wed Feb 9 13:19:15 2011 +0100

    target-arm: fix VSHLL Neon instruction.
    
    Fix bit mask used when widening the result of shift on narrow input.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 89c916d..ef3f369 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4880,16 +4880,28 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         /* The shift is less than the width of the source
                            type, so we can just shift the whole register.  */
                         tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
+                        /* Widen the result of shift: we need to clear
+                         * the potential overflow bits resulting from
+                         * left bits of the narrow input appearing as
+                         * right bits of left the neighbour narrow
+                         * input.  */
                         if (size < 2 || !u) {
                             uint64_t imm64;
                             if (size == 0) {
                                 imm = (0xffu >> (8 - shift));
                                 imm |= imm << 16;
-                            } else {
+                            } else if (size == 1) {
                                 imm = 0xffff >> (16 - shift);
+                            } else {
+                                /* size == 2 */
+                                imm = 0xffffffff >> (32 - shift);
+                            }
+                            if (size < 2) {
+                                imm64 = imm | (((uint64_t)imm) << 32);
+                            } else {
+                                imm64 = imm;
                             }
-                            imm64 = imm | (((uint64_t)imm) << 32);
-                            tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
+                            tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
                         }
                     }
                     neon_store_reg64(cpu_V0, rd + pass);
commit efd410373a4551911f3928bb2ccdf28792b294bf
Author: Chris Dearman <chris at mips.com>
Date:   Tue Feb 8 19:03:30 2011 -0800

    [PATCH] [MIPS] Clear softfpu exception state for round, trunc, ceil and floor
    
    MIPS FPU instructions should start with a clean softfpu status. This
    is done for the arithmetic operations and cvt instructions, but not
    for round, trunc, ceil and floor.
    
    Signed-off-by: Chris Dearman <chris at mips.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 669faf1..bd16ce3 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2282,6 +2282,7 @@ uint64_t helper_float_roundl_d(uint64_t fdt0)
 {
     uint64_t dt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
     RESTORE_ROUNDING_MODE;
@@ -2295,6 +2296,7 @@ uint64_t helper_float_roundl_s(uint32_t fst0)
 {
     uint64_t dt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
     RESTORE_ROUNDING_MODE;
@@ -2308,6 +2310,7 @@ uint32_t helper_float_roundw_d(uint64_t fdt0)
 {
     uint32_t wt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
     RESTORE_ROUNDING_MODE;
@@ -2321,6 +2324,7 @@ uint32_t helper_float_roundw_s(uint32_t fst0)
 {
     uint32_t wt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
     RESTORE_ROUNDING_MODE;
@@ -2334,6 +2338,7 @@ uint64_t helper_float_truncl_d(uint64_t fdt0)
 {
     uint64_t dt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
     update_fcr31();
     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
@@ -2345,6 +2350,7 @@ uint64_t helper_float_truncl_s(uint32_t fst0)
 {
     uint64_t dt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
     update_fcr31();
     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
@@ -2356,6 +2362,7 @@ uint32_t helper_float_truncw_d(uint64_t fdt0)
 {
     uint32_t wt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
     update_fcr31();
     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
@@ -2367,6 +2374,7 @@ uint32_t helper_float_truncw_s(uint32_t fst0)
 {
     uint32_t wt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
     update_fcr31();
     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
@@ -2378,6 +2386,7 @@ uint64_t helper_float_ceill_d(uint64_t fdt0)
 {
     uint64_t dt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
     RESTORE_ROUNDING_MODE;
@@ -2391,6 +2400,7 @@ uint64_t helper_float_ceill_s(uint32_t fst0)
 {
     uint64_t dt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
     RESTORE_ROUNDING_MODE;
@@ -2404,6 +2414,7 @@ uint32_t helper_float_ceilw_d(uint64_t fdt0)
 {
     uint32_t wt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
     RESTORE_ROUNDING_MODE;
@@ -2417,6 +2428,7 @@ uint32_t helper_float_ceilw_s(uint32_t fst0)
 {
     uint32_t wt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
     RESTORE_ROUNDING_MODE;
@@ -2430,6 +2442,7 @@ uint64_t helper_float_floorl_d(uint64_t fdt0)
 {
     uint64_t dt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
     RESTORE_ROUNDING_MODE;
@@ -2443,6 +2456,7 @@ uint64_t helper_float_floorl_s(uint32_t fst0)
 {
     uint64_t dt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
     RESTORE_ROUNDING_MODE;
@@ -2456,6 +2470,7 @@ uint32_t helper_float_floorw_d(uint64_t fdt0)
 {
     uint32_t wt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
     RESTORE_ROUNDING_MODE;
@@ -2469,6 +2484,7 @@ uint32_t helper_float_floorw_s(uint32_t fst0)
 {
     uint32_t wt2;
 
+    set_float_exception_flags(0, &env->active_fpu.fp_status);
     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
     RESTORE_ROUNDING_MODE;
commit cc2212c2f851291929becc3f4fd153d05ca4c54a
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Feb 9 15:42:33 2011 +0000

    target-arm: Fix 32 bit signed saturating narrow
    
    The returned value when doing saturating signed 64->32 bit
    conversion of a negative number was incorrect due to a missing cast.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index a7cf383..61890dd 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -1209,7 +1209,7 @@ uint32_t HELPER(neon_narrow_sat_s32)(CPUState *env, uint64_t x)
 {
     if ((int64_t)x != (int32_t)x) {
         SET_QC();
-        return (x >> 63) ^ 0x7fffffff;
+        return ((int64_t)x >> 63) ^ 0x7fffffff;
     }
     return x;
 }
commit af1bbf30c407cb194599a4e1724c38c7bf1d94b3
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Wed Feb 9 15:42:32 2011 +0000

    target-arm: Fix VQMOVUN Neon instruction.
    
    VQMOVUN does a signed-to-unsigned saturating conversion. This is
    different from both the signed-to-signed and unsigned-to-unsigned
    conversions already implemented, so we need a new set of helper
    functions (neon_unarrow_sat*).
    
    Signed-off-by: Juha Riihimäki <juha.riihimaki at nokia.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index 8a2564e..4d0de00 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -299,10 +299,13 @@ DEF_HELPER_3(neon_qrdmulh_s32, i32, env, i32, i32)
 
 DEF_HELPER_1(neon_narrow_u8, i32, i64)
 DEF_HELPER_1(neon_narrow_u16, i32, i64)
+DEF_HELPER_2(neon_unarrow_sat8, i32, env, i64)
 DEF_HELPER_2(neon_narrow_sat_u8, i32, env, i64)
 DEF_HELPER_2(neon_narrow_sat_s8, i32, env, i64)
+DEF_HELPER_2(neon_unarrow_sat16, i32, env, i64)
 DEF_HELPER_2(neon_narrow_sat_u16, i32, env, i64)
 DEF_HELPER_2(neon_narrow_sat_s16, i32, env, i64)
+DEF_HELPER_2(neon_unarrow_sat32, i32, env, i64)
 DEF_HELPER_2(neon_narrow_sat_u32, i32, env, i64)
 DEF_HELPER_2(neon_narrow_sat_s32, i32, env, i64)
 DEF_HELPER_1(neon_narrow_high_u8, i32, i64)
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 268af33..a7cf383 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -1053,6 +1053,33 @@ uint32_t HELPER(neon_narrow_round_high_u16)(uint64_t x)
     return ((x >> 16) & 0xffff) | ((x >> 32) & 0xffff0000);
 }
 
+uint32_t HELPER(neon_unarrow_sat8)(CPUState *env, uint64_t x)
+{
+    uint16_t s;
+    uint8_t d;
+    uint32_t res = 0;
+#define SAT8(n) \
+    s = x >> n; \
+    if (s & 0x8000) { \
+        SET_QC(); \
+    } else { \
+        if (s > 0xff) { \
+            d = 0xff; \
+            SET_QC(); \
+        } else  { \
+            d = s; \
+        } \
+        res |= (uint32_t)d << (n / 2); \
+    }
+
+    SAT8(0);
+    SAT8(16);
+    SAT8(32);
+    SAT8(48);
+#undef SAT8
+    return res;
+}
+
 uint32_t HELPER(neon_narrow_sat_u8)(CPUState *env, uint64_t x)
 {
     uint16_t s;
@@ -1099,6 +1126,29 @@ uint32_t HELPER(neon_narrow_sat_s8)(CPUState *env, uint64_t x)
     return res;
 }
 
+uint32_t HELPER(neon_unarrow_sat16)(CPUState *env, uint64_t x)
+{
+    uint32_t high;
+    uint32_t low;
+    low = x;
+    if (low & 0x80000000) {
+        low = 0;
+        SET_QC();
+    } else if (low > 0xffff) {
+        low = 0xffff;
+        SET_QC();
+    }
+    high = x >> 32;
+    if (high & 0x80000000) {
+        high = 0;
+        SET_QC();
+    } else if (high > 0xffff) {
+        high = 0xffff;
+        SET_QC();
+    }
+    return low | (high << 16);
+}
+
 uint32_t HELPER(neon_narrow_sat_u16)(CPUState *env, uint64_t x)
 {
     uint32_t high;
@@ -1133,6 +1183,19 @@ uint32_t HELPER(neon_narrow_sat_s16)(CPUState *env, uint64_t x)
     return (uint16_t)low | (high << 16);
 }
 
+uint32_t HELPER(neon_unarrow_sat32)(CPUState *env, uint64_t x)
+{
+    if (x & 0x8000000000000000ull) {
+        SET_QC();
+        return 0;
+    }
+    if (x > 0xffffffffu) {
+        SET_QC();
+        return 0xffffffffu;
+    }
+    return x;
+}
+
 uint32_t HELPER(neon_narrow_sat_u32)(CPUState *env, uint64_t x)
 {
     if (x > 0xffffffffu) {
diff --git a/target-arm/translate.c b/target-arm/translate.c
index e4649e6..89c916d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4065,6 +4065,16 @@ static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
     }
 }
 
+static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
+{
+    switch (size) {
+    case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
+    case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
+    case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
+    default: abort();
+    }
+}
+
 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
                                          int q, int u)
 {
@@ -5461,12 +5471,18 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     for (pass = 0; pass < 2; pass++) {
                         neon_load_reg64(cpu_V0, rm + pass);
                         tmp = new_tmp();
-                        if (op == 36 && q == 0) {
-                            gen_neon_narrow(size, tmp, cpu_V0);
-                        } else if (q) {
-                            gen_neon_narrow_satu(size, tmp, cpu_V0);
-                        } else {
-                            gen_neon_narrow_sats(size, tmp, cpu_V0);
+                        if (op == 36) {
+                            if (q) { /* VQMOVUN */
+                                gen_neon_unarrow_sats(size, tmp, cpu_V0);
+                            } else { /* VMOVN */
+                                gen_neon_narrow(size, tmp, cpu_V0);
+                            }
+                        } else { /* VQMOVN */
+                            if (q) {
+                                gen_neon_narrow_satu(size, tmp, cpu_V0);
+                            } else {
+                                gen_neon_narrow_sats(size, tmp, cpu_V0);
+                            }
                         }
                         if (pass == 0) {
                             tmp2 = tmp;
commit 898b1bebf97e5f973624a4e513da45dffefdb9b7
Author: Martin Mohring <martin.mohring at 5edatasoft.com>
Date:   Tue Feb 8 14:48:56 2011 +0200

    linux-user: fix for loopmount ioctl
    
    In case a chrooted build uses XEN or KVM, a looped mount needs to be done to setup the chroot.
    The ioctl for loop mount works correctly for arm, mips, ppc32 and sh4, so its now activated.
    
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index acff781..526aaa2 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -312,10 +312,8 @@
   IOCTL(LOOP_CLR_FD, 0, TYPE_INT)
   IOCTL(LOOP_SET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info)))
   IOCTL(LOOP_GET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info)))
-#if 0 /* These have some problems - not fully tested */
   IOCTL(LOOP_SET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64)))
   IOCTL(LOOP_GET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64)))
-#endif
   IOCTL(LOOP_CHANGE_FD, 0, TYPE_INT)
 
   IOCTL(MTIOCTOP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_mtop)))
commit 8d9016c0919bab1fdf3a36c0f72d012924bb7efd
Author: Mike Frysinger <vapier at gentoo.org>
Date:   Mon Feb 7 01:05:57 2011 -0500

    linux-user: fix build errors for mmap2-only ports
    
    The current print_mmap func is only enabled when the target supports the
    mmap syscall, but both mmap and mmap2 syscalls use it.  This leads to a
    build failure when the target supports mmap2 but not mmap.
    
    Signed-off-by: Mike Frysinger <vapier at gentoo.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/strace.c b/linux-user/strace.c
index a8786bb..1836666 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1203,7 +1203,7 @@ print_utimensat(const struct syscallname *name,
 }
 #endif
 
-#ifdef TARGET_NR_mmap
+#if defined(TARGET_NR_mmap) || defined(TARGET_NR_mmap2)
 static void
 print_mmap(const struct syscallname *name,
     abi_long arg0, abi_long arg1, abi_long arg2,
commit 2296f194dfde4c0a54f249d3fdb8c8ca21dc611b
Author: Mike Frysinger <vapier at gentoo.org>
Date:   Mon Feb 7 01:05:56 2011 -0500

    user: speed up init_paths a bit
    
    The current init_paths code will attempt to opendir() every single file it
    finds.  This can obviously generated a huge number of syscalls with even a
    moderately small sysroot that will fail.  Since the readdir() call provides
    the file type in the struct itself, use it.  On my system, this prevents
    over 1000 syscalls from being made at every invocation of a target binary,
    and I only have a C library installed.
    
    Signed-off-by: Mike Frysinger <vapier at gentoo.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/path.c b/path.c
index 0d2bf14..ef3f277 100644
--- a/path.c
+++ b/path.c
@@ -38,7 +38,8 @@ static int strneq(const char *s1, unsigned int n, const char *s2)
     return s2[i] == 0;
 }
 
-static struct pathelem *add_entry(struct pathelem *root, const char *name);
+static struct pathelem *add_entry(struct pathelem *root, const char *name,
+                                  unsigned char type);
 
 static struct pathelem *new_entry(const char *root,
                                   struct pathelem *parent,
@@ -56,6 +57,15 @@ static struct pathelem *new_entry(const char *root,
 
 #define streq(a,b) (strcmp((a), (b)) == 0)
 
+/* Not all systems provide this feature */
+#if defined(DT_DIR) && defined(DT_UNKNOWN)
+# define dirent_type(dirent) ((dirent)->d_type)
+# define is_dir_maybe(type)  ((type) == DT_DIR || (type) == DT_UNKNOWN)
+#else
+# define dirent_type(dirent) (1)
+# define is_dir_maybe(type)  (type)
+#endif
+
 static struct pathelem *add_dir_maybe(struct pathelem *path)
 {
     DIR *dir;
@@ -65,7 +75,7 @@ static struct pathelem *add_dir_maybe(struct pathelem *path)
 
         while ((dirent = readdir(dir)) != NULL) {
             if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){
-                path = add_entry(path, dirent->d_name);
+                path = add_entry(path, dirent->d_name, dirent_type(dirent));
             }
         }
         closedir(dir);
@@ -73,16 +83,22 @@ static struct pathelem *add_dir_maybe(struct pathelem *path)
     return path;
 }
 
-static struct pathelem *add_entry(struct pathelem *root, const char *name)
+static struct pathelem *add_entry(struct pathelem *root, const char *name,
+                                  unsigned char type)
 {
+    struct pathelem **e;
+
     root->num_entries++;
 
     root = realloc(root, sizeof(*root)
                    + sizeof(root->entries[0])*root->num_entries);
+    e = &root->entries[root->num_entries-1];
+
+    *e = new_entry(root->pathname, root, name);
+    if (is_dir_maybe(type)) {
+        *e = add_dir_maybe(*e);
+    }
 
-    root->entries[root->num_entries-1] = new_entry(root->pathname, root, name);
-    root->entries[root->num_entries-1]
-        = add_dir_maybe(root->entries[root->num_entries-1]);
     return root;
 }
 
commit 737de1d1357b13f162b26ca0b775eb375594833a
Author: Mike Frysinger <vapier at gentoo.org>
Date:   Mon Feb 7 01:05:55 2011 -0500

    linux-user: implement sched_{g,s}etaffinity
    
    Signed-off-by: Mike Frysinger <vapier at gentoo.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index bb6ef43..4412a9b 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -235,6 +235,12 @@ _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
           const struct timespec *,timeout,int *,uaddr2,int,val3)
 #endif
 #endif
+#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
+_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
+          unsigned long *, user_mask_ptr);
+#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
+_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
+          unsigned long *, user_mask_ptr);
 
 static bitmask_transtbl fcntl_flags_tbl[] = {
   { TARGET_O_ACCMODE,   TARGET_O_WRONLY,    O_ACCMODE,   O_WRONLY,    },
@@ -6354,6 +6360,67 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
            return value. */
         ret = -TARGET_ENOTDIR;
         break;
+    case TARGET_NR_sched_getaffinity:
+        {
+            unsigned int mask_size;
+            unsigned long *mask;
+
+            /*
+             * sched_getaffinity needs multiples of ulong, so need to take
+             * care of mismatches between target ulong and host ulong sizes.
+             */
+            if (arg2 & (sizeof(abi_ulong) - 1)) {
+                ret = -TARGET_EINVAL;
+                break;
+            }
+            mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
+
+            mask = alloca(mask_size);
+            ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
+
+            if (!is_error(ret)) {
+                if (arg2 > ret) {
+                    /* Zero out any extra space kernel didn't fill */
+                    unsigned long zero = arg2 - ret;
+                    p = alloca(zero);
+                    memset(p, 0, zero);
+                    if (copy_to_user(arg3 + zero, p, zero)) {
+                        goto efault;
+                    }
+                    arg2 = ret;
+                }
+                if (copy_to_user(arg3, mask, arg2)) {
+                    goto efault;
+                }
+                ret = arg2;
+            }
+        }
+        break;
+    case TARGET_NR_sched_setaffinity:
+        {
+            unsigned int mask_size;
+            unsigned long *mask;
+
+            /*
+             * sched_setaffinity needs multiples of ulong, so need to take
+             * care of mismatches between target ulong and host ulong sizes.
+             */
+            if (arg2 & (sizeof(abi_ulong) - 1)) {
+                ret = -TARGET_EINVAL;
+                break;
+            }
+            mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
+
+            mask = alloca(mask_size);
+            if (!lock_user_struct(VERIFY_READ, p, arg3, 1)) {
+                goto efault;
+            }
+            memcpy(mask, p, arg2);
+            unlock_user_struct(p, arg2, 0);
+
+            ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
+        }
+        break;
     case TARGET_NR_sched_setparam:
         {
             struct sched_param *target_schp;
commit c3109ba1b109f84929abbfe0462d910d5aa8617c
Author: Mike Frysinger <vapier at gentoo.org>
Date:   Mon Feb 7 01:05:54 2011 -0500

    linux-user/FLAT: allow targets to override FLAT processing
    
    This brings flatload.c more in line with the current Linux FLAT loader
    which allows targets to handle various FLAT aspects in their own way.
    For the common behavior, the new functions get stubbed out.
    
    Signed-off-by: Mike Frysinger <vapier at gentoo.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/Makefile.target b/Makefile.target
index b0ba95f..48e6c00 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -107,7 +107,7 @@ ifdef CONFIG_LINUX_USER
 
 $(call set-vpath, $(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR))
 
-QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
+QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
 obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \
       elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \
       qemu-malloc.o $(oslib-obj-y)
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index d8b4476..cd7af7c 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -41,6 +41,8 @@
 
 #include "qemu.h"
 #include "flat.h"
+#define ntohl(x) be32_to_cpu(x)
+#include <target_flat.h>
 
 //#define DEBUG
 
@@ -50,14 +52,6 @@
 #define	DBG_FLT(...)
 #endif
 
-#define flat_reloc_valid(reloc, size)             ((reloc) <= (size))
-#define flat_old_ram_flag(flag)                   (flag)
-#ifdef TARGET_WORDS_BIGENDIAN
-#define flat_get_relocate_addr(relval)            (relval)
-#else
-#define flat_get_relocate_addr(relval)            bswap32(relval)
-#endif
-
 #define RELOC_FAILED 0xff00ff01		/* Relocation incorrect somewhere */
 #define UNLOADED_LIB 0x7ff000ff		/* Placeholder for unused library */
 
@@ -78,8 +72,6 @@ static int load_flat_shared_library(int id, struct lib_info *p);
 
 struct linux_binprm;
 
-#define ntohl(x) be32_to_cpu(x)
-
 /****************************************************************************/
 /*
  * create_flat_tables() parses the env- and arg-strings in new user
@@ -625,6 +617,7 @@ static int load_flat_file(struct linux_binprm * bprm,
      * __start to address 4 so that is okay).
      */
     if (rev > OLD_FLAT_VERSION) {
+        abi_ulong persistent = 0;
         for (i = 0; i < relocs; i++) {
             abi_ulong addr, relval;
 
@@ -633,6 +626,9 @@ static int load_flat_file(struct linux_binprm * bprm,
                relocated first).  */
             if (get_user_ual(relval, reloc + i * sizeof(abi_ulong)))
                 return -EFAULT;
+            relval = ntohl(relval);
+            if (flat_set_persistent(relval, &persistent))
+                continue;
             addr = flat_get_relocate_addr(relval);
             rp = calc_reloc(addr, libinfo, id, 1);
             if (rp == RELOC_FAILED)
@@ -641,22 +637,20 @@ static int load_flat_file(struct linux_binprm * bprm,
             /* Get the pointer's value.  */
             if (get_user_ual(addr, rp))
                 return -EFAULT;
+            addr = flat_get_addr_from_rp(rp, relval, flags, &persistent);
             if (addr != 0) {
                 /*
                  * Do the relocation.  PIC relocs in the data section are
                  * already in target order
                  */
-
-#ifndef TARGET_WORDS_BIGENDIAN
                 if ((flags & FLAT_FLAG_GOTPIC) == 0)
-                    addr = bswap32(addr);
-#endif
+                    addr = ntohl(addr);
                 addr = calc_reloc(addr, libinfo, id, 0);
                 if (addr == RELOC_FAILED)
                     return -ENOEXEC;
 
                 /* Write back the relocated pointer.  */
-                if (put_user_ual(addr, rp))
+                if (flat_put_addr_at_rp(rp, addr, relval))
                     return -EFAULT;
             }
         }
@@ -782,7 +776,8 @@ int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     stack_len *= sizeof(abi_ulong);
     if ((sp + stack_len) & 15)
         sp -= 16 - ((sp + stack_len) & 15);
-    sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, 1);
+    sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p,
+                             flat_argvp_envp_on_stack());
 
     /* Fake some return addresses to ensure the call chain will
      * initialise library in order for us.  We are required to call
diff --git a/linux-user/target_flat.h b/linux-user/target_flat.h
new file mode 100644
index 0000000..0ba6bdd
--- /dev/null
+++ b/linux-user/target_flat.h
@@ -0,0 +1,10 @@
+/* If your arch needs to do custom stuff, create your own target_flat.h
+ * header file in linux-user/<your arch>/
+ */
+#define flat_argvp_envp_on_stack()                           1
+#define flat_reloc_valid(reloc, size)                        ((reloc) <= (size))
+#define flat_old_ram_flag(flag)                              (flag)
+#define flat_get_relocate_addr(relval)                       (relval)
+#define flat_get_addr_from_rp(rp, relval, flags, persistent) (rp)
+#define flat_set_persistent(relval, persistent)              (*persistent)
+#define flat_put_addr_at_rp(rp, addr, relval)                put_user_ual(addr, rp)
commit 82a39595f7c70aecfb4649ae5a125147b62131f8
Author: Mike Frysinger <vapier at gentoo.org>
Date:   Mon Feb 7 01:05:53 2011 -0500

    linux-user/FLAT: fix auto-stack sizing
    
    The current auto-stack sizing works like it does on a NOMMU system; the
    problem is that this only works if the envp/argv arrays are fairly slim.
    On a desktop system, this is rarely the case, and can easily blow past
    the stack and into data/text regions as the default stack for FLAT progs
    is a mere 4KiB.  So rather than rely on the NOMMU calculation (which is
    only there because NOMMU can't easily allocate gobs of contiguous mem),
    calc the full space actually needed and let the MMU host make space.
    
    Signed-off-by: Mike Frysinger <vapier at gentoo.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 8f9f4a5..d8b4476 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -733,8 +733,15 @@ int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
      * pedantic and include space for the argv/envp array as it may have
      * a lot of entries.
      */
-#define TOP_OF_ARGS (TARGET_PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *))
-    stack_len = TOP_OF_ARGS - bprm->p;             /* the strings */
+    stack_len = 0;
+    for (i = 0; i < bprm->argc; ++i) {
+        /* the argv strings */
+        stack_len += strlen(bprm->argv[i]);
+    }
+    for (i = 0; i < bprm->envc; ++i) {
+        /* the envp strings */
+        stack_len += strlen(bprm->envp[i]);
+    }
     stack_len += (bprm->argc + 1) * 4; /* the argv array */
     stack_len += (bprm->envc + 1) * 4; /* the envp array */
 
commit 906c1b8ec8ed8987662e2697af20b9ca19c659b5
Author: Mike Frysinger <vapier at gentoo.org>
Date:   Mon Feb 7 01:05:52 2011 -0500

    linux-user: decode MAP_{UNINITIALIZED,EXECUTABLE} in strace
    
    Signed-off-by: Mike Frysinger <vapier at gentoo.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/strace.c b/linux-user/strace.c
index bf9a0d9..a8786bb 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -398,6 +398,7 @@ UNUSED static struct flags mmap_flags[] = {
     FLAG_TARGET(MAP_DENYWRITE),
     FLAG_TARGET(MAP_FIXED),
     FLAG_TARGET(MAP_GROWSDOWN),
+    FLAG_TARGET(MAP_EXECUTABLE),
 #ifdef MAP_LOCKED
     FLAG_TARGET(MAP_LOCKED),
 #endif
@@ -408,6 +409,9 @@ UNUSED static struct flags mmap_flags[] = {
 #ifdef MAP_POPULATE
     FLAG_TARGET(MAP_POPULATE),
 #endif
+#ifdef TARGET_MAP_UNINITIALIZED
+    FLAG_TARGET(MAP_UNINITIALIZED),
+#endif
     FLAG_END,
 };
 
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index d02a9bf..4742ac0 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -999,6 +999,7 @@ struct target_winsize {
 #define TARGET_MAP_NORESERVE	0x4000		/* don't check for reservations */
 #define TARGET_MAP_POPULATE	0x8000		/* populate (prefault) pagetables */
 #define TARGET_MAP_NONBLOCK	0x10000		/* do not block on IO */
+#define TARGET_MAP_UNINITIALIZED 0x4000000	/* for anonymous mmap, memory could be uninitialized */
 #endif
 
 #if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_CRIS)
commit d8035d4cfce42e0268e39e109d5abf01d9f25259
Author: Mike Frysinger <vapier at gentoo.org>
Date:   Mon Feb 7 01:05:51 2011 -0500

    linux-user: add ppoll syscall support
    
    Some architectures (like Blackfin) only implement ppoll (and skip poll).
    So add support for it using existing poll code.
    
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Mike Frysinger <vapier at gentoo.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 6116ab5..bb6ef43 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -529,6 +529,15 @@ static int sys_inotify_init1(int flags)
 #undef TARGET_NR_inotify_rm_watch
 #endif /* CONFIG_INOTIFY  */
 
+#if defined(TARGET_NR_ppoll)
+#ifndef __NR_ppoll
+# define __NR_ppoll -1
+#endif
+#define __NR_sys_ppoll __NR_ppoll
+_syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds,
+          struct timespec *, timeout, const __sigset_t *, sigmask,
+          size_t, sigsetsize)
+#endif
 
 extern int personality(int);
 extern int flock(int, int);
@@ -6230,8 +6239,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         ret = do_select(arg1, arg2, arg3, arg4, arg5);
         break;
 #endif
-#ifdef TARGET_NR_poll
+#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
+# ifdef TARGET_NR_poll
     case TARGET_NR_poll:
+# endif
+# ifdef TARGET_NR_ppoll
+    case TARGET_NR_ppoll:
+# endif
         {
             struct target_pollfd *target_pfd;
             unsigned int nfds = arg2;
@@ -6242,12 +6256,51 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
             if (!target_pfd)
                 goto efault;
+
             pfd = alloca(sizeof(struct pollfd) * nfds);
             for(i = 0; i < nfds; i++) {
                 pfd[i].fd = tswap32(target_pfd[i].fd);
                 pfd[i].events = tswap16(target_pfd[i].events);
             }
-            ret = get_errno(poll(pfd, nfds, timeout));
+
+# ifdef TARGET_NR_ppoll
+            if (num == TARGET_NR_ppoll) {
+                struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
+                target_sigset_t *target_set;
+                sigset_t _set, *set = &_set;
+
+                if (arg3) {
+                    if (target_to_host_timespec(timeout_ts, arg3)) {
+                        unlock_user(target_pfd, arg1, 0);
+                        goto efault;
+                    }
+                } else {
+                    timeout_ts = NULL;
+                }
+
+                if (arg4) {
+                    target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1);
+                    if (!target_set) {
+                        unlock_user(target_pfd, arg1, 0);
+                        goto efault;
+                    }
+                    target_to_host_sigset(set, target_set);
+                } else {
+                    set = NULL;
+                }
+
+                ret = get_errno(sys_ppoll(pfd, nfds, timeout_ts, set, _NSIG/8));
+
+                if (!is_error(ret) && arg3) {
+                    host_to_target_timespec(arg3, timeout_ts);
+                }
+                if (arg4) {
+                    unlock_user(target_set, arg4, 0);
+                }
+            } else
+# endif
+                ret = get_errno(poll(pfd, nfds, timeout));
+
             if (!is_error(ret)) {
                 for(i = 0; i < nfds; i++) {
                     target_pfd[i].revents = tswap16(pfd[i].revents);
commit 1af02e83c00fe269fbbaeaccc7c0b914ad277d18
Author: Mike Frysinger <vapier at gentoo.org>
Date:   Mon Feb 7 01:05:50 2011 -0500

    linux-user/elfload: add FDPIC support
    
    Signed-off-by: Mike Frysinger <vapier at gentoo.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/elf.h b/elf.h
index 7067c90..d2f24f4 100644
--- a/elf.h
+++ b/elf.h
@@ -1191,6 +1191,25 @@ typedef struct elf64_note {
   Elf64_Word n_type;	/* Content type */
 } Elf64_Nhdr;
 
+
+/* This data structure represents a PT_LOAD segment.  */
+struct elf32_fdpic_loadseg {
+  /* Core address to which the segment is mapped.  */
+  Elf32_Addr addr;
+  /* VMA recorded in the program header.  */
+  Elf32_Addr p_vaddr;
+  /* Size of this segment in memory.  */
+  Elf32_Word p_memsz;
+};
+struct elf32_fdpic_loadmap {
+  /* Protocol version number, must be zero.  */
+  Elf32_Half version;
+  /* Number of segments in this map.  */
+  Elf32_Half nsegs;
+  /* The actual memory map.  */
+  struct elf32_fdpic_loadseg segs[/*nsegs*/];
+};
+
 #ifdef ELF_CLASS
 #if ELF_CLASS == ELFCLASS32
 
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 08c44d8..2de83e4 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1075,6 +1075,33 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
     }
 }
 
+#ifdef CONFIG_USE_FDPIC
+static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp)
+{
+    uint16_t n;
+    struct elf32_fdpic_loadseg *loadsegs = info->loadsegs;
+
+    /* elf32_fdpic_loadseg */
+    n = info->nsegs;
+    while (n--) {
+        sp -= 12;
+        put_user_u32(loadsegs[n].addr, sp+0);
+        put_user_u32(loadsegs[n].p_vaddr, sp+4);
+        put_user_u32(loadsegs[n].p_memsz, sp+8);
+    }
+
+    /* elf32_fdpic_loadmap */
+    sp -= 4;
+    put_user_u16(0, sp+0); /* version */
+    put_user_u16(info->nsegs, sp+2); /* nsegs */
+
+    info->personality = PER_LINUX_FDPIC;
+    info->loadmap_addr = sp;
+
+    return sp;
+}
+#endif
+
 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    struct elfhdr *exec,
                                    struct image_info *info,
@@ -1087,6 +1114,21 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     const int n = sizeof(elf_addr_t);
 
     sp = p;
+
+#ifdef CONFIG_USE_FDPIC
+    /* Needs to be before we load the env/argc/... */
+    if (elf_is_fdpic(exec)) {
+        /* Need 4 byte alignment for these structs */
+        sp &= ~3;
+        sp = loader_build_fdpic_loadmap(info, sp);
+        info->other_info = interp_info;
+        if (interp_info) {
+            interp_info->other_info = info;
+            sp = loader_build_fdpic_loadmap(interp_info, sp);
+        }
+    }
+#endif
+
     u_platform = 0;
     k_platform = ELF_PLATFORM;
     if (k_platform) {
@@ -1197,6 +1239,11 @@ static void load_elf_image(const char *image_name, int image_fd,
     }
     bswap_phdr(phdr, ehdr->e_phnum);
 
+#ifdef CONFIG_USE_FDPIC
+    info->nsegs = 0;
+    info->pt_dynamic_addr = 0;
+#endif
+
     /* Find the maximum size of the image and allocate an appropriate
        amount of memory to handle that.  */
     loaddr = -1, hiaddr = 0;
@@ -1210,6 +1257,9 @@ static void load_elf_image(const char *image_name, int image_fd,
             if (a > hiaddr) {
                 hiaddr = a;
             }
+#ifdef CONFIG_USE_FDPIC
+            ++info->nsegs;
+#endif
         }
     }
 
@@ -1290,6 +1340,27 @@ static void load_elf_image(const char *image_name, int image_fd,
     }
     load_bias = load_addr - loaddr;
 
+#ifdef CONFIG_USE_FDPIC
+    {
+        struct elf32_fdpic_loadseg *loadsegs = info->loadsegs =
+            qemu_malloc(sizeof(*loadsegs) * info->nsegs);
+
+        for (i = 0; i < ehdr->e_phnum; ++i) {
+            switch (phdr[i].p_type) {
+            case PT_DYNAMIC:
+                info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias;
+                break;
+            case PT_LOAD:
+                loadsegs->addr = phdr[i].p_vaddr + load_bias;
+                loadsegs->p_vaddr = phdr[i].p_vaddr;
+                loadsegs->p_memsz = phdr[i].p_memsz;
+                ++loadsegs;
+                break;
+            }
+        }
+    }
+#endif
+
     info->load_bias = load_bias;
     info->load_addr = load_addr;
     info->entry = ehdr->e_entry + load_bias;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 32de241..250814d 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -51,6 +51,13 @@ struct image_info {
         abi_ulong       arg_start;
         abi_ulong       arg_end;
 	int		personality;
+#ifdef CONFIG_USE_FDPIC
+        abi_ulong       loadmap_addr;
+        uint16_t        nsegs;
+        void           *loadsegs;
+        abi_ulong       pt_dynamic_addr;
+        struct image_info *other_info;
+#endif
 };
 
 #ifdef TARGET_I386
commit 73160d952922157f16946e8ebb4419072de4c657
Author: Mike Frysinger <vapier at gentoo.org>
Date:   Mon Feb 7 01:05:49 2011 -0500

    linux-user: fix sizeof handling for getsockopt
    
    Signed-off-by: Mike Frysinger <vapier at gentoo.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 499c4d7..6116ab5 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1448,7 +1448,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
             return -TARGET_EFAULT;
         if (len < 0)
             return -TARGET_EINVAL;
-        lv = sizeof(int);
+        lv = sizeof(lv);
         ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
         if (ret < 0)
             return ret;
@@ -1485,7 +1485,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
                 return -TARGET_EFAULT;
             if (len < 0)
                 return -TARGET_EINVAL;
-            lv = sizeof(int);
+            lv = sizeof(lv);
             ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
             if (ret < 0)
                 return ret;
commit 8d79de6e42947a4a11ad7c7bb87e8f745a4f8321
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Mon Jan 17 21:36:06 2011 +0100

    linux-user: Fix possible realloc memory leak
    
    Extract from "man realloc":
    "If realloc() fails the original block is left untouched;
    it is not freed or moved."
    
    Fix a possible memory leak (reported by cppcheck).
    
    Cc: Riku Voipio <riku.voipio at iki.fi>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 33d776d..08c44d8 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1481,7 +1481,7 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
     struct elf_shdr *shdr;
     char *strings;
     struct syminfo *s;
-    struct elf_sym *syms;
+    struct elf_sym *syms, *new_syms;
 
     shnum = hdr->e_shnum;
     i = shnum * sizeof(struct elf_shdr);
@@ -1550,12 +1550,14 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
        that we threw away.  Whether or not this has any effect on the
        memory allocation depends on the malloc implementation and how
        many symbols we managed to discard.  */
-    syms = realloc(syms, nsyms * sizeof(*syms));
-    if (syms == NULL) {
+    new_syms = realloc(syms, nsyms * sizeof(*syms));
+    if (new_syms == NULL) {
         free(s);
+        free(syms);
         free(strings);
         return;
     }
+    syms = new_syms;
 
     qsort(syms, nsyms, sizeof(*syms), symcmp);
 
commit 6672b0b22a8ab92ad3a07889c2220a7568a3da30
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Jan 20 03:28:02 2011 +0000

    linux-user: Add support for -version option
    
    Add support to the linux-user qemu for the -version command line
    option, bringing it into line with the system emulation qemu.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Riku Voipio <riku.voipio at nokia.com>

diff --git a/linux-user/main.c b/linux-user/main.c
index 0d627d6..e651bfd 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2624,14 +2624,21 @@ void cpu_loop (CPUState *env)
 }
 #endif /* TARGET_ALPHA */
 
+static void version(void)
+{
+    printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION
+           ", Copyright (c) 2003-2008 Fabrice Bellard\n");
+}
+
 static void usage(void)
 {
-    printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n"
-           "usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
+    version();
+    printf("usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
            "Linux CPU emulator (compiled for %s emulation)\n"
            "\n"
            "Standard options:\n"
            "-h                print this help\n"
+           "-version          display version information and exit\n"
            "-g port           wait gdb connection to port\n"
            "-L path           set the elf interpreter prefix (default=%s)\n"
            "-s size           set the stack size in bytes (default=%ld)\n"
@@ -2886,8 +2893,10 @@ int main(int argc, char **argv, char **envp)
             singlestep = 1;
         } else if (!strcmp(r, "strace")) {
             do_strace = 1;
-        } else
-        {
+        } else if (!strcmp(r, "version")) {
+            version();
+            exit(0);
+        } else {
             usage();
         }
     }
commit c0c1dc992584b8ccbae0e8f8b09124b76662633b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Tue Feb 8 18:18:19 2011 +0100

    cris, microblaze: use cpu_has_work
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-cris/exec.h b/target-cris/exec.h
index 93ce768..34c0132 100644
--- a/target-cris/exec.h
+++ b/target-cris/exec.h
@@ -37,9 +37,7 @@ static inline int cpu_halted(CPUState *env) {
 	if (!env->halted)
 		return 0;
 
-	/* IRQ, NMI and GURU execeptions wakes us up.  */
-	if (env->interrupt_request
-	    & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI)) {
+	if (cpu_has_work(env)) {
 		env->halted = 0;
 		return 0;
 	}
diff --git a/target-microblaze/exec.h b/target-microblaze/exec.h
index 87b2494..ab19828 100644
--- a/target-microblaze/exec.h
+++ b/target-microblaze/exec.h
@@ -36,9 +36,7 @@ static inline int cpu_halted(CPUState *env) {
 	if (!env->halted)
 		return 0;
 
-	/* IRQ, NMI and GURU execeptions wakes us up.  */
-	if (env->interrupt_request
-	    & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI)) {
+	if (cpu_has_work(env)) {
 		env->halted = 0;
 		return 0;
 	}
commit 29057492871e63caeab8ee7cdf1062c0270f19d8
Author: Jan Kiszka <jan.kiszka at web.de>
Date:   Fri Feb 4 13:47:25 2011 -0200

    x86: Fix MCA broadcast parameters for TCG case
    
    When broadcasting MCEs, we need to set MCIP and RIPV in mcg_status like
    it is done for KVM. Use the symbolic constants at this chance.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-i386/helper.c b/target-i386/helper.c
index 1217452..f0c546d 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1147,8 +1147,8 @@ void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
                 if (cenv == env) {
                     continue;
                 }
-
-                qemu_inject_x86_mce(env, 1, 0xa000000000000000, 0, 0, 0);
+                qemu_inject_x86_mce(env, 1, MCI_STATUS_VAL | MCI_STATUS_UC,
+                                    MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0);
             }
         }
     }
commit f26e5a54f0554798a2e6f7a074b809b13635d007
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Fri Feb 4 22:01:32 2011 +0100

    qemu-timer: Fix compilation of new timer code for w32, w64
    
    qemu_next_alarm_deadline() is needed by MinGW, too.
    
    Cc: Paolo Bonzini <pbonzini at redhat.com>
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index 658f637..b0db780 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -708,8 +708,6 @@ int64_t qemu_next_deadline(void)
     return delta;
 }
 
-#ifndef _WIN32
-
 static int64_t qemu_next_alarm_deadline(void)
 {
     int64_t delta;
@@ -922,6 +920,8 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
 
 #endif /* defined(__linux__) */
 
+#if !defined(_WIN32)
+
 static int unix_start_timer(struct qemu_alarm_timer *t)
 {
     struct sigaction act;
commit 8591675f44929a9e4b5d3a5fd702a4b6d41c7903
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Jan 26 12:12:35 2011 -0200

    block: enable in_use flag
    
    Set block device in use during block migration, disallow drive_del and
    bdrv_truncate for in use devices.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index 323e1e2..8218bac 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -301,6 +301,7 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
         bmds->shared_base = block_mig_state.shared_base;
         alloc_aio_bitmap(bmds);
         drive_get_ref(drive_get_by_blockdev(bs));
+        bdrv_set_in_use(bs, 1);
 
         block_mig_state.total_sector_sum += sectors;
 
@@ -539,6 +540,7 @@ static void blk_mig_cleanup(Monitor *mon)
 
     while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
         QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
+        bdrv_set_in_use(bmds->bs, 0);
         drive_put_ref(drive_get_by_blockdev(bmds->bs));
         qemu_free(bmds->aio_bitmap);
         qemu_free(bmds);
diff --git a/block.c b/block.c
index ee9edfc..b476479 100644
--- a/block.c
+++ b/block.c
@@ -1132,6 +1132,8 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
         return -ENOTSUP;
     if (bs->read_only)
         return -EACCES;
+    if (bdrv_in_use(bs))
+        return -EBUSY;
     ret = drv->bdrv_truncate(bs, offset);
     if (ret == 0) {
         ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
diff --git a/blockdev.c b/blockdev.c
index f2a00bd..ecfadc1 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -726,6 +726,10 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
         qerror_report(QERR_DEVICE_NOT_FOUND, id);
         return -1;
     }
+    if (bdrv_in_use(bs)) {
+        qerror_report(QERR_DEVICE_IN_USE, id);
+        return -1;
+    }
 
     /* quiesce block driver; prevent further io */
     qemu_aio_flush();
commit db593f2565dc12442d6bac9e8eaefa027dfcada9
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Jan 26 12:12:34 2011 -0200

    Add flag to indicate external users to block device
    
    Certain operations such as drive_del or resize cannot be performed
    while external users (eg. block migration) reference the block device.
    
    Add a flag to indicate that.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 998df1b..ee9edfc 100644
--- a/block.c
+++ b/block.c
@@ -2774,6 +2774,17 @@ int64_t bdrv_get_dirty_count(BlockDriverState *bs)
     return bs->dirty_count;
 }
 
+void bdrv_set_in_use(BlockDriverState *bs, int in_use)
+{
+    assert(bs->in_use != in_use);
+    bs->in_use = in_use;
+}
+
+int bdrv_in_use(BlockDriverState *bs)
+{
+    return bs->in_use;
+}
+
 int bdrv_img_create(const char *filename, const char *fmt,
                     const char *base_filename, const char *base_fmt,
                     char *options, uint64_t img_size, int flags)
diff --git a/block.h b/block.h
index 239f729..19f4768 100644
--- a/block.h
+++ b/block.h
@@ -241,6 +241,8 @@ void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
                       int nr_sectors);
 int64_t bdrv_get_dirty_count(BlockDriverState *bs);
 
+void bdrv_set_in_use(BlockDriverState *bs, int in_use);
+int bdrv_in_use(BlockDriverState *bs);
 
 typedef enum {
     BLKDBG_L1_UPDATE,
diff --git a/block_int.h b/block_int.h
index 6ebdc3e..545ad11 100644
--- a/block_int.h
+++ b/block_int.h
@@ -199,6 +199,7 @@ struct BlockDriverState {
     char device_name[32];
     unsigned long *dirty_bitmap;
     int64_t dirty_count;
+    int in_use; /* users other than guest access, eg. block migration */
     QTAILQ_ENTRY(BlockDriverState) list;
     void *private;
 };
commit f48905d44f670cd83227b3a8d06ae1406f0c771c
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Jan 26 12:12:33 2011 -0200

    block-migration: add reference to target DriveInfo
    
    So that ejection of attached device by guest does not free data
    in use by block migration instance.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    CC: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index 483ca7b..323e1e2 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -19,6 +19,7 @@
 #include "monitor.h"
 #include "block-migration.h"
 #include "migration.h"
+#include "blockdev.h"
 #include <assert.h>
 
 #define BLOCK_SIZE (BDRV_SECTORS_PER_DIRTY_CHUNK << BDRV_SECTOR_BITS)
@@ -299,6 +300,7 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
         bmds->completed_sectors = 0;
         bmds->shared_base = block_mig_state.shared_base;
         alloc_aio_bitmap(bmds);
+        drive_get_ref(drive_get_by_blockdev(bs));
 
         block_mig_state.total_sector_sum += sectors;
 
@@ -537,6 +539,7 @@ static void blk_mig_cleanup(Monitor *mon)
 
     while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
         QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
+        drive_put_ref(drive_get_by_blockdev(bmds->bs));
         qemu_free(bmds->aio_bitmap);
         qemu_free(bmds);
     }
commit 84fb392526479d54602a3830326d50d44657f630
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Jan 26 12:12:32 2011 -0200

    blockdev: add refcount to DriveInfo
    
    The host part of a block device can be deleted with in progress
    block migration.
    
    To fix this, add a reference count to DriveInfo, freeing resources
    on last reference.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    CC: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 1c56da0..f2a00bd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -71,7 +71,7 @@ void blockdev_auto_del(BlockDriverState *bs)
     DriveInfo *dinfo = drive_get_by_blockdev(bs);
 
     if (dinfo && dinfo->auto_del) {
-        drive_uninit(dinfo);
+        drive_put_ref(dinfo);
     }
 }
 
@@ -178,7 +178,7 @@ static void bdrv_format_print(void *opaque, const char *name)
     error_printf(" %s", name);
 }
 
-void drive_uninit(DriveInfo *dinfo)
+static void drive_uninit(DriveInfo *dinfo)
 {
     qemu_opts_del(dinfo->opts);
     bdrv_delete(dinfo->bdrv);
@@ -186,6 +186,19 @@ void drive_uninit(DriveInfo *dinfo)
     qemu_free(dinfo);
 }
 
+void drive_put_ref(DriveInfo *dinfo)
+{
+    assert(dinfo->refcount);
+    if (--dinfo->refcount == 0) {
+        drive_uninit(dinfo);
+    }
+}
+
+void drive_get_ref(DriveInfo *dinfo)
+{
+    dinfo->refcount++;
+}
+
 static int parse_block_error_action(const char *buf, int is_read)
 {
     if (!strcmp(buf, "ignore")) {
@@ -453,6 +466,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
     dinfo->bus = bus_id;
     dinfo->unit = unit_id;
     dinfo->opts = opts;
+    dinfo->refcount = 1;
     if (serial)
         strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1);
     QTAILQ_INSERT_TAIL(&drives, dinfo, next);
diff --git a/blockdev.h b/blockdev.h
index 84e462a..2c9e780 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -36,13 +36,15 @@ struct DriveInfo {
     QemuOpts *opts;
     char serial[BLOCK_SERIAL_STRLEN + 1];
     QTAILQ_ENTRY(DriveInfo) next;
+    int refcount;
 };
 
 DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
 DriveInfo *drive_get_by_index(BlockInterfaceType type, int index);
 int drive_get_max_bus(BlockInterfaceType type);
 DriveInfo *drive_get_next(BlockInterfaceType type);
-void drive_uninit(DriveInfo *dinfo);
+void drive_get_ref(DriveInfo *dinfo);
+void drive_put_ref(DriveInfo *dinfo);
 DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
 
 QemuOpts *drive_def(const char *optstr);
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index b6dcbda..478fe9b 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -147,7 +147,7 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
 
 err:
     if (dinfo)
-        drive_uninit(dinfo);
+        drive_put_ref(dinfo);
     return;
 }
 
commit 8f794c557c4b51c7a957d47ef6a2230114bb9e79
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Jan 26 12:12:31 2011 -0200

    block-migration: actually disable dirty tracking on cleanup
    
    Call to set_dirty_tracking() is misplaced.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index c9d3e81..483ca7b 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -533,6 +533,8 @@ static void blk_mig_cleanup(Monitor *mon)
     BlkMigDevState *bmds;
     BlkMigBlock *blk;
 
+    set_dirty_tracking(0);
+
     while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
         QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
         qemu_free(bmds->aio_bitmap);
@@ -545,8 +547,6 @@ static void blk_mig_cleanup(Monitor *mon)
         qemu_free(blk);
     }
 
-    set_dirty_tracking(0);
-
     monitor_printf(mon, "\n");
 }
 
commit 2c4b9d0ea42c27ec2112e437a0fa954afe73bd23
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Feb 1 15:51:31 2011 +0100

    ahci: make number of ports runtime determined
    
    Different AHCI controllers have a different number of ports, so the core
    shouldn't care about the amount of ports available.
    
    This patch makes the number of ports available to the AHCI core runtime
    configurable, allowing us to have multiple different AHCI implementations
    with different amounts of ports.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 105dd53..98bdf70 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -145,7 +145,7 @@ static void ahci_check_irq(AHCIState *s)
 
     DPRINTF(-1, "check irq %#x\n", s->control_regs.irqstatus);
 
-    for (i = 0; i < SATA_PORTS; i++) {
+    for (i = 0; i < s->ports; i++) {
         AHCIPortRegs *pr = &s->dev[i].port_regs;
         if (pr->irq_stat & pr->irq_mask) {
             s->control_regs.irqstatus |= (1 << i);
@@ -303,7 +303,8 @@ static uint32_t ahci_mem_readl(void *ptr, target_phys_addr_t addr)
 
         DPRINTF(-1, "(addr 0x%08X), val 0x%08X\n", (unsigned) addr, val);
     } else if ((addr >= AHCI_PORT_REGS_START_ADDR) &&
-               (addr < AHCI_PORT_REGS_END_ADDR)) {
+               (addr < (AHCI_PORT_REGS_START_ADDR +
+                (s->ports * AHCI_PORT_ADDR_OFFSET_LEN)))) {
         val = ahci_port_read(s, (addr - AHCI_PORT_REGS_START_ADDR) >> 7,
                              addr & AHCI_PORT_ADDR_OFFSET_MASK);
     }
@@ -355,7 +356,8 @@ static void ahci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
                 DPRINTF(-1, "write to unknown register 0x%x\n", (unsigned)addr);
         }
     } else if ((addr >= AHCI_PORT_REGS_START_ADDR) &&
-               (addr < AHCI_PORT_REGS_END_ADDR)) {
+               (addr < (AHCI_PORT_REGS_START_ADDR +
+                (s->ports * AHCI_PORT_ADDR_OFFSET_LEN)))) {
         ahci_port_write(s, (addr - AHCI_PORT_REGS_START_ADDR) >> 7,
                         addr & AHCI_PORT_ADDR_OFFSET_MASK, val);
     }
@@ -378,16 +380,16 @@ static void ahci_reg_init(AHCIState *s)
 {
     int i;
 
-    s->control_regs.cap = (SATA_PORTS - 1) |
+    s->control_regs.cap = (s->ports - 1) |
                           (AHCI_NUM_COMMAND_SLOTS << 8) |
                           (AHCI_SUPPORTED_SPEED_GEN1 << AHCI_SUPPORTED_SPEED) |
                           HOST_CAP_NCQ | HOST_CAP_AHCI;
 
-    s->control_regs.impl = (1 << SATA_PORTS) - 1;
+    s->control_regs.impl = (1 << s->ports) - 1;
 
     s->control_regs.version = AHCI_VERSION_1_0;
 
-    for (i = 0; i < SATA_PORTS; i++) {
+    for (i = 0; i < s->ports; i++) {
         s->dev[i].port_state = STATE_RUN;
     }
 }
@@ -1096,17 +1098,19 @@ static const IDEDMAOps ahci_dma_ops = {
     .reset = ahci_dma_reset,
 };
 
-void ahci_init(AHCIState *s, DeviceState *qdev)
+void ahci_init(AHCIState *s, DeviceState *qdev, int ports)
 {
     qemu_irq *irqs;
     int i;
 
+    s->ports = ports;
+    s->dev = qemu_mallocz(sizeof(AHCIDevice) * ports);
     ahci_reg_init(s);
     s->mem = cpu_register_io_memory(ahci_readfn, ahci_writefn, s,
                                     DEVICE_LITTLE_ENDIAN);
-    irqs = qemu_allocate_irqs(ahci_irq_set, s, SATA_PORTS);
+    irqs = qemu_allocate_irqs(ahci_irq_set, s, s->ports);
 
-    for (i = 0; i < SATA_PORTS; i++) {
+    for (i = 0; i < s->ports; i++) {
         AHCIDevice *ad = &s->dev[i];
 
         ide_bus_new(&ad->port, qdev, i);
@@ -1120,6 +1124,11 @@ void ahci_init(AHCIState *s, DeviceState *qdev)
     }
 }
 
+void ahci_uninit(AHCIState *s)
+{
+    qemu_free(s->dev);
+}
+
 void ahci_pci_map(PCIDevice *pci_dev, int region_num,
         pcibus_t addr, pcibus_t size, int type)
 {
@@ -1137,7 +1146,7 @@ void ahci_reset(void *opaque)
     d->ahci.control_regs.irqstatus = 0;
     d->ahci.control_regs.ghc = 0;
 
-    for (i = 0; i < SATA_PORTS; i++) {
+    for (i = 0; i < d->ahci.ports; i++) {
         ahci_reset_port(&d->ahci, i);
     }
 }
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index b2786d1..a4560c4 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -188,11 +188,9 @@
 #define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20
                                             /* Shouldn't this be 0x2c? */
 
-#define SATA_PORTS                         4
-
 #define AHCI_PORT_REGS_START_ADDR          0x100
-#define AHCI_PORT_REGS_END_ADDR (AHCI_PORT_REGS_START_ADDR + SATA_PORTS * 0x80)
 #define AHCI_PORT_ADDR_OFFSET_MASK         0x7f
+#define AHCI_PORT_ADDR_OFFSET_LEN          0x80
 
 #define AHCI_NUM_COMMAND_SLOTS             31
 #define AHCI_SUPPORTED_SPEED               20
@@ -289,9 +287,10 @@ struct AHCIDevice {
 };
 
 typedef struct AHCIState {
-    AHCIDevice dev[SATA_PORTS];
+    AHCIDevice *dev;
     AHCIControlRegs control_regs;
     int mem;
+    int ports;
     qemu_irq irq;
 } AHCIState;
 
@@ -323,7 +322,8 @@ typedef struct NCQFrame {
     uint8_t reserved10;
 } __attribute__ ((packed)) NCQFrame;
 
-void ahci_init(AHCIState *s, DeviceState *qdev);
+void ahci_init(AHCIState *s, DeviceState *qdev, int ports);
+void ahci_uninit(AHCIState *s);
 
 void ahci_pci_map(PCIDevice *pci_dev, int region_num,
         pcibus_t addr, pcibus_t size, int type);
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 70cb766..f242d7a 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -100,7 +100,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
 
     msi_init(dev, 0x50, 1, true, false);
 
-    ahci_init(&d->ahci, &dev->qdev);
+    ahci_init(&d->ahci, &dev->qdev, 6);
     d->ahci.irq = d->card.irq[0];
 
     return 0;
@@ -116,6 +116,7 @@ static int pci_ich9_uninit(PCIDevice *dev)
     }
 
     qemu_unregister_reset(ahci_reset, d);
+    ahci_uninit(&d->ahci);
 
     return 0;
 }
commit 760c3e44d3a1d8a7e9d22f0429b1805d1c688178
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Feb 1 15:51:30 2011 +0100

    ahci: Implement HBA reset
    
    The ahci code was missing its soft reset functionality. This wasn't really an
    issue for Linux guests, but Windows gets confused when the controller doesn't
    reset when it tells it so.
    
    Using this patch I can now successfully boot Windows 7 from AHCI using AHCI
    enabled SeaBIOS.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index e6ac77c..105dd53 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -335,7 +335,7 @@ static void ahci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
             case HOST_CTL: /* R/W */
                 if (val & HOST_CTL_RESET) {
                     DPRINTF(-1, "HBA Reset\n");
-                    /* FIXME reset? */
+                    ahci_reset(container_of(s, AHCIPCIState, ahci));
                 } else {
                     s->control_regs.ghc = (val & 0x3) | HOST_CTL_AHCI_EN;
                     ahci_check_irq(s);
@@ -1134,6 +1134,9 @@ void ahci_reset(void *opaque)
     struct AHCIPCIState *d = opaque;
     int i;
 
+    d->ahci.control_regs.irqstatus = 0;
+    d->ahci.control_regs.ghc = 0;
+
     for (i = 0; i < SATA_PORTS; i++) {
         ahci_reset_port(&d->ahci, i);
     }
commit 87e62065bb5e0e544e45e6935e3ac2b053fe446e
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Feb 1 15:51:29 2011 +0100

    ahci: send init d2h fis on fis enable
    
    The drive sends a d2h init fis on initialization. Usually, the guest doesn't
    receive fises yet at that point though, so the delivery is deferred.
    
    Let's reflect that by sending the init fis on fis receive enablement.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 6822046..e6ac77c 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -47,6 +47,7 @@ static void check_cmd(AHCIState *s, int port);
 static int handle_cmd(AHCIState *s,int port,int slot);
 static void ahci_reset_port(AHCIState *s, int port);
 static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis);
+static void ahci_init_d2h(AHCIDevice *ad);
 
 static uint32_t  ahci_port_read(AHCIState *s, int port, int offset)
 {
@@ -230,6 +231,16 @@ static void  ahci_port_write(AHCIState *s, int port, int offset, uint32_t val)
                 pr->cmd |= PORT_CMD_FIS_ON;
             }
 
+            /* XXX usually the FIS would be pending on the bus here and
+                   issuing deferred until the OS enables FIS receival.
+                   Instead, we only submit it once - which works in most
+                   cases, but is a hack. */
+            if ((pr->cmd & PORT_CMD_FIS_ON) &&
+                !s->dev[port].init_d2h_sent) {
+                ahci_init_d2h(&s->dev[port]);
+                s->dev[port].init_d2h_sent = 1;
+            }
+
             check_cmd(s, port);
             break;
         case PORT_TFDATA:
@@ -462,12 +473,29 @@ static void ahci_check_cmd_bh(void *opaque)
     check_cmd(ad->hba, ad->port_no);
 }
 
+static void ahci_init_d2h(AHCIDevice *ad)
+{
+    uint8_t init_fis[0x20];
+    IDEState *ide_state = &ad->port.ifs[0];
+
+    memset(init_fis, 0, sizeof(init_fis));
+
+    init_fis[4] = 1;
+    init_fis[12] = 1;
+
+    if (ide_state->drive_kind == IDE_CD) {
+        init_fis[5] = ide_state->lcyl;
+        init_fis[6] = ide_state->hcyl;
+    }
+
+    ahci_write_fis_d2h(ad, init_fis);
+}
+
 static void ahci_reset_port(AHCIState *s, int port)
 {
     AHCIDevice *d = &s->dev[port];
     AHCIPortRegs *pr = &d->port_regs;
     IDEState *ide_state = &d->port.ifs[0];
-    uint8_t init_fis[0x20];
     int i;
 
     DPRINTF(port, "reset port\n");
@@ -482,6 +510,7 @@ static void ahci_reset_port(AHCIState *s, int port)
     pr->scr_err = 0;
     pr->scr_act = 0;
     d->busy_slot = -1;
+    d->init_d2h_sent = 0;
 
     ide_state = &s->dev[port].port.ifs[0];
     if (!ide_state->bs) {
@@ -504,7 +533,6 @@ static void ahci_reset_port(AHCIState *s, int port)
         ncq_tfs->used = 0;
     }
 
-    memset(init_fis, 0, sizeof(init_fis));
     s->dev[port].port_state = STATE_RUN;
     if (!ide_state->bs) {
         s->dev[port].port_regs.sig = 0;
@@ -514,8 +542,6 @@ static void ahci_reset_port(AHCIState *s, int port)
         ide_state->lcyl = 0x14;
         ide_state->hcyl = 0xeb;
         DPRINTF(port, "set lcyl = %d\n", ide_state->lcyl);
-        init_fis[5] = ide_state->lcyl;
-        init_fis[6] = ide_state->hcyl;
         ide_state->status = SEEK_STAT | WRERR_STAT | READY_STAT;
     } else {
         s->dev[port].port_regs.sig = SATA_SIGNATURE_DISK;
@@ -523,9 +549,7 @@ static void ahci_reset_port(AHCIState *s, int port)
     }
 
     ide_state->error = 1;
-    init_fis[4] = 1;
-    init_fis[12] = 1;
-    ahci_write_fis_d2h(d, init_fis);
+    ahci_init_d2h(d);
 }
 
 static void debug_print_fis(uint8_t *fis, int cmd_len)
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index d65b5e3..b2786d1 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -282,6 +282,7 @@ struct AHCIDevice {
     int dma_status;
     int done_atapi_packet;
     int busy_slot;
+    int init_d2h_sent;
     BlockDriverCompletionFunc *dma_cb;
     AHCICmdHdr *cur_cmd;
     NCQTransferState ncq_tfs[AHCI_MAX_CMDS];
commit 7fb6577b130c615e42e1ccf8dad69c27c3eef085
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Feb 1 15:51:28 2011 +0100

    ahci: split ICH and AHCI even more
    
    Sebastian's patch already did a pretty good job at splitting up ICH-9
    AHCI code and the AHCI core. We need some more though. Copyright was missing,
    the lspci dump belongs to ICH-9, we don't need the AHCI core to have its
    own qdev device duplicate.
    
    So let's split them a bit more in this patch, making things easier to
    read an understand.
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 28412d0..6822046 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -19,47 +19,6 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  *
- *
- * lspci dump of a ICH-9 real device in IDE mode (hopefully close enough):
- *
- * 00:1f.2 SATA controller [0106]: Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA AHCI Controller [8086:2922] (rev 02) (prog-if 01 [AHCI 1.0])
- *         Subsystem: Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA AHCI Controller [8086:2922]
- *         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
- *         Status: Cap+ 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
- *         Latency: 0
- *         Interrupt: pin B routed to IRQ 222
- *         Region 0: I/O ports at d000 [size=8]
- *         Region 1: I/O ports at cc00 [size=4]
- *         Region 2: I/O ports at c880 [size=8]
- *         Region 3: I/O ports at c800 [size=4]
- *         Region 4: I/O ports at c480 [size=32]
- *         Region 5: Memory at febf9000 (32-bit, non-prefetchable) [size=2K]
- *         Capabilities: [80] Message Signalled Interrupts: Mask- 64bit- Count=1/16 Enable+
- *                 Address: fee0f00c  Data: 41d9
- *         Capabilities: [70] Power Management version 3
- *                 Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot+,D3cold-)
- *                 Status: D0 PME-Enable- DSel=0 DScale=0 PME-
- *         Capabilities: [a8] SATA HBA <?>
- *         Capabilities: [b0] Vendor Specific Information <?>
- *         Kernel driver in use: ahci
- *         Kernel modules: ahci
- * 00: 86 80 22 29 07 04 b0 02 02 01 06 01 00 00 00 00
- * 10: 01 d0 00 00 01 cc 00 00 81 c8 00 00 01 c8 00 00
- * 20: 81 c4 00 00 00 90 bf fe 00 00 00 00 86 80 22 29
- * 30: 00 00 00 00 80 00 00 00 00 00 00 00 0f 02 00 00
- * 40: 00 80 00 80 00 00 00 00 00 00 00 00 00 00 00 00
- * 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 70: 01 a8 03 40 08 00 00 00 00 00 00 00 00 00 00 00
- * 80: 05 70 09 00 0c f0 e0 fe d9 41 00 00 00 00 00 00
- * 90: 40 00 0f 82 93 01 00 00 00 00 00 00 00 00 00 00
- * a0: ac 00 00 00 0a 00 12 00 12 b0 10 00 48 00 00 00
- * b0: 09 00 06 20 00 00 00 00 00 00 00 00 00 00 00 00
- * c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * f0: 00 00 00 00 00 00 00 00 86 0f 02 00 00 00 00 00
- *
  */
 
 #include <hw/hw.h>
@@ -1155,72 +1114,3 @@ void ahci_reset(void *opaque)
         ahci_reset_port(&d->ahci, i);
     }
 }
-
-static int pci_ahci_init(PCIDevice *dev)
-{
-    struct AHCIPCIState *d;
-    d = DO_UPCAST(struct AHCIPCIState, card, dev);
-
-    pci_config_set_vendor_id(d->card.config, PCI_VENDOR_ID_INTEL);
-    pci_config_set_device_id(d->card.config, PCI_DEVICE_ID_INTEL_82801IR);
-
-    pci_config_set_class(d->card.config, PCI_CLASS_STORAGE_SATA);
-    pci_config_set_revision(d->card.config, 0x02);
-    pci_config_set_prog_interface(d->card.config, AHCI_PROGMODE_MAJOR_REV_1);
-
-    d->card.config[PCI_CACHE_LINE_SIZE] = 0x08;  /* Cache line size */
-    d->card.config[PCI_LATENCY_TIMER]   = 0x00;  /* Latency timer */
-    pci_config_set_interrupt_pin(d->card.config, 1);
-
-    /* XXX Software should program this register */
-    d->card.config[0x90]   = 1 << 6; /* Address Map Register - AHCI mode */
-
-    qemu_register_reset(ahci_reset, d);
-
-    /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
-    pci_register_bar(&d->card, 5, 0x1000, PCI_BASE_ADDRESS_SPACE_MEMORY,
-                     ahci_pci_map);
-
-    msi_init(dev, 0x50, 1, true, false);
-
-    ahci_init(&d->ahci, &dev->qdev);
-    d->ahci.irq = d->card.irq[0];
-
-    return 0;
-}
-
-static int pci_ahci_uninit(PCIDevice *dev)
-{
-    struct AHCIPCIState *d;
-    d = DO_UPCAST(struct AHCIPCIState, card, dev);
-
-    if (msi_enabled(dev)) {
-        msi_uninit(dev);
-    }
-
-    qemu_unregister_reset(ahci_reset, d);
-
-    return 0;
-}
-
-static void pci_ahci_write_config(PCIDevice *pci, uint32_t addr,
-                                  uint32_t val, int len)
-{
-    pci_default_write_config(pci, addr, val, len);
-    msi_write_config(pci, addr, val, len);
-}
-
-static PCIDeviceInfo ahci_info = {
-    .qdev.name  = "ahci",
-    .qdev.size  = sizeof(AHCIPCIState),
-    .init       = pci_ahci_init,
-    .exit       = pci_ahci_uninit,
-    .config_write = pci_ahci_write_config,
-};
-
-static void ahci_pci_register_devices(void)
-{
-    pci_qdev_register(&ahci_info);
-}
-
-device_init(ahci_pci_register_devices)
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 9868b73..70cb766 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -1,3 +1,65 @@
+/*
+ * QEMU ICH Emulation
+ *
+ * Copyright (c) 2010 Sebastian Herbszt <herbszt at gmx.de>
+ * Copyright (c) 2010 Alexander Graf <agraf at suse.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * lspci dump of a ICH-9 real device
+ *
+ * 00:1f.2 SATA controller [0106]: Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA AHCI Controller [8086:2922] (rev 02) (prog-if 01 [AHCI 1.0])
+ *         Subsystem: Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA AHCI Controller [8086:2922]
+ *         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
+ *         Status: Cap+ 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
+ *         Latency: 0
+ *         Interrupt: pin B routed to IRQ 222
+ *         Region 0: I/O ports at d000 [size=8]
+ *         Region 1: I/O ports at cc00 [size=4]
+ *         Region 2: I/O ports at c880 [size=8]
+ *         Region 3: I/O ports at c800 [size=4]
+ *         Region 4: I/O ports at c480 [size=32]
+ *         Region 5: Memory at febf9000 (32-bit, non-prefetchable) [size=2K]
+ *         Capabilities: [80] Message Signalled Interrupts: Mask- 64bit- Count=1/16 Enable+
+ *                 Address: fee0f00c  Data: 41d9
+ *         Capabilities: [70] Power Management version 3
+ *                 Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot+,D3cold-)
+ *                 Status: D0 PME-Enable- DSel=0 DScale=0 PME-
+ *         Capabilities: [a8] SATA HBA <?>
+ *         Capabilities: [b0] Vendor Specific Information <?>
+ *         Kernel driver in use: ahci
+ *         Kernel modules: ahci
+ * 00: 86 80 22 29 07 04 b0 02 02 01 06 01 00 00 00 00
+ * 10: 01 d0 00 00 01 cc 00 00 81 c8 00 00 01 c8 00 00
+ * 20: 81 c4 00 00 00 90 bf fe 00 00 00 00 86 80 22 29
+ * 30: 00 00 00 00 80 00 00 00 00 00 00 00 0f 02 00 00
+ * 40: 00 80 00 80 00 00 00 00 00 00 00 00 00 00 00 00
+ * 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 70: 01 a8 03 40 08 00 00 00 00 00 00 00 00 00 00 00
+ * 80: 05 70 09 00 0c f0 e0 fe d9 41 00 00 00 00 00 00
+ * 90: 40 00 0f 82 93 01 00 00 00 00 00 00 00 00 00 00
+ * a0: ac 00 00 00 0a 00 12 00 12 b0 10 00 48 00 00 00
+ * b0: 09 00 06 20 00 00 00 00 00 00 00 00 00 00 00 00
+ * c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * f0: 00 00 00 00 00 00 00 00 86 0f 02 00 00 00 00 00
+ *
+ */
+
 #include <hw/hw.h>
 #include <hw/msi.h>
 #include <hw/pc.h>
@@ -11,7 +73,7 @@
 #include <hw/ide/pci.h>
 #include <hw/ide/ahci.h>
 
-static int pci_ich9_ahci_initfn(PCIDevice *dev)
+static int pci_ich9_ahci_init(PCIDevice *dev)
 {
     struct AHCIPCIState *d;
     d = DO_UPCAST(struct AHCIPCIState, card, dev);
@@ -44,11 +106,35 @@ static int pci_ich9_ahci_initfn(PCIDevice *dev)
     return 0;
 }
 
+static int pci_ich9_uninit(PCIDevice *dev)
+{
+    struct AHCIPCIState *d;
+    d = DO_UPCAST(struct AHCIPCIState, card, dev);
+
+    if (msi_enabled(dev)) {
+        msi_uninit(dev);
+    }
+
+    qemu_unregister_reset(ahci_reset, d);
+
+    return 0;
+}
+
+static void pci_ich9_write_config(PCIDevice *pci, uint32_t addr,
+                                  uint32_t val, int len)
+{
+    pci_default_write_config(pci, addr, val, len);
+    msi_write_config(pci, addr, val, len);
+}
+
 static PCIDeviceInfo ich_ahci_info[] = {
     {
         .qdev.name    = "ich9-ahci",
+        .qdev.alias   = "ahci",
         .qdev.size    = sizeof(AHCIPCIState),
-        .init         = pci_ich9_ahci_initfn,
+        .init         = pci_ich9_ahci_init,
+        .exit         = pci_ich9_uninit,
+        .config_write = pci_ich9_write_config,
     },{
         /* end of list */
     }
commit f83a40dcd7c38aef8cb4aa93e1f6f0e21c750992
Author: Alexander Graf <agraf at suse.de>
Date:   Tue Feb 1 15:51:27 2011 +0100

    ahci: add license header in ahci.h
    
    Due to popular request, this patch adds a license header to ahci.h
    
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index 63ef785..d65b5e3 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -1,3 +1,26 @@
+/*
+ * QEMU AHCI Emulation
+ *
+ * Copyright (c) 2010 qiaochong at loongson.cn
+ * Copyright (c) 2010 Roland Elek <elek.roland at gmail.com>
+ * Copyright (c) 2010 Sebastian Herbszt <herbszt at gmx.de>
+ * Copyright (c) 2010 Alexander Graf <agraf at suse.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
 #ifndef HW_IDE_AHCI_H
 #define HW_IDE_AHCI_H
 
commit 03c7a6a8e7122b9c12a532577046094a69593116
Author: Sebastian Herbszt <herbszt at gmx.de>
Date:   Tue Feb 1 15:51:26 2011 +0100

    ahci: split ICH9 from core
    
    There are multiple ahci devices out there. The currently implemented ich-9
    is only one of the many. So let's split that one out into a separate file
    to stress the difference.
    
    Signed-off-by: Sebastian Herbszt <herbszt at gmx.de>
    Signed-off-by: Alexander Graf <agraf at suse.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index f1c7bfe..353b1a8 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -244,6 +244,7 @@ hw-obj-$(CONFIG_IDE_CMD646) += ide/cmd646.o
 hw-obj-$(CONFIG_IDE_MACIO) += ide/macio.o
 hw-obj-$(CONFIG_IDE_VIA) += ide/via.o
 hw-obj-$(CONFIG_AHCI) += ide/ahci.o
+hw-obj-$(CONFIG_AHCI) += ide/ich.o
 
 # SCSI layer
 hw-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 671b4df..28412d0 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -72,6 +72,7 @@
 #include "cpu-common.h"
 #include "internal.h"
 #include <hw/ide/pci.h>
+#include <hw/ide/ahci.h>
 
 /* #define DEBUG_AHCI */
 
@@ -83,304 +84,6 @@ do { fprintf(stderr, "ahci: %s: [%d] ", __FUNCTION__, port); \
 #define DPRINTF(port, fmt, ...) do {} while(0)
 #endif
 
-#define AHCI_PCI_BAR              5
-#define AHCI_MAX_PORTS            32
-#define AHCI_MAX_SG               168 /* hardware max is 64K */
-#define AHCI_DMA_BOUNDARY         0xffffffff
-#define AHCI_USE_CLUSTERING       0
-#define AHCI_MAX_CMDS             32
-#define AHCI_CMD_SZ               32
-#define AHCI_CMD_SLOT_SZ          (AHCI_MAX_CMDS * AHCI_CMD_SZ)
-#define AHCI_RX_FIS_SZ            256
-#define AHCI_CMD_TBL_CDB          0x40
-#define AHCI_CMD_TBL_HDR_SZ       0x80
-#define AHCI_CMD_TBL_SZ           (AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16))
-#define AHCI_CMD_TBL_AR_SZ        (AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS)
-#define AHCI_PORT_PRIV_DMA_SZ     (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \
-                                   AHCI_RX_FIS_SZ)
-
-#define AHCI_IRQ_ON_SG            (1 << 31)
-#define AHCI_CMD_ATAPI            (1 << 5)
-#define AHCI_CMD_WRITE            (1 << 6)
-#define AHCI_CMD_PREFETCH         (1 << 7)
-#define AHCI_CMD_RESET            (1 << 8)
-#define AHCI_CMD_CLR_BUSY         (1 << 10)
-
-#define RX_FIS_D2H_REG            0x40 /* offset of D2H Register FIS data */
-#define RX_FIS_SDB                0x58 /* offset of SDB FIS data */
-#define RX_FIS_UNK                0x60 /* offset of Unknown FIS data */
-
-/* global controller registers */
-#define HOST_CAP                  0x00 /* host capabilities */
-#define HOST_CTL                  0x04 /* global host control */
-#define HOST_IRQ_STAT             0x08 /* interrupt status */
-#define HOST_PORTS_IMPL           0x0c /* bitmap of implemented ports */
-#define HOST_VERSION              0x10 /* AHCI spec. version compliancy */
-
-/* HOST_CTL bits */
-#define HOST_CTL_RESET            (1 << 0)  /* reset controller; self-clear */
-#define HOST_CTL_IRQ_EN           (1 << 1)  /* global IRQ enable */
-#define HOST_CTL_AHCI_EN          (1 << 31) /* AHCI enabled */
-
-/* HOST_CAP bits */
-#define HOST_CAP_SSC              (1 << 14) /* Slumber capable */
-#define HOST_CAP_AHCI             (1 << 18) /* AHCI only */
-#define HOST_CAP_CLO              (1 << 24) /* Command List Override support */
-#define HOST_CAP_SSS              (1 << 27) /* Staggered Spin-up */
-#define HOST_CAP_NCQ              (1 << 30) /* Native Command Queueing */
-#define HOST_CAP_64               (1 << 31) /* PCI DAC (64-bit DMA) support */
-
-/* registers for each SATA port */
-#define PORT_LST_ADDR             0x00 /* command list DMA addr */
-#define PORT_LST_ADDR_HI          0x04 /* command list DMA addr hi */
-#define PORT_FIS_ADDR             0x08 /* FIS rx buf addr */
-#define PORT_FIS_ADDR_HI          0x0c /* FIS rx buf addr hi */
-#define PORT_IRQ_STAT             0x10 /* interrupt status */
-#define PORT_IRQ_MASK             0x14 /* interrupt enable/disable mask */
-#define PORT_CMD                  0x18 /* port command */
-#define PORT_TFDATA               0x20 /* taskfile data */
-#define PORT_SIG                  0x24 /* device TF signature */
-#define PORT_SCR_STAT             0x28 /* SATA phy register: SStatus */
-#define PORT_SCR_CTL              0x2c /* SATA phy register: SControl */
-#define PORT_SCR_ERR              0x30 /* SATA phy register: SError */
-#define PORT_SCR_ACT              0x34 /* SATA phy register: SActive */
-#define PORT_CMD_ISSUE            0x38 /* command issue */
-#define PORT_RESERVED             0x3c /* reserved */
-
-/* PORT_IRQ_{STAT,MASK} bits */
-#define PORT_IRQ_COLD_PRES        (1 << 31) /* cold presence detect */
-#define PORT_IRQ_TF_ERR           (1 << 30) /* task file error */
-#define PORT_IRQ_HBUS_ERR         (1 << 29) /* host bus fatal error */
-#define PORT_IRQ_HBUS_DATA_ERR    (1 << 28) /* host bus data error */
-#define PORT_IRQ_IF_ERR           (1 << 27) /* interface fatal error */
-#define PORT_IRQ_IF_NONFATAL      (1 << 26) /* interface non-fatal error */
-#define PORT_IRQ_OVERFLOW         (1 << 24) /* xfer exhausted available S/G */
-#define PORT_IRQ_BAD_PMP          (1 << 23) /* incorrect port multiplier */
-
-#define PORT_IRQ_PHYRDY           (1 << 22) /* PhyRdy changed */
-#define PORT_IRQ_DEV_ILCK         (1 << 7) /* device interlock */
-#define PORT_IRQ_CONNECT          (1 << 6) /* port connect change status */
-#define PORT_IRQ_SG_DONE          (1 << 5) /* descriptor processed */
-#define PORT_IRQ_UNK_FIS          (1 << 4) /* unknown FIS rx'd */
-#define PORT_IRQ_SDB_FIS          (1 << 3) /* Set Device Bits FIS rx'd */
-#define PORT_IRQ_DMAS_FIS         (1 << 2) /* DMA Setup FIS rx'd */
-#define PORT_IRQ_PIOS_FIS         (1 << 1) /* PIO Setup FIS rx'd */
-#define PORT_IRQ_D2H_REG_FIS      (1 << 0) /* D2H Register FIS rx'd */
-
-#define PORT_IRQ_FREEZE           (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR |   \
-                                   PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY |    \
-                                   PORT_IRQ_UNK_FIS)
-#define PORT_IRQ_ERROR            (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR |     \
-                                   PORT_IRQ_HBUS_DATA_ERR)
-#define DEF_PORT_IRQ              (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |     \
-                                   PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |  \
-                                   PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS)
-
-/* PORT_CMD bits */
-#define PORT_CMD_ATAPI            (1 << 24) /* Device is ATAPI */
-#define PORT_CMD_LIST_ON          (1 << 15) /* cmd list DMA engine running */
-#define PORT_CMD_FIS_ON           (1 << 14) /* FIS DMA engine running */
-#define PORT_CMD_FIS_RX           (1 << 4) /* Enable FIS receive DMA engine */
-#define PORT_CMD_CLO              (1 << 3) /* Command list override */
-#define PORT_CMD_POWER_ON         (1 << 2) /* Power up device */
-#define PORT_CMD_SPIN_UP          (1 << 1) /* Spin up device */
-#define PORT_CMD_START            (1 << 0) /* Enable port DMA engine */
-
-#define PORT_CMD_ICC_MASK         (0xf << 28) /* i/f ICC state mask */
-#define PORT_CMD_ICC_ACTIVE       (0x1 << 28) /* Put i/f in active state */
-#define PORT_CMD_ICC_PARTIAL      (0x2 << 28) /* Put i/f in partial state */
-#define PORT_CMD_ICC_SLUMBER      (0x6 << 28) /* Put i/f in slumber state */
-
-#define PORT_IRQ_STAT_DHRS        (1 << 0) /* Device to Host Register FIS */
-#define PORT_IRQ_STAT_PSS         (1 << 1) /* PIO Setup FIS */
-#define PORT_IRQ_STAT_DSS         (1 << 2) /* DMA Setup FIS */
-#define PORT_IRQ_STAT_SDBS        (1 << 3) /* Set Device Bits */
-#define PORT_IRQ_STAT_UFS         (1 << 4) /* Unknown FIS */
-#define PORT_IRQ_STAT_DPS         (1 << 5) /* Descriptor Processed */
-#define PORT_IRQ_STAT_PCS         (1 << 6) /* Port Connect Change Status */
-#define PORT_IRQ_STAT_DMPS        (1 << 7) /* Device Mechanical Presence
-                                              Status */
-#define PORT_IRQ_STAT_PRCS        (1 << 22) /* File Ready Status */
-#define PORT_IRQ_STAT_IPMS        (1 << 23) /* Incorrect Port Multiplier
-                                               Status */
-#define PORT_IRQ_STAT_OFS         (1 << 24) /* Overflow Status */
-#define PORT_IRQ_STAT_INFS        (1 << 26) /* Interface Non-Fatal Error
-                                               Status */
-#define PORT_IRQ_STAT_IFS         (1 << 27) /* Interface Fatal Error */
-#define PORT_IRQ_STAT_HBDS        (1 << 28) /* Host Bus Data Error Status */
-#define PORT_IRQ_STAT_HBFS        (1 << 29) /* Host Bus Fatal Error Status */
-#define PORT_IRQ_STAT_TFES        (1 << 30) /* Task File Error Status */
-#define PORT_IRQ_STAT_CPDS        (1 << 31) /* Code Port Detect Status */
-
-/* ap->flags bits */
-#define AHCI_FLAG_NO_NCQ                  (1 << 24)
-#define AHCI_FLAG_IGN_IRQ_IF_ERR          (1 << 25) /* ignore IRQ_IF_ERR */
-#define AHCI_FLAG_HONOR_PI                (1 << 26) /* honor PORTS_IMPL */
-#define AHCI_FLAG_IGN_SERR_INTERNAL       (1 << 27) /* ignore SERR_INTERNAL */
-#define AHCI_FLAG_32BIT_ONLY              (1 << 28) /* force 32bit */
-
-#define ATA_SRST                          (1 << 2)  /* software reset */
-
-#define STATE_RUN                         0
-#define STATE_RESET                       1
-
-#define SATA_SCR_SSTATUS_DET_NODEV        0x0
-#define SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP 0x3
-
-#define SATA_SCR_SSTATUS_SPD_NODEV        0x00
-#define SATA_SCR_SSTATUS_SPD_GEN1         0x10
-
-#define SATA_SCR_SSTATUS_IPM_NODEV        0x000
-#define SATA_SCR_SSTATUS_IPM_ACTIVE       0X100
-
-#define AHCI_SCR_SCTL_DET                 0xf
-
-#define SATA_FIS_TYPE_REGISTER_H2D        0x27
-#define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80
-
-#define AHCI_CMD_HDR_CMD_FIS_LEN           0x1f
-#define AHCI_CMD_HDR_PRDT_LEN              16
-
-#define SATA_SIGNATURE_CDROM               0xeb140000
-#define SATA_SIGNATURE_DISK                0x00000101
-
-#define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20
-                                            /* Shouldn't this be 0x2c? */
-
-#define SATA_PORTS                         4
-
-#define AHCI_PORT_REGS_START_ADDR          0x100
-#define AHCI_PORT_REGS_END_ADDR (AHCI_PORT_REGS_START_ADDR + SATA_PORTS * 0x80)
-#define AHCI_PORT_ADDR_OFFSET_MASK         0x7f
-
-#define AHCI_NUM_COMMAND_SLOTS             31
-#define AHCI_SUPPORTED_SPEED               20
-#define AHCI_SUPPORTED_SPEED_GEN1          1
-#define AHCI_VERSION_1_0                   0x10000
-
-#define AHCI_PROGMODE_MAJOR_REV_1          1
-
-#define AHCI_COMMAND_TABLE_ACMD            0x40
-
-#define IDE_FEATURE_DMA                    1
-
-#define READ_FPDMA_QUEUED                  0x60
-#define WRITE_FPDMA_QUEUED                 0x61
-
-#define RES_FIS_DSFIS                      0x00
-#define RES_FIS_PSFIS                      0x20
-#define RES_FIS_RFIS                       0x40
-#define RES_FIS_SDBFIS                     0x58
-#define RES_FIS_UFIS                       0x60
-
-typedef struct AHCIControlRegs {
-    uint32_t    cap;
-    uint32_t    ghc;
-    uint32_t    irqstatus;
-    uint32_t    impl;
-    uint32_t    version;
-} AHCIControlRegs;
-
-typedef struct AHCIPortRegs {
-    uint32_t    lst_addr;
-    uint32_t    lst_addr_hi;
-    uint32_t    fis_addr;
-    uint32_t    fis_addr_hi;
-    uint32_t    irq_stat;
-    uint32_t    irq_mask;
-    uint32_t    cmd;
-    uint32_t    unused0;
-    uint32_t    tfdata;
-    uint32_t    sig;
-    uint32_t    scr_stat;
-    uint32_t    scr_ctl;
-    uint32_t    scr_err;
-    uint32_t    scr_act;
-    uint32_t    cmd_issue;
-    uint32_t    reserved;
-} AHCIPortRegs;
-
-typedef struct AHCICmdHdr {
-    uint32_t    opts;
-    uint32_t    status;
-    uint64_t    tbl_addr;
-    uint32_t    reserved[4];
-} __attribute__ ((packed)) AHCICmdHdr;
-
-typedef struct AHCI_SG {
-    uint64_t    addr;
-    uint32_t    reserved;
-    uint32_t    flags_size;
-} __attribute__ ((packed)) AHCI_SG;
-
-typedef struct AHCIDevice AHCIDevice;
-
-typedef struct NCQTransferState {
-    AHCIDevice *drive;
-    BlockDriverAIOCB *aiocb;
-    QEMUSGList sglist;
-    int is_read;
-    uint16_t sector_count;
-    uint64_t lba;
-    uint8_t tag;
-    int slot;
-    int used;
-} NCQTransferState;
-
-struct AHCIDevice {
-    IDEDMA dma;
-    IDEBus port;
-    int port_no;
-    uint32_t port_state;
-    uint32_t finished;
-    AHCIPortRegs port_regs;
-    struct AHCIState *hba;
-    QEMUBH *check_bh;
-    uint8_t *lst;
-    uint8_t *res_fis;
-    int dma_status;
-    int done_atapi_packet;
-    int busy_slot;
-    BlockDriverCompletionFunc *dma_cb;
-    AHCICmdHdr *cur_cmd;
-    NCQTransferState ncq_tfs[AHCI_MAX_CMDS];
-};
-
-typedef struct AHCIState {
-    AHCIDevice dev[SATA_PORTS];
-    AHCIControlRegs control_regs;
-    int mem;
-    qemu_irq irq;
-} AHCIState;
-
-typedef struct AHCIPCIState {
-    PCIDevice card;
-    AHCIState ahci;
-} AHCIPCIState;
-
-typedef struct NCQFrame {
-    uint8_t fis_type;
-    uint8_t c;
-    uint8_t command;
-    uint8_t sector_count_low;
-    uint8_t lba0;
-    uint8_t lba1;
-    uint8_t lba2;
-    uint8_t fua;
-    uint8_t lba3;
-    uint8_t lba4;
-    uint8_t lba5;
-    uint8_t sector_count_high;
-    uint8_t tag;
-    uint8_t reserved5;
-    uint8_t reserved6;
-    uint8_t control;
-    uint8_t reserved7;
-    uint8_t reserved8;
-    uint8_t reserved9;
-    uint8_t reserved10;
-} __attribute__ ((packed)) NCQFrame;
-
 static void check_cmd(AHCIState *s, int port);
 static int handle_cmd(AHCIState *s,int port,int slot);
 static void ahci_reset_port(AHCIState *s, int port);
@@ -1410,7 +1113,7 @@ static const IDEDMAOps ahci_dma_ops = {
     .reset = ahci_dma_reset,
 };
 
-static void ahci_init(AHCIState *s, DeviceState *qdev)
+void ahci_init(AHCIState *s, DeviceState *qdev)
 {
     qemu_irq *irqs;
     int i;
@@ -1434,7 +1137,7 @@ static void ahci_init(AHCIState *s, DeviceState *qdev)
     }
 }
 
-static void ahci_pci_map(PCIDevice *pci_dev, int region_num,
+void ahci_pci_map(PCIDevice *pci_dev, int region_num,
         pcibus_t addr, pcibus_t size, int type)
 {
     struct AHCIPCIState *d = (struct AHCIPCIState *)pci_dev;
@@ -1443,7 +1146,7 @@ static void ahci_pci_map(PCIDevice *pci_dev, int region_num,
     cpu_register_physical_memory(addr, size, s->mem);
 }
 
-static void ahci_reset(void *opaque)
+void ahci_reset(void *opaque)
 {
     struct AHCIPCIState *d = opaque;
     int i;
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
new file mode 100644
index 0000000..63ef785
--- /dev/null
+++ b/hw/ide/ahci.h
@@ -0,0 +1,309 @@
+#ifndef HW_IDE_AHCI_H
+#define HW_IDE_AHCI_H
+
+#define AHCI_PCI_BAR              5
+#define AHCI_MAX_PORTS            32
+#define AHCI_MAX_SG               168 /* hardware max is 64K */
+#define AHCI_DMA_BOUNDARY         0xffffffff
+#define AHCI_USE_CLUSTERING       0
+#define AHCI_MAX_CMDS             32
+#define AHCI_CMD_SZ               32
+#define AHCI_CMD_SLOT_SZ          (AHCI_MAX_CMDS * AHCI_CMD_SZ)
+#define AHCI_RX_FIS_SZ            256
+#define AHCI_CMD_TBL_CDB          0x40
+#define AHCI_CMD_TBL_HDR_SZ       0x80
+#define AHCI_CMD_TBL_SZ           (AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16))
+#define AHCI_CMD_TBL_AR_SZ        (AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS)
+#define AHCI_PORT_PRIV_DMA_SZ     (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \
+                                   AHCI_RX_FIS_SZ)
+
+#define AHCI_IRQ_ON_SG            (1 << 31)
+#define AHCI_CMD_ATAPI            (1 << 5)
+#define AHCI_CMD_WRITE            (1 << 6)
+#define AHCI_CMD_PREFETCH         (1 << 7)
+#define AHCI_CMD_RESET            (1 << 8)
+#define AHCI_CMD_CLR_BUSY         (1 << 10)
+
+#define RX_FIS_D2H_REG            0x40 /* offset of D2H Register FIS data */
+#define RX_FIS_SDB                0x58 /* offset of SDB FIS data */
+#define RX_FIS_UNK                0x60 /* offset of Unknown FIS data */
+
+/* global controller registers */
+#define HOST_CAP                  0x00 /* host capabilities */
+#define HOST_CTL                  0x04 /* global host control */
+#define HOST_IRQ_STAT             0x08 /* interrupt status */
+#define HOST_PORTS_IMPL           0x0c /* bitmap of implemented ports */
+#define HOST_VERSION              0x10 /* AHCI spec. version compliancy */
+
+/* HOST_CTL bits */
+#define HOST_CTL_RESET            (1 << 0)  /* reset controller; self-clear */
+#define HOST_CTL_IRQ_EN           (1 << 1)  /* global IRQ enable */
+#define HOST_CTL_AHCI_EN          (1 << 31) /* AHCI enabled */
+
+/* HOST_CAP bits */
+#define HOST_CAP_SSC              (1 << 14) /* Slumber capable */
+#define HOST_CAP_AHCI             (1 << 18) /* AHCI only */
+#define HOST_CAP_CLO              (1 << 24) /* Command List Override support */
+#define HOST_CAP_SSS              (1 << 27) /* Staggered Spin-up */
+#define HOST_CAP_NCQ              (1 << 30) /* Native Command Queueing */
+#define HOST_CAP_64               (1 << 31) /* PCI DAC (64-bit DMA) support */
+
+/* registers for each SATA port */
+#define PORT_LST_ADDR             0x00 /* command list DMA addr */
+#define PORT_LST_ADDR_HI          0x04 /* command list DMA addr hi */
+#define PORT_FIS_ADDR             0x08 /* FIS rx buf addr */
+#define PORT_FIS_ADDR_HI          0x0c /* FIS rx buf addr hi */
+#define PORT_IRQ_STAT             0x10 /* interrupt status */
+#define PORT_IRQ_MASK             0x14 /* interrupt enable/disable mask */
+#define PORT_CMD                  0x18 /* port command */
+#define PORT_TFDATA               0x20 /* taskfile data */
+#define PORT_SIG                  0x24 /* device TF signature */
+#define PORT_SCR_STAT             0x28 /* SATA phy register: SStatus */
+#define PORT_SCR_CTL              0x2c /* SATA phy register: SControl */
+#define PORT_SCR_ERR              0x30 /* SATA phy register: SError */
+#define PORT_SCR_ACT              0x34 /* SATA phy register: SActive */
+#define PORT_CMD_ISSUE            0x38 /* command issue */
+#define PORT_RESERVED             0x3c /* reserved */
+
+/* PORT_IRQ_{STAT,MASK} bits */
+#define PORT_IRQ_COLD_PRES        (1 << 31) /* cold presence detect */
+#define PORT_IRQ_TF_ERR           (1 << 30) /* task file error */
+#define PORT_IRQ_HBUS_ERR         (1 << 29) /* host bus fatal error */
+#define PORT_IRQ_HBUS_DATA_ERR    (1 << 28) /* host bus data error */
+#define PORT_IRQ_IF_ERR           (1 << 27) /* interface fatal error */
+#define PORT_IRQ_IF_NONFATAL      (1 << 26) /* interface non-fatal error */
+#define PORT_IRQ_OVERFLOW         (1 << 24) /* xfer exhausted available S/G */
+#define PORT_IRQ_BAD_PMP          (1 << 23) /* incorrect port multiplier */
+
+#define PORT_IRQ_PHYRDY           (1 << 22) /* PhyRdy changed */
+#define PORT_IRQ_DEV_ILCK         (1 << 7) /* device interlock */
+#define PORT_IRQ_CONNECT          (1 << 6) /* port connect change status */
+#define PORT_IRQ_SG_DONE          (1 << 5) /* descriptor processed */
+#define PORT_IRQ_UNK_FIS          (1 << 4) /* unknown FIS rx'd */
+#define PORT_IRQ_SDB_FIS          (1 << 3) /* Set Device Bits FIS rx'd */
+#define PORT_IRQ_DMAS_FIS         (1 << 2) /* DMA Setup FIS rx'd */
+#define PORT_IRQ_PIOS_FIS         (1 << 1) /* PIO Setup FIS rx'd */
+#define PORT_IRQ_D2H_REG_FIS      (1 << 0) /* D2H Register FIS rx'd */
+
+#define PORT_IRQ_FREEZE           (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR |   \
+                                   PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY |    \
+                                   PORT_IRQ_UNK_FIS)
+#define PORT_IRQ_ERROR            (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR |     \
+                                   PORT_IRQ_HBUS_DATA_ERR)
+#define DEF_PORT_IRQ              (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |     \
+                                   PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |  \
+                                   PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS)
+
+/* PORT_CMD bits */
+#define PORT_CMD_ATAPI            (1 << 24) /* Device is ATAPI */
+#define PORT_CMD_LIST_ON          (1 << 15) /* cmd list DMA engine running */
+#define PORT_CMD_FIS_ON           (1 << 14) /* FIS DMA engine running */
+#define PORT_CMD_FIS_RX           (1 << 4) /* Enable FIS receive DMA engine */
+#define PORT_CMD_CLO              (1 << 3) /* Command list override */
+#define PORT_CMD_POWER_ON         (1 << 2) /* Power up device */
+#define PORT_CMD_SPIN_UP          (1 << 1) /* Spin up device */
+#define PORT_CMD_START            (1 << 0) /* Enable port DMA engine */
+
+#define PORT_CMD_ICC_MASK         (0xf << 28) /* i/f ICC state mask */
+#define PORT_CMD_ICC_ACTIVE       (0x1 << 28) /* Put i/f in active state */
+#define PORT_CMD_ICC_PARTIAL      (0x2 << 28) /* Put i/f in partial state */
+#define PORT_CMD_ICC_SLUMBER      (0x6 << 28) /* Put i/f in slumber state */
+
+#define PORT_IRQ_STAT_DHRS        (1 << 0) /* Device to Host Register FIS */
+#define PORT_IRQ_STAT_PSS         (1 << 1) /* PIO Setup FIS */
+#define PORT_IRQ_STAT_DSS         (1 << 2) /* DMA Setup FIS */
+#define PORT_IRQ_STAT_SDBS        (1 << 3) /* Set Device Bits */
+#define PORT_IRQ_STAT_UFS         (1 << 4) /* Unknown FIS */
+#define PORT_IRQ_STAT_DPS         (1 << 5) /* Descriptor Processed */
+#define PORT_IRQ_STAT_PCS         (1 << 6) /* Port Connect Change Status */
+#define PORT_IRQ_STAT_DMPS        (1 << 7) /* Device Mechanical Presence
+                                              Status */
+#define PORT_IRQ_STAT_PRCS        (1 << 22) /* File Ready Status */
+#define PORT_IRQ_STAT_IPMS        (1 << 23) /* Incorrect Port Multiplier
+                                               Status */
+#define PORT_IRQ_STAT_OFS         (1 << 24) /* Overflow Status */
+#define PORT_IRQ_STAT_INFS        (1 << 26) /* Interface Non-Fatal Error
+                                               Status */
+#define PORT_IRQ_STAT_IFS         (1 << 27) /* Interface Fatal Error */
+#define PORT_IRQ_STAT_HBDS        (1 << 28) /* Host Bus Data Error Status */
+#define PORT_IRQ_STAT_HBFS        (1 << 29) /* Host Bus Fatal Error Status */
+#define PORT_IRQ_STAT_TFES        (1 << 30) /* Task File Error Status */
+#define PORT_IRQ_STAT_CPDS        (1 << 31) /* Code Port Detect Status */
+
+/* ap->flags bits */
+#define AHCI_FLAG_NO_NCQ                  (1 << 24)
+#define AHCI_FLAG_IGN_IRQ_IF_ERR          (1 << 25) /* ignore IRQ_IF_ERR */
+#define AHCI_FLAG_HONOR_PI                (1 << 26) /* honor PORTS_IMPL */
+#define AHCI_FLAG_IGN_SERR_INTERNAL       (1 << 27) /* ignore SERR_INTERNAL */
+#define AHCI_FLAG_32BIT_ONLY              (1 << 28) /* force 32bit */
+
+#define ATA_SRST                          (1 << 2)  /* software reset */
+
+#define STATE_RUN                         0
+#define STATE_RESET                       1
+
+#define SATA_SCR_SSTATUS_DET_NODEV        0x0
+#define SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP 0x3
+
+#define SATA_SCR_SSTATUS_SPD_NODEV        0x00
+#define SATA_SCR_SSTATUS_SPD_GEN1         0x10
+
+#define SATA_SCR_SSTATUS_IPM_NODEV        0x000
+#define SATA_SCR_SSTATUS_IPM_ACTIVE       0X100
+
+#define AHCI_SCR_SCTL_DET                 0xf
+
+#define SATA_FIS_TYPE_REGISTER_H2D        0x27
+#define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80
+
+#define AHCI_CMD_HDR_CMD_FIS_LEN           0x1f
+#define AHCI_CMD_HDR_PRDT_LEN              16
+
+#define SATA_SIGNATURE_CDROM               0xeb140000
+#define SATA_SIGNATURE_DISK                0x00000101
+
+#define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20
+                                            /* Shouldn't this be 0x2c? */
+
+#define SATA_PORTS                         4
+
+#define AHCI_PORT_REGS_START_ADDR          0x100
+#define AHCI_PORT_REGS_END_ADDR (AHCI_PORT_REGS_START_ADDR + SATA_PORTS * 0x80)
+#define AHCI_PORT_ADDR_OFFSET_MASK         0x7f
+
+#define AHCI_NUM_COMMAND_SLOTS             31
+#define AHCI_SUPPORTED_SPEED               20
+#define AHCI_SUPPORTED_SPEED_GEN1          1
+#define AHCI_VERSION_1_0                   0x10000
+
+#define AHCI_PROGMODE_MAJOR_REV_1          1
+
+#define AHCI_COMMAND_TABLE_ACMD            0x40
+
+#define IDE_FEATURE_DMA                    1
+
+#define READ_FPDMA_QUEUED                  0x60
+#define WRITE_FPDMA_QUEUED                 0x61
+
+#define RES_FIS_DSFIS                      0x00
+#define RES_FIS_PSFIS                      0x20
+#define RES_FIS_RFIS                       0x40
+#define RES_FIS_SDBFIS                     0x58
+#define RES_FIS_UFIS                       0x60
+
+typedef struct AHCIControlRegs {
+    uint32_t    cap;
+    uint32_t    ghc;
+    uint32_t    irqstatus;
+    uint32_t    impl;
+    uint32_t    version;
+} AHCIControlRegs;
+
+typedef struct AHCIPortRegs {
+    uint32_t    lst_addr;
+    uint32_t    lst_addr_hi;
+    uint32_t    fis_addr;
+    uint32_t    fis_addr_hi;
+    uint32_t    irq_stat;
+    uint32_t    irq_mask;
+    uint32_t    cmd;
+    uint32_t    unused0;
+    uint32_t    tfdata;
+    uint32_t    sig;
+    uint32_t    scr_stat;
+    uint32_t    scr_ctl;
+    uint32_t    scr_err;
+    uint32_t    scr_act;
+    uint32_t    cmd_issue;
+    uint32_t    reserved;
+} AHCIPortRegs;
+
+typedef struct AHCICmdHdr {
+    uint32_t    opts;
+    uint32_t    status;
+    uint64_t    tbl_addr;
+    uint32_t    reserved[4];
+} __attribute__ ((packed)) AHCICmdHdr;
+
+typedef struct AHCI_SG {
+    uint64_t    addr;
+    uint32_t    reserved;
+    uint32_t    flags_size;
+} __attribute__ ((packed)) AHCI_SG;
+
+typedef struct AHCIDevice AHCIDevice;
+
+typedef struct NCQTransferState {
+    AHCIDevice *drive;
+    BlockDriverAIOCB *aiocb;
+    QEMUSGList sglist;
+    int is_read;
+    uint16_t sector_count;
+    uint64_t lba;
+    uint8_t tag;
+    int slot;
+    int used;
+} NCQTransferState;
+
+struct AHCIDevice {
+    IDEDMA dma;
+    IDEBus port;
+    int port_no;
+    uint32_t port_state;
+    uint32_t finished;
+    AHCIPortRegs port_regs;
+    struct AHCIState *hba;
+    QEMUBH *check_bh;
+    uint8_t *lst;
+    uint8_t *res_fis;
+    int dma_status;
+    int done_atapi_packet;
+    int busy_slot;
+    BlockDriverCompletionFunc *dma_cb;
+    AHCICmdHdr *cur_cmd;
+    NCQTransferState ncq_tfs[AHCI_MAX_CMDS];
+};
+
+typedef struct AHCIState {
+    AHCIDevice dev[SATA_PORTS];
+    AHCIControlRegs control_regs;
+    int mem;
+    qemu_irq irq;
+} AHCIState;
+
+typedef struct AHCIPCIState {
+    PCIDevice card;
+    AHCIState ahci;
+} AHCIPCIState;
+
+typedef struct NCQFrame {
+    uint8_t fis_type;
+    uint8_t c;
+    uint8_t command;
+    uint8_t sector_count_low;
+    uint8_t lba0;
+    uint8_t lba1;
+    uint8_t lba2;
+    uint8_t fua;
+    uint8_t lba3;
+    uint8_t lba4;
+    uint8_t lba5;
+    uint8_t sector_count_high;
+    uint8_t tag;
+    uint8_t reserved5;
+    uint8_t reserved6;
+    uint8_t control;
+    uint8_t reserved7;
+    uint8_t reserved8;
+    uint8_t reserved9;
+    uint8_t reserved10;
+} __attribute__ ((packed)) NCQFrame;
+
+void ahci_init(AHCIState *s, DeviceState *qdev);
+
+void ahci_pci_map(PCIDevice *pci_dev, int region_num,
+        pcibus_t addr, pcibus_t size, int type);
+
+void ahci_reset(void *opaque);
+
+#endif /* HW_IDE_AHCI_H */
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
new file mode 100644
index 0000000..9868b73
--- /dev/null
+++ b/hw/ide/ich.c
@@ -0,0 +1,61 @@
+#include <hw/hw.h>
+#include <hw/msi.h>
+#include <hw/pc.h>
+#include <hw/pci.h>
+#include <hw/isa.h>
+#include "block.h"
+#include "block_int.h"
+#include "sysemu.h"
+#include "dma.h"
+
+#include <hw/ide/pci.h>
+#include <hw/ide/ahci.h>
+
+static int pci_ich9_ahci_initfn(PCIDevice *dev)
+{
+    struct AHCIPCIState *d;
+    d = DO_UPCAST(struct AHCIPCIState, card, dev);
+
+    pci_config_set_vendor_id(d->card.config, PCI_VENDOR_ID_INTEL);
+    pci_config_set_device_id(d->card.config, PCI_DEVICE_ID_INTEL_82801IR);
+
+    pci_config_set_class(d->card.config, PCI_CLASS_STORAGE_SATA);
+    pci_config_set_revision(d->card.config, 0x02);
+    pci_config_set_prog_interface(d->card.config, AHCI_PROGMODE_MAJOR_REV_1);
+
+    d->card.config[PCI_CACHE_LINE_SIZE] = 0x08;  /* Cache line size */
+    d->card.config[PCI_LATENCY_TIMER]   = 0x00;  /* Latency timer */
+    pci_config_set_interrupt_pin(d->card.config, 1);
+
+    /* XXX Software should program this register */
+    d->card.config[0x90]   = 1 << 6; /* Address Map Register - AHCI mode */
+
+    qemu_register_reset(ahci_reset, d);
+
+    /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
+    pci_register_bar(&d->card, 5, 0x1000, PCI_BASE_ADDRESS_SPACE_MEMORY,
+                     ahci_pci_map);
+
+    msi_init(dev, 0x50, 1, true, false);
+
+    ahci_init(&d->ahci, &dev->qdev);
+    d->ahci.irq = d->card.irq[0];
+
+    return 0;
+}
+
+static PCIDeviceInfo ich_ahci_info[] = {
+    {
+        .qdev.name    = "ich9-ahci",
+        .qdev.size    = sizeof(AHCIPCIState),
+        .init         = pci_ich9_ahci_initfn,
+    },{
+        /* end of list */
+    }
+};
+
+static void ich_ahci_register(void)
+{
+    pci_qdev_register_many(ich_ahci_info);
+}
+device_init(ich_ahci_register);
commit 4f3669ea5bd73ade0dce5f1155cb9ad9788fd54c
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Fri Feb 4 21:01:16 2011 +0100

    block/vdi: Fix wrong size in conditionally used memset, memcmp
    
    Error report from cppcheck:
    block/vdi.c:122: error: Using sizeof for array given as function argument returns the size of pointer.
    block/vdi.c:128: error: Using sizeof for array given as function argument returns the size of pointer.
    
    Fix both by setting the correct size.
    
    The buggy code is only used when QEMU is build without uuid support.
    The bug is not critical, so there is no urgent need to apply it to
    old versions of QEMU.
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/vdi.c b/block/vdi.c
index ab8f70f..116b25b 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -119,13 +119,13 @@ void uuid_unparse(const uuid_t uu, char *out);
 #if !defined(CONFIG_UUID)
 void uuid_generate(uuid_t out)
 {
-    memset(out, 0, sizeof(out));
+    memset(out, 0, sizeof(uuid_t));
 }
 
 int uuid_is_null(const uuid_t uu)
 {
     uuid_t null_uuid = { 0 };
-    return memcmp(uu, null_uuid, sizeof(uu)) == 0;
+    return memcmp(uu, null_uuid, sizeof(uuid_t)) == 0;
 }
 
 void uuid_unparse(const uuid_t uu, char *out)
commit 42af9c30ea9a963ce604ac96230fde2f987634db
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Mon Feb 7 16:04:04 2011 +0900

    Documentation: add Sheepdog disk images
    
    Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-doc.texi b/qemu-doc.texi
index 22a8663..86e017c 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -407,6 +407,7 @@ snapshots.
 * host_drives::               Using host drives
 * disk_images_fat_images::    Virtual FAT disk images
 * disk_images_nbd::           NBD access
+* disk_images_sheepdog::      Sheepdog disk images
 @end menu
 
 @node disk_images_quickstart
@@ -630,6 +631,57 @@ qemu -cdrom nbd:localhost:exportname=debian-500-ppc-netinst
 qemu -cdrom nbd:localhost:exportname=openSUSE-11.1-ppc-netinst
 @end example
 
+ at node disk_images_sheepdog
+ at subsection Sheepdog disk images
+
+Sheepdog is a distributed storage system for QEMU.  It provides highly
+available block level storage volumes that can be attached to
+QEMU-based virtual machines.
+
+You can create a Sheepdog disk image with the command:
+ at example
+qemu-img create sheepdog:@var{image} @var{size}
+ at end example
+where @var{image} is the Sheepdog image name and @var{size} is its
+size.
+
+To import the existing @var{filename} to Sheepdog, you can use a
+convert command.
+ at example
+qemu-img convert @var{filename} sheepdog:@var{image}
+ at end example
+
+You can boot from the Sheepdog disk image with the command:
+ at example
+qemu sheepdog:@var{image}
+ at end example
+
+You can also create a snapshot of the Sheepdog image like qcow2.
+ at example
+qemu-img snapshot -c @var{tag} sheepdog:@var{image}
+ at end example
+where @var{tag} is a tag name of the newly created snapshot.
+
+To boot from the Sheepdog snapshot, specify the tag name of the
+snapshot.
+ at example
+qemu sheepdog:@var{image}:@var{tag}
+ at end example
+
+You can create a cloned image from the existing snapshot.
+ at example
+qemu-img create -b sheepdog:@var{base}:@var{tag} sheepdog:@var{image}
+ at end example
+where @var{base} is a image name of the source snapshot and @var{tag}
+is its tag name.
+
+If the Sheepdog daemon doesn't run on the local host, you need to
+specify one of the Sheepdog servers to connect to.
+ at example
+qemu-img create sheepdog:@var{hostname}:@var{port}:@var{image} @var{size}
+qemu sheepdog:@var{hostname}:@var{port}:@var{image}
+ at end example
+
 @node pcsys_network
 @section Network emulation
 
commit e1a7107f2d92af646ec37b74d074dc150e688559
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Thu Jan 27 16:46:01 2011 +0100

    qcow2: Really use cache=unsafe for image creation
    
    For cache=unsafe we also need to set BDRV_O_CACHE_WB, otherwise we have some
    strange unsafe writethrough mode.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2.c b/block/qcow2.c
index dbe4fdd..a1773e4 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -975,7 +975,8 @@ static int qcow2_create2(const char *filename, int64_t total_size,
      */
     BlockDriver* drv = bdrv_find_format("qcow2");
     assert(drv != NULL);
-    ret = bdrv_open(bs, filename, BDRV_O_RDWR | BDRV_O_NO_FLUSH, drv);
+    ret = bdrv_open(bs, filename,
+        BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv);
     if (ret < 0) {
         goto out;
     }
commit ad36ce8ba95a756ef558579c6e9ecedfae4dfd0b
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Feb 5 13:18:20 2011 +0000

    checkpatch.pl: don't complain about old lines with tabs
    
    Don't complain when the patch includes lines with tabs
    only in the hunk's untouched context.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 4fa06c0..075b614 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1495,7 +1495,7 @@ sub process {
 		next if ($realfile !~ /\.(h|c|pl)$/);
 
 # in QEMU, no tabs are allowed
-		if ($rawline =~ /\t/) {
+		if ($rawline =~ /^\+.*\t/) {
 			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
 			ERROR("code indent should never use tabs\n" . $herevet);
 			$rpt_cleaners = 1;
commit a2fdc8907bee6eb572fea992be7126e1b616d5bf
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Feb 3 19:43:25 2011 +0000

    target-arm: Fix decoding of Thumb preload and hint space
    
    Refine the decoding of the Thumb preload and hint space, so we
    UNDEF on the patterns that are supposed to UNDEF rather than NOP.
    We also move the tests for this space earlier, so we don't emit
    harmless but unnecessary address generation code for preload
    hints (which by their nature are likely to be in hot code paths).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index a8f1ffe..e4649e6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -8306,6 +8306,42 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                 goto illegal_op;
             break;
         }
+        op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
+        if (rs == 15) {
+            if (!(insn & (1 << 20))) {
+                goto illegal_op;
+            }
+            if (op != 2) {
+                /* Byte or halfword load space with dest == r15 : memory hints.
+                 * Catch them early so we don't emit pointless addressing code.
+                 * This space is a mix of:
+                 *  PLD/PLDW/PLI,  which we implement as NOPs (note that unlike
+                 *     the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
+                 *     cores)
+                 *  unallocated hints, which must be treated as NOPs
+                 *  UNPREDICTABLE space, which we NOP or UNDEF depending on
+                 *     which is easiest for the decoding logic
+                 *  Some space which must UNDEF
+                 */
+                int op1 = (insn >> 23) & 3;
+                int op2 = (insn >> 6) & 0x3f;
+                if (op & 2) {
+                    goto illegal_op;
+                }
+                if (rn == 15) {
+                    /* UNPREDICTABLE or unallocated hint */
+                    return 0;
+                }
+                if (op1 & 1) {
+                    return 0; /* PLD* or unallocated hint */
+                }
+                if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
+                    return 0; /* PLD* or unallocated hint */
+                }
+                /* UNDEF space, or an UNPREDICTABLE */
+                return 1;
+            }
+        }
         user = IS_USER(s);
         if (rn == 15) {
             addr = new_tmp();
@@ -8324,9 +8360,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                 imm = insn & 0xfff;
                 tcg_gen_addi_i32(addr, addr, imm);
             } else {
-                op = (insn >> 8) & 7;
                 imm = insn & 0xff;
-                switch (op) {
+                switch ((insn >> 8) & 7) {
                 case 0: case 8: /* Shifted Register.  */
                     shift = (insn >> 4) & 0xf;
                     if (shift > 3)
@@ -8363,32 +8398,23 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
                 }
             }
         }
-        op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
         if (insn & (1 << 20)) {
             /* Load.  */
-            if (rs == 15 && op != 2) {
-                if (op & 2)
-                    goto illegal_op;
-                /* Memory hint.  Implemented as NOP.  */
+            switch (op) {
+            case 0: tmp = gen_ld8u(addr, user); break;
+            case 4: tmp = gen_ld8s(addr, user); break;
+            case 1: tmp = gen_ld16u(addr, user); break;
+            case 5: tmp = gen_ld16s(addr, user); break;
+            case 2: tmp = gen_ld32(addr, user); break;
+            default: goto illegal_op;
+            }
+            if (rs == 15) {
+                gen_bx(s, tmp);
             } else {
-                switch (op) {
-                case 0: tmp = gen_ld8u(addr, user); break;
-                case 4: tmp = gen_ld8s(addr, user); break;
-                case 1: tmp = gen_ld16u(addr, user); break;
-                case 5: tmp = gen_ld16s(addr, user); break;
-                case 2: tmp = gen_ld32(addr, user); break;
-                default: goto illegal_op;
-                }
-                if (rs == 15) {
-                    gen_bx(s, tmp);
-                } else {
-                    store_reg(s, rs, tmp);
-                }
+                store_reg(s, rs, tmp);
             }
         } else {
             /* Store.  */
-            if (rs == 15)
-                goto illegal_op;
             tmp = load_reg(s, rs);
             switch (op) {
             case 0: gen_st8(tmp, addr, user); break;
commit 3d185e5dd4967b7d03772d806ee566ed09d67485
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Feb 3 19:43:24 2011 +0000

    target-arm: Fix decoding of preload and memory hint space
    
    Correct the decoding of the ARM preload and memory hint space,
    by adding decoding of PLI, PLDW and the v7MP unallocated hint
    space. This commit also corrects a slightly overexuberant
    decoding of PLD(register) which was not checking that bit 4
    was one.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 5149543..a8f1ffe 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6100,9 +6100,31 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                 goto illegal_op;
             return;
         }
-        if ((insn & 0x0d70f000) == 0x0550f000)
-            return; /* PLD */
-        else if ((insn & 0x0ffffdff) == 0x01010000) {
+        if (((insn & 0x0f30f000) == 0x0510f000) ||
+            ((insn & 0x0f30f010) == 0x0710f000)) {
+            if ((insn & (1 << 22)) == 0) {
+                /* PLDW; v7MP */
+                if (!arm_feature(env, ARM_FEATURE_V7MP)) {
+                    goto illegal_op;
+                }
+            }
+            /* Otherwise PLD; v5TE+ */
+            return;
+        }
+        if (((insn & 0x0f70f000) == 0x0450f000) ||
+            ((insn & 0x0f70f010) == 0x0650f000)) {
+            ARCH(7);
+            return; /* PLI; V7 */
+        }
+        if (((insn & 0x0f700000) == 0x04100000) ||
+            ((insn & 0x0f700010) == 0x06100000)) {
+            if (!arm_feature(env, ARM_FEATURE_V7MP)) {
+                goto illegal_op;
+            }
+            return; /* v7MP: Unallocated memory hint: must NOP */
+        }
+
+        if ((insn & 0x0ffffdff) == 0x01010000) {
             ARCH(6);
             /* setend */
             if (insn & (1 << 9)) {
commit 607b4b0876bd3b1f33786ecc010ca2723de57270
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Feb 3 19:43:23 2011 +0000

    target-arm: Clean up handling of MPIDR
    
    The ARM cp15 register 0,c0,c0,5 is standardised in the v7 architecture
    as the MPIDR. Clean up its implementation to remove A9 specific handling.
    
    This commit includes fixing an error in the value returned for the
    MPIDR on A9, where we were erroneously claiming a cluster ID of 9.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helper.c b/target-arm/helper.c
index 3cf9181..d46defc 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1608,12 +1608,28 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
                     return 0;
                 case 3: /* TLB type register.  */
                     return 0; /* No lockable TLB entries.  */
-                case 5: /* CPU ID */
-                    if (ARM_CPUID(env) == ARM_CPUID_CORTEXA9) {
-                        return env->cpu_index | 0x80000900;
-                    } else {
-                        return env->cpu_index;
+                case 5: /* MPIDR */
+                    /* The MPIDR was standardised in v7; prior to
+                     * this it was implemented only in the 11MPCore.
+                     * For all other pre-v7 cores it does not exist.
+                     */
+                    if (arm_feature(env, ARM_FEATURE_V7) ||
+                        ARM_CPUID(env) == ARM_CPUID_ARM11MPCORE) {
+                        int mpidr = env->cpu_index;
+                        /* We don't support setting cluster ID ([8..11])
+                         * so these bits always RAZ.
+                         */
+                        if (arm_feature(env, ARM_FEATURE_V7MP)) {
+                            mpidr |= (1 << 31);
+                            /* Cores which are uniprocessor (non-coherent)
+                             * but still implement the MP extensions set
+                             * bit 30. (For instance, A9UP.) However we do
+                             * not currently model any of those cores.
+                             */
+                        }
+                        return mpidr;
                     }
+                    /* otherwise fall through to the unimplemented-reg case */
                 default:
                     goto bad_reg;
                 }
commit e1bbf44636a7435be0582f56aa0947d5186d6009
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Thu Feb 3 19:43:22 2011 +0000

    target-arm: Add CPU feature flag for v7MP
    
    Add a CPU feature flag for v7MP (the multiprocessing extensions); some
    instructions exist only for v7MP and not for the base v7 architecture.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 5bcd53a..0d96325 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -362,7 +362,8 @@ enum arm_features {
     ARM_FEATURE_DIV,
     ARM_FEATURE_M, /* Microcontroller profile.  */
     ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling.  */
-    ARM_FEATURE_THUMB2EE
+    ARM_FEATURE_THUMB2EE,
+    ARM_FEATURE_V7MP    /* v7 Multiprocessing Extensions */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index b562767..3cf9181 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -123,6 +123,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         set_feature(env, ARM_FEATURE_VFP_FP16);
         set_feature(env, ARM_FEATURE_NEON);
         set_feature(env, ARM_FEATURE_THUMB2EE);
+        /* Note that A9 supports the MP extensions even for
+         * A9UP and single-core A9MP (which are both different
+         * and valid configurations; we don't model A9UP).
+         */
+        set_feature(env, ARM_FEATURE_V7MP);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x41034000; /* Guess */
         env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222;
         env->vfp.xregs[ARM_VFP_MVFR1] = 0x01111111;
@@ -152,6 +157,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         set_feature(env, ARM_FEATURE_NEON);
         set_feature(env, ARM_FEATURE_THUMB2EE);
         set_feature(env, ARM_FEATURE_DIV);
+        set_feature(env, ARM_FEATURE_V7MP);
         break;
     case ARM_CPUID_TI915T:
     case ARM_CPUID_TI925T:
commit 4fef930af8d7fab4b6c777fa4c6e2b902359262a
Author: Gleb Natapov <gleb at redhat.com>
Date:   Wed Feb 2 17:34:34 2011 +0200

    do not pass NULL to strdup.
    
    Also use qemu_strdup() instead of strdup() in bootindex code.
    
    Signed-off-by: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/vl.c b/vl.c
index 655617f..ed2cdfa 100644
--- a/vl.c
+++ b/vl.c
@@ -738,7 +738,7 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev,
 
     node = qemu_mallocz(sizeof(FWBootEntry));
     node->bootindex = bootindex;
-    node->suffix = strdup(suffix);
+    node->suffix = suffix ? qemu_strdup(suffix) : NULL;
     node->dev = dev;
 
     QTAILQ_FOREACH(i, &fw_boot_order, link) {
@@ -785,7 +785,7 @@ char *get_boot_devices_list(uint32_t *size)
         } else if (devpath) {
             bootpath = devpath;
         } else {
-            bootpath = strdup(i->suffix);
+            bootpath = qemu_strdup(i->suffix);
             assert(bootpath);
         }
 
commit 72902672dc2ed6281cdb205259c1d52ecf01f6b2
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Fri Feb 4 15:17:51 2011 +0100

    Set the right overflow bit for neon 32 and 64 bit saturating add/sub.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index b88ebae..8a2564e 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -137,10 +137,6 @@ DEF_HELPER_2(rsqrte_f32, f32, f32, env)
 DEF_HELPER_2(recpe_u32, i32, i32, env)
 DEF_HELPER_2(rsqrte_u32, i32, i32, env)
 DEF_HELPER_4(neon_tbl, i32, i32, i32, i32, i32)
-DEF_HELPER_2(neon_add_saturate_u64, i64, i64, i64)
-DEF_HELPER_2(neon_add_saturate_s64, i64, i64, i64)
-DEF_HELPER_2(neon_sub_saturate_u64, i64, i64, i64)
-DEF_HELPER_2(neon_sub_saturate_s64, i64, i64, i64)
 
 DEF_HELPER_2(add_cc, i32, i32, i32)
 DEF_HELPER_2(adc_cc, i32, i32, i32)
@@ -160,10 +156,18 @@ DEF_HELPER_3(neon_qadd_u8, i32, env, i32, i32)
 DEF_HELPER_3(neon_qadd_s8, i32, env, i32, i32)
 DEF_HELPER_3(neon_qadd_u16, i32, env, i32, i32)
 DEF_HELPER_3(neon_qadd_s16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qadd_u32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qadd_s32, i32, env, i32, i32)
 DEF_HELPER_3(neon_qsub_u8, i32, env, i32, i32)
 DEF_HELPER_3(neon_qsub_s8, i32, env, i32, i32)
 DEF_HELPER_3(neon_qsub_u16, i32, env, i32, i32)
 DEF_HELPER_3(neon_qsub_s16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qsub_u32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qsub_s32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qadd_u64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qadd_s64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qsub_u64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qsub_s64, i64, env, i64, i64)
 
 DEF_HELPER_2(neon_hadd_s8, i32, i32, i32)
 DEF_HELPER_2(neon_hadd_u8, i32, i32, i32)
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index fead152..268af33 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -198,6 +198,28 @@ NEON_VOP_ENV(qadd_u16, neon_u16, 2)
 #undef NEON_FN
 #undef NEON_USAT
 
+uint32_t HELPER(neon_qadd_u32)(CPUState *env, uint32_t a, uint32_t b)
+{
+    uint32_t res = a + b;
+    if (res < a) {
+        SET_QC();
+        res = ~0;
+    }
+    return res;
+}
+
+uint64_t HELPER(neon_qadd_u64)(CPUState *env, uint64_t src1, uint64_t src2)
+{
+    uint64_t res;
+
+    res = src1 + src2;
+    if (res < src1) {
+        SET_QC();
+        res = ~(uint64_t)0;
+    }
+    return res;
+}
+
 #define NEON_SSAT(dest, src1, src2, type) do { \
     int32_t tmp = (uint32_t)src1 + (uint32_t)src2; \
     if (tmp != (type)tmp) { \
@@ -218,6 +240,28 @@ NEON_VOP_ENV(qadd_s16, neon_s16, 2)
 #undef NEON_FN
 #undef NEON_SSAT
 
+uint32_t HELPER(neon_qadd_s32)(CPUState *env, uint32_t a, uint32_t b)
+{
+    uint32_t res = a + b;
+    if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
+        SET_QC();
+        res = ~(((int32_t)a >> 31) ^ SIGNBIT);
+    }
+    return res;
+}
+
+uint64_t HELPER(neon_qadd_s64)(CPUState *env, uint64_t src1, uint64_t src2)
+{
+    uint64_t res;
+
+    res = src1 + src2;
+    if (((res ^ src1) & SIGNBIT64) && !((src1 ^ src2) & SIGNBIT64)) {
+        SET_QC();
+        res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64;
+    }
+    return res;
+}
+
 #define NEON_USAT(dest, src1, src2, type) do { \
     uint32_t tmp = (uint32_t)src1 - (uint32_t)src2; \
     if (tmp != (type)tmp) { \
@@ -234,6 +278,29 @@ NEON_VOP_ENV(qsub_u16, neon_u16, 2)
 #undef NEON_FN
 #undef NEON_USAT
 
+uint32_t HELPER(neon_qsub_u32)(CPUState *env, uint32_t a, uint32_t b)
+{
+    uint32_t res = a - b;
+    if (res > a) {
+        SET_QC();
+        res = 0;
+    }
+    return res;
+}
+
+uint64_t HELPER(neon_qsub_u64)(CPUState *env, uint64_t src1, uint64_t src2)
+{
+    uint64_t res;
+
+    if (src1 < src2) {
+        SET_QC();
+        res = 0;
+    } else {
+        res = src1 - src2;
+    }
+    return res;
+}
+
 #define NEON_SSAT(dest, src1, src2, type) do { \
     int32_t tmp = (uint32_t)src1 - (uint32_t)src2; \
     if (tmp != (type)tmp) { \
@@ -254,6 +321,28 @@ NEON_VOP_ENV(qsub_s16, neon_s16, 2)
 #undef NEON_FN
 #undef NEON_SSAT
 
+uint32_t HELPER(neon_qsub_s32)(CPUState *env, uint32_t a, uint32_t b)
+{
+    uint32_t res = a - b;
+    if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) {
+        SET_QC();
+        res = ~(((int32_t)a >> 31) ^ SIGNBIT);
+    }
+    return res;
+}
+
+uint64_t HELPER(neon_qsub_s64)(CPUState *env, uint64_t src1, uint64_t src2)
+{
+    uint64_t res;
+
+    res = src1 - src2;
+    if (((res ^ src1) & SIGNBIT64) && ((src1 ^ src2) & SIGNBIT64)) {
+        SET_QC();
+        res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64;
+    }
+    return res;
+}
+
 #define NEON_FN(dest, src1, src2) dest = (src1 + src2) >> 1
 NEON_VOP(hadd_s8, neon_s8, 4)
 NEON_VOP(hadd_u8, neon_u8, 4)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 43baa63..3de2610 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -424,52 +424,3 @@ uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i)
         return ((uint32_t)x >> shift) | (x << (32 - shift));
     }
 }
-
-uint64_t HELPER(neon_add_saturate_s64)(uint64_t src1, uint64_t src2)
-{
-    uint64_t res;
-
-    res = src1 + src2;
-    if (((res ^ src1) & SIGNBIT64) && !((src1 ^ src2) & SIGNBIT64)) {
-        env->QF = 1;
-        res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64;
-    }
-    return res;
-}
-
-uint64_t HELPER(neon_add_saturate_u64)(uint64_t src1, uint64_t src2)
-{
-    uint64_t res;
-
-    res = src1 + src2;
-    if (res < src1) {
-        env->QF = 1;
-        res = ~(uint64_t)0;
-    }
-    return res;
-}
-
-uint64_t HELPER(neon_sub_saturate_s64)(uint64_t src1, uint64_t src2)
-{
-    uint64_t res;
-
-    res = src1 - src2;
-    if (((res ^ src1) & SIGNBIT64) && ((src1 ^ src2) & SIGNBIT64)) {
-        env->QF = 1;
-        res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64;
-    }
-    return res;
-}
-
-uint64_t HELPER(neon_sub_saturate_u64)(uint64_t src1, uint64_t src2)
-{
-    uint64_t res;
-
-    if (src1 < src2) {
-        env->QF = 1;
-        res = 0;
-    } else {
-        res = src1 - src2;
-    }
-    return res;
-}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 92d0ef0..5149543 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3539,12 +3539,6 @@ static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
 #define gen_helper_neon_pmin_s32  gen_helper_neon_min_s32
 #define gen_helper_neon_pmin_u32  gen_helper_neon_min_u32
 
-/* FIXME: This is wrong.  They set the wrong overflow bit.  */
-#define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
-#define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
-#define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
-#define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
-
 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
     switch ((size << 1) | u) { \
     case 0: \
@@ -4233,16 +4227,20 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 switch (op) {
                 case 1: /* VQADD */
                     if (u) {
-                        gen_helper_neon_add_saturate_u64(CPU_V001);
+                        gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
+                                                 cpu_V0, cpu_V1);
                     } else {
-                        gen_helper_neon_add_saturate_s64(CPU_V001);
+                        gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
+                                                 cpu_V0, cpu_V1);
                     }
                     break;
                 case 5: /* VQSUB */
                     if (u) {
-                        gen_helper_neon_sub_saturate_u64(CPU_V001);
+                        gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
+                                                 cpu_V0, cpu_V1);
                     } else {
-                        gen_helper_neon_sub_saturate_s64(CPU_V001);
+                        gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
+                                                 cpu_V0, cpu_V1);
                     }
                     break;
                 case 8: /* VSHL */
commit 5371cb81405a35ca4c1f6ab23f93a4f7260ffa53
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Tue Jan 25 18:18:08 2011 +0100

    target-arm: Fix Neon vsra instructions.
    
    This patch fixes the errors reported by my tests in VSRA.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index d95133f..92d0ef0 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4686,7 +4686,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         }
                         if (op == 1 || op == 3) {
                             /* Accumulate.  */
-                            neon_load_reg64(cpu_V0, rd + pass);
+                            neon_load_reg64(cpu_V1, rd + pass);
                             tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
                         } else if (op == 4 || (op == 5 && u)) {
                             /* Insert */
@@ -4750,7 +4750,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         if (op == 1 || op == 3) {
                             /* Accumulate.  */
                             tmp2 = neon_load_reg(rd, pass);
-                            gen_neon_add(size, tmp2, tmp);
+                            gen_neon_add(size, tmp, tmp2);
                             dead_tmp(tmp2);
                         } else if (op == 4 || (op == 5 && u)) {
                             /* Insert */
commit 7026259f79ffc85ceaaaeee32df518ea96863ee4
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Fri Feb 4 20:19:33 2011 +0100

    target-sh4: fix negc
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 35573be..58e9b8f 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -960,9 +960,9 @@ static void _decode_opc(DisasContext * ctx)
             tcg_gen_andi_i32(t1, cpu_sr, SR_T);
             tcg_gen_sub_i32(REG(B11_8), t0, t1);
             tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
-            tcg_gen_setcond_i32(TCG_COND_GE, t1, REG(B11_8), t0);
+            tcg_gen_setcondi_i32(TCG_COND_GTU, t1, t0, 0);
             tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
-            tcg_gen_setcondi_i32(TCG_COND_GE, t1, t0, 0);
+            tcg_gen_setcond_i32(TCG_COND_GTU, t1, REG(B11_8), t0);
             tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
             tcg_temp_free(t0);
             tcg_temp_free(t1);
commit 1f5e71a8e6b24dce74b156472ff9253b9bd33a11
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Thu Feb 3 22:54:14 2011 +0100

    ioapic: Style & magics cleanup
    
    Fix a few style issues and convert magic numbers into prober symbolic
    constants, also fixing the wrong but unused IOAPIC_DM_SIPI value.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ioapic.c b/hw/ioapic.c
index fb3d173..569327d 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -39,20 +39,48 @@
 
 #define MAX_IOAPICS                     1
 
-#define IOAPIC_LVT_MASKED               (1 << 16)
-#define IOAPIC_LVT_REMOTE_IRR           (1 << 14)
+#define IOAPIC_VERSION                  0x11
 
-#define IOAPIC_TRIGGER_EDGE		0
-#define IOAPIC_TRIGGER_LEVEL		1
+#define IOAPIC_LVT_DEST_SHIFT           56
+#define IOAPIC_LVT_MASKED_SHIFT         16
+#define IOAPIC_LVT_TRIGGER_MODE_SHIFT   15
+#define IOAPIC_LVT_REMOTE_IRR_SHIFT     14
+#define IOAPIC_LVT_POLARITY_SHIFT       13
+#define IOAPIC_LVT_DELIV_STATUS_SHIFT   12
+#define IOAPIC_LVT_DEST_MODE_SHIFT      11
+#define IOAPIC_LVT_DELIV_MODE_SHIFT     8
+
+#define IOAPIC_LVT_MASKED               (1 << IOAPIC_LVT_MASKED_SHIFT)
+#define IOAPIC_LVT_REMOTE_IRR           (1 << IOAPIC_LVT_REMOTE_IRR_SHIFT)
+
+#define IOAPIC_TRIGGER_EDGE             0
+#define IOAPIC_TRIGGER_LEVEL            1
 
 /*io{apic,sapic} delivery mode*/
-#define IOAPIC_DM_FIXED			0x0
-#define IOAPIC_DM_LOWEST_PRIORITY	0x1
-#define IOAPIC_DM_PMI			0x2
-#define IOAPIC_DM_NMI			0x4
-#define IOAPIC_DM_INIT			0x5
-#define IOAPIC_DM_SIPI			0x5
-#define IOAPIC_DM_EXTINT		0x7
+#define IOAPIC_DM_FIXED                 0x0
+#define IOAPIC_DM_LOWEST_PRIORITY       0x1
+#define IOAPIC_DM_PMI                   0x2
+#define IOAPIC_DM_NMI                   0x4
+#define IOAPIC_DM_INIT                  0x5
+#define IOAPIC_DM_SIPI                  0x6
+#define IOAPIC_DM_EXTINT                0x7
+#define IOAPIC_DM_MASK                  0x7
+
+#define IOAPIC_VECTOR_MASK              0xff
+
+#define IOAPIC_IOREGSEL                 0x00
+#define IOAPIC_IOWIN                    0x10
+
+#define IOAPIC_REG_ID                   0x00
+#define IOAPIC_REG_VER                  0x01
+#define IOAPIC_REG_ARB                  0x02
+#define IOAPIC_REG_REDTBL_BASE          0x10
+#define IOAPIC_ID                       0x00
+
+#define IOAPIC_ID_SHIFT                 24
+#define IOAPIC_ID_MASK                  0xf
+
+#define IOAPIC_VER_ENTRIES_SHIFT        16
 
 typedef struct IOAPICState IOAPICState;
 
@@ -60,7 +88,6 @@ struct IOAPICState {
     SysBusDevice busdev;
     uint8_t id;
     uint8_t ioregsel;
-
     uint32_t irr;
     uint64_t ioredtbl[IOAPIC_NUM_PINS];
 };
@@ -84,21 +111,22 @@ static void ioapic_service(IOAPICState *s)
         if (s->irr & mask) {
             entry = s->ioredtbl[i];
             if (!(entry & IOAPIC_LVT_MASKED)) {
-                trig_mode = ((entry >> 15) & 1);
-                dest = entry >> 56;
-                dest_mode = (entry >> 11) & 1;
-                delivery_mode = (entry >> 8) & 7;
-                polarity = (entry >> 13) & 1;
+                trig_mode = ((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1);
+                dest = entry >> IOAPIC_LVT_DEST_SHIFT;
+                dest_mode = (entry >> IOAPIC_LVT_DEST_MODE_SHIFT) & 1;
+                delivery_mode =
+                    (entry >> IOAPIC_LVT_DELIV_MODE_SHIFT) & IOAPIC_DM_MASK;
+                polarity = (entry >> IOAPIC_LVT_POLARITY_SHIFT) & 1;
                 if (trig_mode == IOAPIC_TRIGGER_EDGE) {
                     s->irr &= ~mask;
                 } else {
                     s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR;
                 }
-                if (delivery_mode == IOAPIC_DM_EXTINT)
+                if (delivery_mode == IOAPIC_DM_EXTINT) {
                     vector = pic_read_irq(isa_pic);
-                else
-                    vector = entry & 0xff;
-
+                } else {
+                    vector = entry & IOAPIC_VECTOR_MASK;
+                }
                 apic_deliver_irq(dest, dest_mode, delivery_mode,
                                  vector, polarity, trig_mode);
             }
@@ -114,15 +142,16 @@ static void ioapic_set_irq(void *opaque, int vector, int level)
      * to GSI 2.  GSI maps to ioapic 1-1.  This is not
      * the cleanest way of doing it but it should work. */
 
-    DPRINTF("%s: %s vec %x\n", __func__, level? "raise" : "lower", vector);
-    if (vector == 0)
+    DPRINTF("%s: %s vec %x\n", __func__, level ? "raise" : "lower", vector);
+    if (vector == 0) {
         vector = 2;
-
+    }
     if (vector >= 0 && vector < IOAPIC_NUM_PINS) {
         uint32_t mask = 1 << vector;
         uint64_t entry = s->ioredtbl[vector];
 
-        if ((entry >> 15) & 1) {
+        if (((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1) ==
+            IOAPIC_TRIGGER_LEVEL) {
             /* level triggered */
             if (level) {
                 s->irr |= mask;
@@ -153,7 +182,8 @@ void ioapic_eoi_broadcast(int vector)
         }
         for (n = 0; n < IOAPIC_NUM_PINS; n++) {
             entry = s->ioredtbl[n];
-            if ((entry & IOAPIC_LVT_REMOTE_IRR) && (entry & 0xff) == vector) {
+            if ((entry & IOAPIC_LVT_REMOTE_IRR)
+                && (entry & IOAPIC_VECTOR_MASK) == vector) {
                 s->ioredtbl[n] = entry & ~IOAPIC_LVT_REMOTE_IRR;
                 if (!(entry & IOAPIC_LVT_MASKED) && (s->irr & (1 << n))) {
                     ioapic_service(s);
@@ -169,65 +199,71 @@ static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
     int index;
     uint32_t val = 0;
 
-    addr &= 0xff;
-    if (addr == 0x00) {
+    switch (addr & 0xff) {
+    case IOAPIC_IOREGSEL:
         val = s->ioregsel;
-    } else if (addr == 0x10) {
+        break;
+    case IOAPIC_IOWIN:
         switch (s->ioregsel) {
-            case 0x00:
-                val = s->id << 24;
-                break;
-            case 0x01:
-                val = 0x11 | ((IOAPIC_NUM_PINS - 1) << 16); /* version 0x11 */
-                break;
-            case 0x02:
-                val = 0;
-                break;
-            default:
-                index = (s->ioregsel - 0x10) >> 1;
-                if (index >= 0 && index < IOAPIC_NUM_PINS) {
-                    if (s->ioregsel & 1)
-                        val = s->ioredtbl[index] >> 32;
-                    else
-                        val = s->ioredtbl[index] & 0xffffffff;
+        case IOAPIC_REG_ID:
+            val = s->id << IOAPIC_ID_SHIFT;
+            break;
+        case IOAPIC_REG_VER:
+            val = IOAPIC_VERSION |
+                ((IOAPIC_NUM_PINS - 1) << IOAPIC_VER_ENTRIES_SHIFT);
+            break;
+        case IOAPIC_REG_ARB:
+            val = 0;
+            break;
+        default:
+            index = (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1;
+            if (index >= 0 && index < IOAPIC_NUM_PINS) {
+                if (s->ioregsel & 1) {
+                    val = s->ioredtbl[index] >> 32;
+                } else {
+                    val = s->ioredtbl[index] & 0xffffffff;
                 }
+            }
         }
         DPRINTF("read: %08x = %08x\n", s->ioregsel, val);
+        break;
     }
     return val;
 }
 
-static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void
+ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     IOAPICState *s = opaque;
     int index;
 
-    addr &= 0xff;
-    if (addr == 0x00)  {
+    switch (addr & 0xff) {
+    case IOAPIC_IOREGSEL:
         s->ioregsel = val;
-        return;
-    } else if (addr == 0x10) {
+        break;
+    case IOAPIC_IOWIN:
         DPRINTF("write: %08x = %08x\n", s->ioregsel, val);
         switch (s->ioregsel) {
-            case 0x00:
-                s->id = (val >> 24) & 0xff;
-                return;
-            case 0x01:
-            case 0x02:
-                return;
-            default:
-                index = (s->ioregsel - 0x10) >> 1;
-                if (index >= 0 && index < IOAPIC_NUM_PINS) {
-                    if (s->ioregsel & 1) {
-                        s->ioredtbl[index] &= 0xffffffff;
-                        s->ioredtbl[index] |= (uint64_t)val << 32;
-                    } else {
-                        s->ioredtbl[index] &= ~0xffffffffULL;
-                        s->ioredtbl[index] |= val;
-                    }
-                    ioapic_service(s);
+        case IOAPIC_REG_ID:
+            s->id = (val >> IOAPIC_ID_SHIFT) & IOAPIC_ID_MASK;
+            break;
+        case IOAPIC_REG_VER:
+        case IOAPIC_REG_ARB:
+            break;
+        default:
+            index = (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1;
+            if (index >= 0 && index < IOAPIC_NUM_PINS) {
+                if (s->ioregsel & 1) {
+                    s->ioredtbl[index] &= 0xffffffff;
+                    s->ioredtbl[index] |= (uint64_t)val << 32;
+                } else {
+                    s->ioredtbl[index] &= ~0xffffffffULL;
+                    s->ioredtbl[index] |= val;
                 }
+                ioapic_service(s);
+            }
         }
+        break;
     }
 }
 
@@ -248,7 +284,7 @@ static const VMStateDescription vmstate_ioapic = {
     .post_load = ioapic_post_load,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
+    .fields = (VMStateField[]) {
         VMSTATE_UINT8(id, IOAPICState),
         VMSTATE_UINT8(ioregsel, IOAPICState),
         VMSTATE_UNUSED_V(2, 8), /* to account for qemu-kvm's v2 format */
@@ -266,8 +302,9 @@ static void ioapic_reset(DeviceState *d)
     s->id = 0;
     s->ioregsel = 0;
     s->irr = 0;
-    for(i = 0; i < IOAPIC_NUM_PINS; i++)
-        s->ioredtbl[i] = 1 << 16; /* mask LVT */
+    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+        s->ioredtbl[i] = 1 << IOAPIC_LVT_MASKED_SHIFT;
+    }
 }
 
 static CPUReadMemoryFunc * const ioapic_mem_read[3] = {
commit 5dce499948e4a4abe62f010baf4a7ed3d49e53cb
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Thu Feb 3 22:54:13 2011 +0100

    ioapic: Add support for qemu-kvm's vmstate v2
    
    qemu-kvm carries the IOAPIC base address in its v2 vmstate. We only
    support the default base address so far, and saving even that in the
    device state was rejected.
    
    Add a padding field to be able to read qemu-kvm's old state, but
    increase our version to 3, indicating that we are not saving a valid
    address. This also gives downstream the chance to change to stop
    evaluating the base_address and move to v3 as well.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ioapic.c b/hw/ioapic.c
index 8c46c1d..fb3d173 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -244,13 +244,14 @@ static int ioapic_post_load(void *opaque, int version_id)
 
 static const VMStateDescription vmstate_ioapic = {
     .name = "ioapic",
-    .version_id = 2,
+    .version_id = 3,
     .post_load = ioapic_post_load,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
         VMSTATE_UINT8(id, IOAPICState),
         VMSTATE_UINT8(ioregsel, IOAPICState),
+        VMSTATE_UNUSED_V(2, 8), /* to account for qemu-kvm's v2 format */
         VMSTATE_UINT32_V(irr, IOAPICState, 2),
         VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICState, IOAPIC_NUM_PINS),
         VMSTATE_END_OF_LIST()
commit 35a74c5c5941b474d8b985237e1bde0b8cd2a20f
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Thu Feb 3 22:54:12 2011 +0100

    ioapic: Save/restore irr
    
    This is a guest modifiable state that must be saved/restored properly.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/ioapic.c b/hw/ioapic.c
index 8bc31f7..8c46c1d 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -231,14 +231,27 @@ static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
     }
 }
 
+static int ioapic_post_load(void *opaque, int version_id)
+{
+    IOAPICState *s = opaque;
+
+    if (version_id == 1) {
+        /* set sane value */
+        s->irr = 0;
+    }
+    return 0;
+}
+
 static const VMStateDescription vmstate_ioapic = {
     .name = "ioapic",
-    .version_id = 1,
+    .version_id = 2,
+    .post_load = ioapic_post_load,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
         VMSTATE_UINT8(id, IOAPICState),
         VMSTATE_UINT8(ioregsel, IOAPICState),
+        VMSTATE_UINT32_V(irr, IOAPICState, 2),
         VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICState, IOAPIC_NUM_PINS),
         VMSTATE_END_OF_LIST()
     }
commit 0280b571c1a153f8926612d8c8d7359242d596f5
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Thu Feb 3 22:54:11 2011 +0100

    ioapic: Implement EOI handling for level-triggered IRQs
    
    Add the missing EOI broadcast from local APIC to the IOAPICs on
    completion of level-triggered IRQs. This ensures that a still asserted
    IRQ source properly re-triggers an APIC IRQ.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/apic.c b/hw/apic.c
index ff581f0..2f8376a 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -18,6 +18,7 @@
  */
 #include "hw.h"
 #include "apic.h"
+#include "ioapic.h"
 #include "qemu-timer.h"
 #include "host-utils.h"
 #include "sysbus.h"
@@ -57,7 +58,8 @@
 
 #define ESR_ILLEGAL_ADDRESS (1 << 7)
 
-#define APIC_SV_ENABLE (1 << 8)
+#define APIC_SV_DIRECTED_IO             (1<<12)
+#define APIC_SV_ENABLE                  (1<<8)
 
 #define MAX_APICS 255
 #define MAX_APIC_WORDS 8
@@ -420,8 +422,9 @@ static void apic_eoi(APICState *s)
     if (isrv < 0)
         return;
     reset_bit(s->isr, isrv);
-    /* XXX: send the EOI packet to the APIC bus to allow the I/O APIC to
-            set the remote IRR bit for level triggered interrupts. */
+    if (!(s->spurious_vec & APIC_SV_DIRECTED_IO) && get_bit(s->tmr, isrv)) {
+        ioapic_eoi_broadcast(isrv);
+    }
     apic_update_irq(s);
 }
 
diff --git a/hw/ioapic.c b/hw/ioapic.c
index 2109568..8bc31f7 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -23,6 +23,7 @@
 #include "hw.h"
 #include "pc.h"
 #include "apic.h"
+#include "ioapic.h"
 #include "qemu-timer.h"
 #include "host-utils.h"
 #include "sysbus.h"
@@ -36,7 +37,10 @@
 #define DPRINTF(fmt, ...)
 #endif
 
-#define IOAPIC_LVT_MASKED 		(1<<16)
+#define MAX_IOAPICS                     1
+
+#define IOAPIC_LVT_MASKED               (1 << 16)
+#define IOAPIC_LVT_REMOTE_IRR           (1 << 14)
 
 #define IOAPIC_TRIGGER_EDGE		0
 #define IOAPIC_TRIGGER_LEVEL		1
@@ -61,6 +65,8 @@ struct IOAPICState {
     uint64_t ioredtbl[IOAPIC_NUM_PINS];
 };
 
+static IOAPICState *ioapics[MAX_IOAPICS];
+
 static void ioapic_service(IOAPICState *s)
 {
     uint8_t i;
@@ -83,8 +89,11 @@ static void ioapic_service(IOAPICState *s)
                 dest_mode = (entry >> 11) & 1;
                 delivery_mode = (entry >> 8) & 7;
                 polarity = (entry >> 13) & 1;
-                if (trig_mode == IOAPIC_TRIGGER_EDGE)
+                if (trig_mode == IOAPIC_TRIGGER_EDGE) {
                     s->irr &= ~mask;
+                } else {
+                    s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR;
+                }
                 if (delivery_mode == IOAPIC_DM_EXTINT)
                     vector = pic_read_irq(isa_pic);
                 else
@@ -131,6 +140,29 @@ static void ioapic_set_irq(void *opaque, int vector, int level)
     }
 }
 
+void ioapic_eoi_broadcast(int vector)
+{
+    IOAPICState *s;
+    uint64_t entry;
+    int i, n;
+
+    for (i = 0; i < MAX_IOAPICS; i++) {
+        s = ioapics[i];
+        if (!s) {
+            continue;
+        }
+        for (n = 0; n < IOAPIC_NUM_PINS; n++) {
+            entry = s->ioredtbl[n];
+            if ((entry & IOAPIC_LVT_REMOTE_IRR) && (entry & 0xff) == vector) {
+                s->ioredtbl[n] = entry & ~IOAPIC_LVT_REMOTE_IRR;
+                if (!(entry & IOAPIC_LVT_MASKED) && (s->irr & (1 << n))) {
+                    ioapic_service(s);
+                }
+            }
+        }
+    }
+}
+
 static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
 {
     IOAPICState *s = opaque;
@@ -240,6 +272,11 @@ static int ioapic_init1(SysBusDevice *dev)
 {
     IOAPICState *s = FROM_SYSBUS(IOAPICState, dev);
     int io_memory;
+    static int ioapic_no;
+
+    if (ioapic_no >= MAX_IOAPICS) {
+        return -1;
+    }
 
     io_memory = cpu_register_io_memory(ioapic_mem_read,
                                        ioapic_mem_write, s,
@@ -248,6 +285,8 @@ static int ioapic_init1(SysBusDevice *dev)
 
     qdev_init_gpio_in(&dev->qdev, ioapic_set_irq, IOAPIC_NUM_PINS);
 
+    ioapics[ioapic_no++] = s;
+
     return 0;
 }
 
diff --git a/hw/ioapic.h b/hw/ioapic.h
new file mode 100644
index 0000000..cb2642a
--- /dev/null
+++ b/hw/ioapic.h
@@ -0,0 +1,20 @@
+/*
+ *  ioapic.c IOAPIC emulation logic
+ *
+ *  Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+void ioapic_eoi_broadcast(int vector);
commit 73eb4c04e9e8ea7f6eb83694cb0c43e38d882a7c
Author: Corentin Chary <corentincj at iksaif.net>
Date:   Fri Feb 4 09:05:53 2011 +0100

    vnc: qemu can die if the client is disconnected while updating screen
    
    agraf reported that qemu_mutex_destroy(vs->output_mutex) while failing
    in vnc_disconnect_finish().
    
    It's because vnc_worker_thread_loop() tries to unlock the mutex while
    not locked. The unlocking call doesn't fail (pthread bug ?), but
    the destroy call does.
    
    Signed-off-by: Corentin Chary <corentincj at iksaif.net>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/vnc-jobs-async.c b/ui/vnc-jobs-async.c
index 6e9cf08..0b5d750 100644
--- a/ui/vnc-jobs-async.c
+++ b/ui/vnc-jobs-async.c
@@ -227,6 +227,10 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
 
         if (job->vs->csock == -1) {
             vnc_unlock_display(job->vs->vd);
+            /* output mutex must be locked before going to
+             * disconnected:
+             */
+            vnc_lock_output(job->vs);
             goto disconnected;
         }
 
commit 7185f9315bcf90e99b123370cf4d19b8c20afbd5
Author: Amit Shah <amit.shah at redhat.com>
Date:   Fri Feb 4 14:24:18 2011 +0530

    virtio-serial: Make sure virtqueue is ready before discarding data
    
    This can happen if a port gets unplugged before guest has chance to
    initialise vqs.
    
    Reported-by: Juan Quintela <quintela at redhat.com>
    Signed-off-by: Amit Shah <amit.shah 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 09e22aa..e05ab5e 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -117,6 +117,9 @@ static void discard_vq_data(VirtQueue *vq, VirtIODevice *vdev)
 {
     VirtQueueElement elem;
 
+    if (!virtio_queue_ready(vq)) {
+        return;
+    }
     while (virtqueue_pop(vq, &elem)) {
         virtqueue_push(vq, &elem, 0);
     }
commit 4e79bcbb96d3c189e50adbdac7b1e28d834ba43e
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Thu Feb 3 22:35:07 2011 +0100

    ui/sdl: Fix handling of caps lock and num lock keys
    
    Starting with SDL version 1.2.14, caps lock and num lock keys
    will send a SDL_KEYUP when SDL_DISABLE_LOCK_KEYS=1 is set in
    the environment.
    
    The new code sets the environment unconditionally
    (it won't harm old versions which do not know it).
    
    The workaround for SDL_KEYUP is only compiled with old SDL versions.
    
    A similar patch without handling of old SDL versions was already
    published by Benjamin Drung for Ubuntu.
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Cc: Kevin Wolf <kwolf at redhat.com>
    Cc: Benjamin Drung <benjamin.drung at gmail.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/ui/sdl.c b/ui/sdl.c
index a1458ce..47ac49c 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -388,12 +388,16 @@ static void sdl_process_key(SDL_KeyboardEvent *ev)
         else
             modifiers_state[keycode] = 1;
         break;
+#define QEMU_SDL_VERSION ((SDL_MAJOR_VERSION << 8) + SDL_MINOR_VERSION)
+#if QEMU_SDL_VERSION < 0x102 || QEMU_SDL_VERSION == 0x102 && SDL_PATCHLEVEL < 14
+        /* SDL versions before 1.2.14 don't support key up for caps/num lock. */
     case 0x45: /* num lock */
     case 0x3a: /* caps lock */
         /* SDL does not send the key up event, so we generate it */
         kbd_put_keycode(keycode);
         kbd_put_keycode(keycode | SCANCODE_UP);
         return;
+#endif
     }
 
     /* now send the key code */
@@ -831,6 +835,10 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
         setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
     }
 
+    /* Enable normal up/down events for Caps-Lock and Num-Lock keys.
+     * This requires SDL >= 1.2.14. */
+    setenv("SDL_DISABLE_LOCK_KEYS", "1", 1);
+
     flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
     if (SDL_Init (flags)) {
         fprintf(stderr, "Could not initialize SDL(%s) - exiting\n",
commit 4c3d45eb694de3e0bda10841a06ba98be4d569b1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Feb 3 14:49:01 2011 +0100

    Unify alarm deadline computation
    
    This patch shows how using the correct formula for
    qemu_next_deadline_dyntick can simplify the code of
    host_alarm_handler and eliminate useless duplication.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index 69e71d7..658f637 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -635,6 +635,8 @@ void qemu_run_all_timers(void)
     qemu_run_timers(host_clock);
 }
 
+static int64_t qemu_next_alarm_deadline(void);
+
 #ifdef _WIN32
 static void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg,
                                         DWORD_PTR dwUser, DWORD_PTR dw1,
@@ -677,14 +679,7 @@ static void host_alarm_handler(int host_signum)
     }
 #endif
     if (alarm_has_dynticks(t) ||
-        (!use_icount &&
-            qemu_timer_expired(active_timers[QEMU_CLOCK_VIRTUAL],
-                               qemu_get_clock(vm_clock))) ||
-        qemu_timer_expired(active_timers[QEMU_CLOCK_REALTIME],
-                           qemu_get_clock(rt_clock)) ||
-        qemu_timer_expired(active_timers[QEMU_CLOCK_HOST],
-                           qemu_get_clock(host_clock))) {
-
+        qemu_next_alarm_deadline () <= 0) {
         t->expired = alarm_has_dynticks(t);
         t->pending = 1;
         qemu_notify_event();
@@ -715,11 +710,7 @@ int64_t qemu_next_deadline(void)
 
 #ifndef _WIN32
 
-#if defined(__linux__)
-
-#define RTC_FREQ 1024
-
-static uint64_t qemu_next_deadline_dyntick(void)
+static int64_t qemu_next_alarm_deadline(void)
 {
     int64_t delta;
     int64_t rtdelta;
@@ -743,12 +734,13 @@ static uint64_t qemu_next_deadline_dyntick(void)
             delta = rtdelta;
     }
 
-    if (delta < MIN_TIMER_REARM_NS)
-        delta = MIN_TIMER_REARM_NS;
-
     return delta;
 }
 
+#if defined(__linux__)
+
+#define RTC_FREQ 1024
+
 static void enable_sigio_timer(int fd)
 {
     struct sigaction act;
@@ -903,7 +895,9 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
         !active_timers[QEMU_CLOCK_HOST])
         return;
 
-    nearest_delta_ns = qemu_next_deadline_dyntick();
+    nearest_delta_ns = qemu_next_alarm_deadline();
+    if (nearest_delta_ns < MIN_TIMER_REARM_NS)
+        nearest_delta_ns = MIN_TIMER_REARM_NS;
 
     /* check whether a timer is already running */
     if (timer_gettime(host_timer, &timeout)) {
commit 6ad0a1ed21ecd187dbe3239eb45c3598672af6a8
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Feb 3 14:49:00 2011 +0100

    Correct alarm deadline computation
    
    When the QEMU_CLOCK_HOST clock was added, computation of its
    deadline was added to qemu_next_deadline, which is correct but
    incomplete.
    
    I noticed this by reading the very convoluted rules whereby
    qemu_next_deadline_dyntick is computed, which miss QEMU_CLOCK_HOST
    when use_icount is true.  This patch inlines qemu_next_deadline
    into qemu_next_deadline_dyntick, and then corrects the logic to skip
    only QEMU_CLOCK_VIRTUAL when use_icount is true.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Cc: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index bda072f..69e71d7 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -724,11 +724,18 @@ static uint64_t qemu_next_deadline_dyntick(void)
     int64_t delta;
     int64_t rtdelta;
 
-    if (use_icount)
+    if (!use_icount && active_timers[QEMU_CLOCK_VIRTUAL]) {
+        delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
+                     qemu_get_clock(vm_clock);
+    } else {
         delta = INT32_MAX;
-    else
-        delta = qemu_next_deadline();
-
+    }
+    if (active_timers[QEMU_CLOCK_HOST]) {
+        int64_t hdelta = active_timers[QEMU_CLOCK_HOST]->expire_time -
+                 qemu_get_clock_ns(host_clock);
+        if (hdelta < delta)
+            delta = hdelta;
+    }
     if (active_timers[QEMU_CLOCK_REALTIME]) {
         rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time * 1000000 -
                  qemu_get_clock_ns(rt_clock));
commit 9c13246ac13a87e05b5e6e7158e715dfa65fc7aa
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Feb 3 14:48:59 2011 +0100

    use nanoseconds everywhere for timeout computation
    
    Suggested by Aurelien Jarno.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index db1ec49..bda072f 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -197,8 +197,8 @@ static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
     t->rearm(t);
 }
 
-/* TODO: MIN_TIMER_REARM_US should be optimized */
-#define MIN_TIMER_REARM_US 250
+/* TODO: MIN_TIMER_REARM_NS should be optimized */
+#define MIN_TIMER_REARM_NS 250000
 
 #ifdef _WIN32
 
@@ -698,11 +698,11 @@ int64_t qemu_next_deadline(void)
 
     if (active_timers[QEMU_CLOCK_VIRTUAL]) {
         delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
-                     qemu_get_clock(vm_clock);
+                     qemu_get_clock_ns(vm_clock);
     }
     if (active_timers[QEMU_CLOCK_HOST]) {
         int64_t hdelta = active_timers[QEMU_CLOCK_HOST]->expire_time -
-                 qemu_get_clock(host_clock);
+                 qemu_get_clock_ns(host_clock);
         if (hdelta < delta)
             delta = hdelta;
     }
@@ -727,17 +727,17 @@ static uint64_t qemu_next_deadline_dyntick(void)
     if (use_icount)
         delta = INT32_MAX;
     else
-        delta = (qemu_next_deadline() + 999) / 1000;
+        delta = qemu_next_deadline();
 
     if (active_timers[QEMU_CLOCK_REALTIME]) {
-        rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time -
-                 qemu_get_clock(rt_clock))*1000;
+        rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time * 1000000 -
+                 qemu_get_clock_ns(rt_clock));
         if (rtdelta < delta)
             delta = rtdelta;
     }
 
-    if (delta < MIN_TIMER_REARM_US)
-        delta = MIN_TIMER_REARM_US;
+    if (delta < MIN_TIMER_REARM_NS)
+        delta = MIN_TIMER_REARM_NS;
 
     return delta;
 }
@@ -887,8 +887,8 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
 {
     timer_t host_timer = (timer_t)(long)t->priv;
     struct itimerspec timeout;
-    int64_t nearest_delta_us = INT64_MAX;
-    int64_t current_us;
+    int64_t nearest_delta_ns = INT64_MAX;
+    int64_t current_ns;
 
     assert(alarm_has_dynticks(t));
     if (!active_timers[QEMU_CLOCK_REALTIME] &&
@@ -896,7 +896,7 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
         !active_timers[QEMU_CLOCK_HOST])
         return;
 
-    nearest_delta_us = qemu_next_deadline_dyntick();
+    nearest_delta_ns = qemu_next_deadline_dyntick();
 
     /* check whether a timer is already running */
     if (timer_gettime(host_timer, &timeout)) {
@@ -904,14 +904,14 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
         fprintf(stderr, "Internal timer error: aborting\n");
         exit(1);
     }
-    current_us = timeout.it_value.tv_sec * 1000000 + timeout.it_value.tv_nsec/1000;
-    if (current_us && current_us <= nearest_delta_us)
+    current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec;
+    if (current_ns && current_ns <= nearest_delta_ns)
         return;
 
     timeout.it_interval.tv_sec = 0;
     timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */
-    timeout.it_value.tv_sec =  nearest_delta_us / 1000000;
-    timeout.it_value.tv_nsec = (nearest_delta_us % 1000000) * 1000;
+    timeout.it_value.tv_sec =  nearest_delta_ns / 1000000000;
+    timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000;
     if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) {
         perror("settime");
         fprintf(stderr, "Internal timer error: aborting\n");
commit eb60260de0b050a5e8ab725e84d377d0b44c43ae
Author: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
Date:   Thu Feb 3 13:34:08 2011 +0900

    savevm: fix corruption in vmstate_subsection_load().
    
    Although it's rare to happen in live migration, when the head of a
    byte stream contains 0x05 which is the marker of subsection, the
    loader gets corrupted because vmstate_subsection_load() continues even
    the device doesn't require it.  This patch adds a checker whether
    subsection is needed, and skips following routines if not needed.
    
    Signed-off-by: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
    Acked-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/savevm.c b/savevm.c
index 4453217..6d83b0f 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1638,6 +1638,12 @@ static const VMStateDescription *vmstate_get_subsection(const VMStateSubsection
 static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
                                    void *opaque)
 {
+    const VMStateSubsection *sub = vmsd->subsections;
+
+    if (!sub || !sub->needed) {
+        return 0;
+    }
+
     while (qemu_peek_byte(f) == QEMU_VM_SUBSECTION) {
         char idstr[256];
         int ret;
@@ -1650,10 +1656,11 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
         idstr[len] = 0;
         version_id = qemu_get_be32(f);
 
-        sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);
+        sub_vmsd = vmstate_get_subsection(sub, idstr);
         if (sub_vmsd == NULL) {
             return -ENOENT;
         }
+        assert(!sub_vmsd->subsections);
         ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
         if (ret) {
             return ret;
@@ -1677,6 +1684,7 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
             qemu_put_byte(f, len);
             qemu_put_buffer(f, (uint8_t *)vmsd->name, len);
             qemu_put_be32(f, vmsd->version_id);
+            assert(!vmsd->subsections);
             vmstate_save_state(f, vmsd, opaque);
         }
         sub++;
commit 3593e6b592067d4a9a0131deedbe2581a9763548
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Thu Feb 3 06:57:46 2011 -0200

    qemu-kvm-x86: initialize has_msr_star/has_msr_hsave_pa
    
    Fixes 64-bit guest migration.
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index 2f1a090..4be5e32 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -509,6 +509,12 @@ int kvm_arch_qemu_create_context(void)
         kvm_set_shadow_pages(kvm_context, kvm_shadow_memory);
     }
 
+    /* initialize has_msr_star/has_msr_hsave_pa */
+    r = kvm_get_supported_msrs(kvm_state);
+    if (r < 0) {
+        return r;
+    }
+
     kvm_msr_list = kvm_get_msr_list();
     if (!kvm_msr_list) {
         return -1;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 5e0865a..f389b85 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -472,7 +472,6 @@ void kvm_arch_reset_vcpu(CPUState *env)
     }
 }
 
-#ifdef OBSOLETE_KVM_IMPL
 
 static int kvm_get_supported_msrs(KVMState *s)
 {
@@ -521,6 +520,8 @@ static int kvm_get_supported_msrs(KVMState *s)
     return ret;
 }
 
+#ifdef OBSOLETE_KVM_IMPL
+
 int kvm_arch_init(KVMState *s)
 {
     uint64_t identity_base = 0xfffbc000;
commit 4d330984eea55b7c7005e63710597bf72f84f753
Merge: 6f32e3d... 825cc54...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Feb 2 20:22:40 2011 -0200

    Merge branch 'upstream-merge'
    
    * upstream-merge: (177 commits)
      Open up the 0.15 development branch
      Update version for 0.14.0-rc0
      Update SeaBIOS to 0.6.1.2
      vhost: force vhost off for non-MSI guests
      tap: safe sndbuf default
      Add boot index documentation.
      Add bootindex handling into usb storage device.
      fix QemuOpts leak
      remove text_console_opts
      add set_echo implementation for text consoles
      create TextConsole together with the CharDeviceState
      add set_echo implementation for qemu_chr_stdio
      move atexit(term_exit) and O_NONBLOCK to qemu_chr_open_stdio
      add qemu_chr_set_echo
      remove broken code for tty
      vnc: Fix password expiration through 'change vnc ""' (v2)
      linux-user: avoid gcc array overrun warning for sparc
      hw/slavio_intctl.c: fix gcc warning about array bounds overrun
      SPARC: Fix Leon3 cache control
      blockdev: Fix drive_add for drives without media
      ...
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

commit 825cc54385606bc5e471da985ff7d695da249a8f
Merge: 2d2339f... bfddb47...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Feb 2 20:20:35 2011 -0200

    Merge commit 'bfddb47a343b4718e5768aa80bce8adead0f7fca' into upstream-merge
    
    * commit 'bfddb47a343b4718e5768aa80bce8adead0f7fca':
      Open up the 0.15 development branch
      Update version for 0.14.0-rc0
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

commit 2d2339f995d7176dcb2de10d162aed323a1ffbf3
Merge: 16b0249... f487d62...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Feb 2 20:18:11 2011 -0200

    Merge commit 'f487d6278f75f84378833b8c3a67443346d639dc' into upstream-merge
    
    * commit 'f487d6278f75f84378833b8c3a67443346d639dc': (140 commits)
      Update SeaBIOS to 0.6.1.2
      vhost: force vhost off for non-MSI guests
      tap: safe sndbuf default
      Add boot index documentation.
      Add bootindex handling into usb storage device.
      fix QemuOpts leak
      remove text_console_opts
      add set_echo implementation for text consoles
      create TextConsole together with the CharDeviceState
      add set_echo implementation for qemu_chr_stdio
      move atexit(term_exit) and O_NONBLOCK to qemu_chr_open_stdio
      add qemu_chr_set_echo
      remove broken code for tty
      vnc: Fix password expiration through 'change vnc ""' (v2)
      linux-user: avoid gcc array overrun warning for sparc
      hw/slavio_intctl.c: fix gcc warning about array bounds overrun
      SPARC: Fix Leon3 cache control
      blockdev: Fix drive_add for drives without media
      blockdev: Replace drive_add()'s fmt, ... by optstr parameter
      blockdev: Reject multiple definitions for the same drive
      ...
    
    Conflicts:
    	roms/seabios
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --cc Makefile.objs
index c3b7604,f1c7bfe..c4b4883
--- a/Makefile.objs
+++ b/Makefile.objs
@@@ -17,10 -17,9 +17,10 @@@ block-obj-y = cutils.o cache-utils.o qe
  block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o
  block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
  block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 +block-obj-$(CONFIG_POSIX) += compatfd.o
  
  block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
- block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o
+ block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
  block-nested-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
  block-nested-y += qed-check.o
  block-nested-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o
diff --cc blockdev.c
index 82abfe5,1c56da0..c9e249e
--- a/blockdev.c
+++ b/blockdev.c
@@@ -17,10 -17,39 +17,41 @@@
  #include "hw/qdev.h"
  #include "block_int.h"
  
 +DriveInfo *extboot_drive = NULL;
 +
  static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
  
+ static const char *const if_name[IF_COUNT] = {
+     [IF_NONE] = "none",
+     [IF_IDE] = "ide",
+     [IF_SCSI] = "scsi",
+     [IF_FLOPPY] = "floppy",
+     [IF_PFLASH] = "pflash",
+     [IF_MTD] = "mtd",
+     [IF_SD] = "sd",
+     [IF_VIRTIO] = "virtio",
+     [IF_XEN] = "xen",
+ };
+ 
+ static const int if_max_devs[IF_COUNT] = {
+     /*
+      * Do not change these numbers!  They govern how drive option
+      * index maps to unit and bus.  That mapping is ABI.
+      *
+      * All controllers used to imlement if=T drives need to support
+      * if_max_devs[T] units, for any T with if_max_devs[T] != 0.
+      * Otherwise, some index values map to "impossible" bus, unit
+      * values.
+      *
+      * For instance, if you change [IF_SCSI] to 255, -drive
+      * if=scsi,index=12 no longer means bus=1,unit=5, but
+      * bus=0,unit=12.  With an lsi53c895a controller (7 units max),
+      * the drive can't be set up.  Regression.
+      */
+     [IF_IDE] = 2,
+     [IF_SCSI] = 7,
+ };
+ 
  /*
   * We automatically delete the drive when a device using it gets
   * unplugged.  Questionable feature, but we can't just drop it.
diff --cc blockdev.h
index 7faa472,84e462a..c0ee199
--- a/blockdev.h
+++ b/blockdev.h
@@@ -53,7 -61,6 +61,8 @@@ int do_change_block(Monitor *mon, cons
                      const char *filename, const char *fmt);
  int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
  int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data);
+ int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data);
  
 +extern DriveInfo *extboot_drive;
 +
  #endif
diff --cc hw/pc_piix.c
index 318745b,7b74473..ad45148
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@@ -34,10 -34,9 +34,11 @@@
  #include "kvm.h"
  #include "sysemu.h"
  #include "sysbus.h"
+ #include "arch_init.h"
  #include "blockdev.h"
  
 +qemu_irq *ioapic_irq_hack;
 +
  #define MAX_IDE_BUS 2
  
  static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
diff --cc target-i386/kvm.c
index cb82899,05010bb..5e0865a
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@@ -441,24 -437,10 +447,22 @@@ int kvm_arch_init_vcpu(CPUState *env
      return kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data);
  }
  
 +static void kvm_clear_vapic(CPUState *env)
 +{
 +#ifdef KVM_SET_VAPIC_ADDR
 +    struct kvm_vapic_addr va = {
 +        .vapic_addr = 0,
 +    };
 +
 +    kvm_vcpu_ioctl(env, KVM_SET_VAPIC_ADDR, &va);
 +#endif
 +}
 +
  void kvm_arch_reset_vcpu(CPUState *env)
  {
 +    kvm_clear_vapic(env);
      env->exception_injected = -1;
      env->interrupt_injected = -1;
-     env->nmi_injected = 0;
-     env->nmi_pending = 0;
      env->xcr0 = 1;
      if (kvm_irqchip_in_kernel()) {
          env->mp_state = cpu_is_bsp(env) ? KVM_MP_STATE_RUNNABLE :
@@@ -569,11 -546,9 +570,11 @@@ int kvm_arch_init(KVMState *s
          return ret;
      }
  
-     return kvm_init_identity_map_page(s);
+     return 0;
  }
  
 +#endif
 +
  static void set_v8086_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
  {
      lhs->selector = rhs->selector;
commit 16b0249ee000c083c359a419bad4b460a465b3b8
Merge: 774dce1... 94a8d39...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Feb 2 19:29:32 2011 -0200

    Merge commit '94a8d39afd8ccfdbf578af04c3385fdb5f545af1' into upstream-merge
    
    * commit '94a8d39afd8ccfdbf578af04c3385fdb5f545af1':
      kvm: Consolidate must-have capability checks
    
    Conflicts:
    	kvm-all.c
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --cc kvm-all.c
index f7df264,3a1f63b..114c6b9
--- a/kvm-all.c
+++ b/kvm-all.c
@@@ -84,8 -80,12 +82,15 @@@ struct KVMStat
  
  static KVMState *kvm_state;
  
++
+ static const KVMCapabilityInfo kvm_required_capabilites[] = {
+     KVM_CAP_INFO(USER_MEMORY),
+     KVM_CAP_INFO(DESTROY_MEMORY_REGION_WORKS),
+     KVM_CAP_LAST_INFO
+ };
+ 
 +#endif
 +
  static KVMSlot *kvm_alloc_slot(KVMState *s)
  {
      int i;
@@@ -489,6 -479,18 +488,20 @@@ static int kvm_check_many_ioeventfds(vo
  #endif
  }
  
++#ifdef OBSOLETE_KVM_IMPL
+ static const KVMCapabilityInfo *
+ kvm_check_extension_list(KVMState *s, const KVMCapabilityInfo *list)
+ {
+     while (list->name) {
+         if (!kvm_check_extension(s, list->value)) {
+             return list;
+         }
+         list++;
+     }
+     return NULL;
+ }
++#endif
+ 
  static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
                               ram_addr_t phys_offset)
  {
@@@ -875,11 -853,8 +872,10 @@@ void kvm_flush_coalesced_mmio_buffer(vo
              ring->first = (ring->first + 1) % KVM_COALESCED_MMIO_MAX;
          }
      }
- #endif
  }
  
 +#ifdef OBSOLETE_KVM_IMPL
 +
  static void do_kvm_cpu_synchronize_state(void *_env)
  {
      CPUState *env = _env;
diff --cc kvm.h
index 3f06cce,ca57517..f06676c
--- a/kvm.h
+++ b/kvm.h
@@@ -33,9 -30,16 +33,17 @@@ extern int kvm_allowed
  #define kvm_enabled() (0)
  #endif
  
 +#ifdef OBSOLETE_KVM_IMPL
  struct kvm_run;
  
+ typedef struct KVMCapabilityInfo {
+     const char *name;
+     int value;
+ } KVMCapabilityInfo;
+ 
+ #define KVM_CAP_INFO(CAP) { "KVM_CAP_" stringify(CAP), KVM_CAP_##CAP }
+ #define KVM_CAP_LAST_INFO { NULL, 0 }
+ 
  /* external API */
  
  int kvm_init(void);
@@@ -92,6 -94,8 +100,10 @@@ int kvm_vcpu_ioctl(CPUState *env, int t
  
  /* Arch specific hooks */
  
++#ifdef OBSOLETE_KVM_IMPL
+ extern const KVMCapabilityInfo kvm_arch_required_capabilities[];
++#endif
+ 
  int kvm_arch_post_run(CPUState *env, struct kvm_run *run);
  
  int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run);
diff --cc target-i386/kvm.c
index 8784de1,1db8227..cb82899
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@@ -54,6 -54,13 +54,15 @@@
  #define BUS_MCEERR_AO 5
  #endif
  
++#ifdef OBSOLETE_KVM_IMPL
+ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+     KVM_CAP_INFO(SET_TSS_ADDR),
+     KVM_CAP_INFO(EXT_CPUID),
+     KVM_CAP_INFO(MP_STATE),
+     KVM_CAP_LAST_INFO
+ };
++#endif
+ 
  static bool has_msr_star;
  static bool has_msr_hsave_pa;
  static int lm_capable_kernel;
commit 774dce1308b01518571795825e46d6f4104ee251
Merge: b131811... cad1e28...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Feb 2 19:11:35 2011 -0200

    Merge commit 'cad1e2827b616487e3574300f2eaeea13a355197' into upstream-merge
    
    * commit 'cad1e2827b616487e3574300f2eaeea13a355197':
      kvm: Drop smp_cpus argument from init functions
      kvm: x86: Fix !CONFIG_KVM_PARA build
      kvm: x86: Reset paravirtual MSRs
    
    Conflicts:
    	kvm-all.c
    	kvm.h
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --cc kvm-all.c
index a334ae8,8053f92..f7df264
--- a/kvm-all.c
+++ b/kvm-all.c
@@@ -644,15 -636,7 +644,14 @@@ static CPUPhysMemoryClient kvm_cpu_phys
      .migration_log = kvm_client_migration_log,
  };
  
- 
 +void kvm_cpu_register_phys_memory_client(void)
 +{
 +    cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client);
 +}
 +
 +#ifdef OBSOLETE_KVM_IMPL
 +
- int kvm_init(int smp_cpus)
+ int kvm_init(void)
  {
      static const char upgrade_note[] =
          "Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n"
diff --cc kvm.h
index 45124ef,a971752..3f06cce
--- a/kvm.h
+++ b/kvm.h
@@@ -38,8 -34,7 +38,8 @@@ struct kvm_run
  
  /* external API */
  
- int kvm_init(int smp_cpus);
+ int kvm_init(void);
 +#endif /* OBSOLETE_KVM_IMPL */
  
  int kvm_has_sync_mmu(void);
  int kvm_has_vcpu_events(void);
diff --cc qemu-kvm.c
index 76731fe,0000000..4974179
mode 100644,000000..100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@@ -1,1783 -1,0 +1,1783 @@@
 +/*
 + * qemu/kvm integration
 + *
 + * Copyright (C) 2006-2008 Qumranet Technologies
 + *
 + * Licensed under the terms of the GNU GPL version 2 or higher.
 + */
 +#include "config.h"
 +#include "config-host.h"
 +
 +#include <assert.h>
 +#include <string.h>
 +#include "hw/hw.h"
 +#include "sysemu.h"
 +#include "qemu-common.h"
 +#include "console.h"
 +#include "block.h"
 +#include "compatfd.h"
 +#include "gdbstub.h"
 +#include "monitor.h"
 +
 +#include "qemu-kvm.h"
 +#include "libkvm.h"
 +
 +#include <pthread.h>
 +#include <sys/utsname.h>
 +#include <sys/syscall.h>
 +#include <sys/mman.h>
 +#include <sys/ioctl.h>
 +#include "compatfd.h"
 +#include <sys/prctl.h>
 +
 +#define false 0
 +#define true 1
 +
 +#ifndef PR_MCE_KILL
 +#define PR_MCE_KILL 33
 +#endif
 +
 +#ifndef BUS_MCEERR_AR
 +#define BUS_MCEERR_AR 4
 +#endif
 +#ifndef BUS_MCEERR_AO
 +#define BUS_MCEERR_AO 5
 +#endif
 +
 +#define EXPECTED_KVM_API_VERSION 12
 +
 +#if EXPECTED_KVM_API_VERSION != KVM_API_VERSION
 +#error libkvm: userspace and kernel version mismatch
 +#endif
 +
 +int kvm_irqchip = 1;
 +int kvm_pit = 1;
 +int kvm_pit_reinject = 1;
 +int kvm_nested = 0;
 +
 +
 +KVMState *kvm_state;
 +kvm_context_t kvm_context;
 +
 +pthread_mutex_t qemu_mutex = PTHREAD_MUTEX_INITIALIZER;
 +pthread_cond_t qemu_vcpu_cond = PTHREAD_COND_INITIALIZER;
 +pthread_cond_t qemu_system_cond = PTHREAD_COND_INITIALIZER;
 +pthread_cond_t qemu_pause_cond = PTHREAD_COND_INITIALIZER;
 +pthread_cond_t qemu_work_cond = PTHREAD_COND_INITIALIZER;
 +__thread CPUState *current_env;
 +
 +static int qemu_system_ready;
 +
 +#define SIG_IPI (SIGRTMIN+4)
 +
 +pthread_t io_thread;
 +static int io_thread_sigfd = -1;
 +
 +static CPUState *kvm_debug_cpu_requested;
 +
 +#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
 +/* The list of ioperm_data */
 +static QLIST_HEAD(, ioperm_data) ioperm_head;
 +#endif
 +
 +#define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1))
 +
 +int kvm_abi = EXPECTED_KVM_API_VERSION;
 +int kvm_page_size;
 +
 +#ifdef KVM_CAP_SET_GUEST_DEBUG
 +static int kvm_debug(CPUState *env,
 +                     struct kvm_debug_exit_arch *arch_info)
 +{
 +    int handle = kvm_arch_debug(arch_info);
 +
 +    if (handle) {
 +        kvm_debug_cpu_requested = env;
 +        env->stopped = 1;
 +    }
 +    return handle;
 +}
 +#endif
 +
 +static int handle_unhandled(uint64_t reason)
 +{
 +    fprintf(stderr, "kvm: unhandled exit %" PRIx64 "\n", reason);
 +    return -EINVAL;
 +}
 +
 +#define VMX_INVALID_GUEST_STATE 0x80000021
 +
 +static int handle_failed_vmentry(uint64_t reason)
 +{
 +    fprintf(stderr, "kvm: vm entry failed with error 0x%" PRIx64 "\n\n", reason);
 +
 +    /* Perhaps we will need to check if this machine is intel since exit reason 0x21
 +       has a different interpretation on SVM */
 +    if (reason == VMX_INVALID_GUEST_STATE) {
 +        fprintf(stderr, "If you're runnning a guest on an Intel machine without\n");
 +        fprintf(stderr, "unrestricted mode support, the failure can be most likely\n");
 +        fprintf(stderr, "due to the guest entering an invalid state for Intel VT.\n");
 +        fprintf(stderr, "For example, the guest maybe running in big real mode\n");
 +        fprintf(stderr, "which is not supported on less recent Intel processors.\n\n");
 +    }
 +
 +    return -EINVAL;
 +}
 +
 +static inline void set_gsi(kvm_context_t kvm, unsigned int gsi)
 +{
 +    uint32_t *bitmap = kvm->used_gsi_bitmap;
 +
 +    if (gsi < kvm->max_gsi)
 +        bitmap[gsi / 32] |= 1U << (gsi % 32);
 +    else
 +        DPRINTF("Invalid GSI %u\n", gsi);
 +}
 +
 +static inline void clear_gsi(kvm_context_t kvm, unsigned int gsi)
 +{
 +    uint32_t *bitmap = kvm->used_gsi_bitmap;
 +
 +    if (gsi < kvm->max_gsi)
 +        bitmap[gsi / 32] &= ~(1U << (gsi % 32));
 +    else
 +        DPRINTF("Invalid GSI %u\n", gsi);
 +}
 +
 +static int kvm_create_context(void);
 +
- int kvm_init(int smp_cpus)
++int kvm_init(void)
 +{
 +    int fd;
 +    int r, gsi_count;
 +
 +
 +    fd = open("/dev/kvm", O_RDWR);
 +    if (fd == -1) {
 +        perror("open /dev/kvm");
 +        return -1;
 +    }
 +    r = ioctl(fd, KVM_GET_API_VERSION, 0);
 +    if (r == -1) {
 +        fprintf(stderr,
 +                "kvm kernel version too old: "
 +                "KVM_GET_API_VERSION ioctl not supported\n");
 +        goto out_close;
 +    }
 +    if (r < EXPECTED_KVM_API_VERSION) {
 +        fprintf(stderr, "kvm kernel version too old: "
 +                "We expect API version %d or newer, but got "
 +                "version %d\n", EXPECTED_KVM_API_VERSION, r);
 +        goto out_close;
 +    }
 +    if (r > EXPECTED_KVM_API_VERSION) {
 +        fprintf(stderr, "kvm userspace version too old\n");
 +        goto out_close;
 +    }
 +    kvm_abi = r;
 +    kvm_page_size = getpagesize();
 +    kvm_state = qemu_mallocz(sizeof(*kvm_state));
 +    kvm_context = &kvm_state->kvm_context;
 +
 +    kvm_state->fd = fd;
 +    kvm_state->vmfd = -1;
 +    kvm_context->opaque = cpu_single_env;
 +    kvm_context->dirty_pages_log_all = 0;
 +    kvm_context->no_irqchip_creation = 0;
 +    kvm_context->no_pit_creation = 0;
 +
 +#ifdef KVM_CAP_SET_GUEST_DEBUG
 +    QTAILQ_INIT(&kvm_state->kvm_sw_breakpoints);
 +#endif
 +
 +    gsi_count = kvm_get_gsi_count(kvm_context);
 +    if (gsi_count > 0) {
 +        int gsi_bits, i;
 +
 +        /* Round up so we can search ints using ffs */
 +        gsi_bits = ALIGN(gsi_count, 32);
 +        kvm_context->used_gsi_bitmap = qemu_mallocz(gsi_bits / 8);
 +        kvm_context->max_gsi = gsi_bits;
 +
 +        /* Mark any over-allocated bits as already in use */
 +        for (i = gsi_count; i < gsi_bits; i++) {
 +            set_gsi(kvm_context, i);
 +        }
 +    }
 +
 +    kvm_cpu_register_phys_memory_client();
 +
 +    pthread_mutex_lock(&qemu_mutex);
 +    return kvm_create_context();
 +
 +  out_close:
 +    close(fd);
 +    return -1;
 +}
 +
 +static void kvm_finalize(KVMState *s)
 +{
 +    /* FIXME
 +       if (kvm->vcpu_fd[0] != -1)
 +           close(kvm->vcpu_fd[0]);
 +       if (kvm->vm_fd != -1)
 +           close(kvm->vm_fd);
 +     */
 +    close(s->fd);
 +    free(s);
 +}
 +
 +void kvm_disable_irqchip_creation(kvm_context_t kvm)
 +{
 +    kvm->no_irqchip_creation = 1;
 +}
 +
 +void kvm_disable_pit_creation(kvm_context_t kvm)
 +{
 +    kvm->no_pit_creation = 1;
 +}
 +
 +static void kvm_reset_vcpu(void *opaque)
 +{
 +    CPUState *env = opaque;
 +
 +    kvm_arch_cpu_reset(env);
 +}
 +
 +static void kvm_create_vcpu(CPUState *env, int id)
 +{
 +    long mmap_size;
 +    int r;
 +    KVMState *s = kvm_state;
 +
 +    r = kvm_vm_ioctl(kvm_state, KVM_CREATE_VCPU, id);
 +    if (r < 0) {
 +        fprintf(stderr, "kvm_create_vcpu: %m\n");
 +        fprintf(stderr, "Failed to create vCPU. Check the -smp parameter.\n");
 +        goto err;
 +    }
 +
 +    env->kvm_fd = r;
 +    env->kvm_state = kvm_state;
 +
 +    mmap_size = kvm_ioctl(kvm_state, KVM_GET_VCPU_MMAP_SIZE, 0);
 +    if (mmap_size < 0) {
 +        fprintf(stderr, "get vcpu mmap size: %m\n");
 +        goto err_fd;
 +    }
 +    env->kvm_run =
 +        mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, env->kvm_fd,
 +             0);
 +    if (env->kvm_run == MAP_FAILED) {
 +        fprintf(stderr, "mmap vcpu area: %m\n");
 +        goto err_fd;
 +    }
 +
 +#ifdef KVM_CAP_COALESCED_MMIO
 +    if (s->coalesced_mmio && !s->coalesced_mmio_ring)
 +        s->coalesced_mmio_ring = (void *) env->kvm_run +
 +               s->coalesced_mmio * PAGE_SIZE;
 +#endif
 +
 +    r = kvm_arch_init_vcpu(env);
 +    if (r == 0) {
 +        qemu_register_reset(kvm_reset_vcpu, env);
 +    }
 +
 +    return;
 +  err_fd:
 +    close(env->kvm_fd);
 +  err:
 +    /* We're no good with semi-broken states. */
 +    abort();
 +}
 +
 +static int kvm_set_boot_vcpu_id(kvm_context_t kvm, uint32_t id)
 +{
 +#ifdef KVM_CAP_SET_BOOT_CPU_ID
 +    int r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_SET_BOOT_CPU_ID);
 +    if (r > 0) {
 +        return kvm_vm_ioctl(kvm_state, KVM_SET_BOOT_CPU_ID, id);
 +    }
 +    return -ENOSYS;
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_create_vm(kvm_context_t kvm)
 +{
 +    int fd;
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    kvm->irq_routes = qemu_mallocz(sizeof(*kvm->irq_routes));
 +    kvm->nr_allocated_irq_routes = 0;
 +#endif
 +
 +    fd = kvm_ioctl(kvm_state, KVM_CREATE_VM, 0);
 +    if (fd < 0) {
 +        fprintf(stderr, "kvm_create_vm: %m\n");
 +        return -1;
 +    }
 +    kvm_state->vmfd = fd;
 +    return 0;
 +}
 +
 +static int kvm_create_default_phys_mem(kvm_context_t kvm,
 +                                       unsigned long phys_mem_bytes,
 +                                       void **vm_mem)
 +{
 +#ifdef KVM_CAP_USER_MEMORY
 +    int r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_USER_MEMORY);
 +    if (r > 0)
 +        return 0;
 +    fprintf(stderr,
 +            "Hypervisor too old: KVM_CAP_USER_MEMORY extension not supported\n");
 +#else
 +#error Hypervisor too old: KVM_CAP_USER_MEMORY extension not supported
 +#endif
 +    return -1;
 +}
 +
 +void kvm_create_irqchip(kvm_context_t kvm)
 +{
 +    int r;
 +
 +    kvm->irqchip_in_kernel = 0;
 +#ifdef KVM_CAP_IRQCHIP
 +    if (!kvm->no_irqchip_creation) {
 +        r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_IRQCHIP);
 +        if (r > 0) {            /* kernel irqchip supported */
 +            r = kvm_vm_ioctl(kvm_state, KVM_CREATE_IRQCHIP);
 +            if (r >= 0) {
 +                kvm->irqchip_inject_ioctl = KVM_IRQ_LINE;
 +#if defined(KVM_CAP_IRQ_INJECT_STATUS) && defined(KVM_IRQ_LINE_STATUS)
 +                r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION,
 +                              KVM_CAP_IRQ_INJECT_STATUS);
 +                if (r > 0) {
 +                    kvm->irqchip_inject_ioctl = KVM_IRQ_LINE_STATUS;
 +                }
 +#endif
 +                kvm->irqchip_in_kernel = 1;
 +            } else
 +                fprintf(stderr, "Create kernel PIC irqchip failed\n");
 +        }
 +    }
 +#endif
 +    kvm_state->irqchip_in_kernel = kvm->irqchip_in_kernel;
 +}
 +
 +int kvm_create(kvm_context_t kvm, unsigned long phys_mem_bytes, void **vm_mem)
 +{
 +    int r, i;
 +
 +    r = kvm_create_vm(kvm);
 +    if (r < 0) {
 +        return r;
 +    }
 +    r = kvm_arch_create(kvm, phys_mem_bytes, vm_mem);
 +    if (r < 0) {
 +        return r;
 +    }
 +    for (i = 0; i < ARRAY_SIZE(kvm_state->slots); i++) {
 +        kvm_state->slots[i].slot = i;
 +    }
 +
 +    r = kvm_create_default_phys_mem(kvm, phys_mem_bytes, vm_mem);
 +    if (r < 0) {
 +        return r;
 +    }
 +
 +    kvm_create_irqchip(kvm);
 +
 +    return 0;
 +}
 +
 +#ifdef KVM_CAP_IRQCHIP
 +
 +int kvm_set_irq_level(kvm_context_t kvm, int irq, int level, int *status)
 +{
 +    struct kvm_irq_level event;
 +    int r;
 +
 +    if (!kvm->irqchip_in_kernel) {
 +        return 0;
 +    }
 +    event.level = level;
 +    event.irq = irq;
 +    r = kvm_vm_ioctl(kvm_state, kvm->irqchip_inject_ioctl, &event);
 +    if (r < 0) {
 +        perror("kvm_set_irq_level");
 +    }
 +
 +    if (status) {
 +#ifdef KVM_CAP_IRQ_INJECT_STATUS
 +        *status =
 +            (kvm->irqchip_inject_ioctl == KVM_IRQ_LINE) ? 1 : event.status;
 +#else
 +        *status = 1;
 +#endif
 +    }
 +
 +    return 1;
 +}
 +
 +int kvm_get_irqchip(kvm_context_t kvm, struct kvm_irqchip *chip)
 +{
 +    int r;
 +
 +    if (!kvm->irqchip_in_kernel) {
 +        return 0;
 +    }
 +    r = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, chip);
 +    if (r < 0) {
 +        perror("kvm_get_irqchip\n");
 +    }
 +    return r;
 +}
 +
 +int kvm_set_irqchip(kvm_context_t kvm, struct kvm_irqchip *chip)
 +{
 +    int r;
 +
 +    if (!kvm->irqchip_in_kernel) {
 +        return 0;
 +    }
 +    r = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip);
 +    if (r < 0) {
 +        perror("kvm_set_irqchip\n");
 +    }
 +    return r;
 +}
 +
 +#endif
 +
 +static int handle_debug(CPUState *env)
 +{
 +#ifdef KVM_CAP_SET_GUEST_DEBUG
 +    struct kvm_run *run = env->kvm_run;
 +
 +    return kvm_debug(env, &run->debug.arch);
 +#else
 +    return 0;
 +#endif
 +}
 +
 +int kvm_get_regs(CPUState *env, struct kvm_regs *regs)
 +{
 +    return kvm_vcpu_ioctl(env, KVM_GET_REGS, regs);
 +}
 +
 +int kvm_set_regs(CPUState *env, struct kvm_regs *regs)
 +{
 +    return kvm_vcpu_ioctl(env, KVM_SET_REGS, regs);
 +}
 +
 +#ifdef KVM_CAP_MP_STATE
 +int kvm_get_mpstate(CPUState *env, struct kvm_mp_state *mp_state)
 +{
 +    int r;
 +
 +    r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_MP_STATE);
 +    if (r > 0) {
 +        return kvm_vcpu_ioctl(env, KVM_GET_MP_STATE, mp_state);
 +    }
 +    return -ENOSYS;
 +}
 +
 +int kvm_set_mpstate(CPUState *env, struct kvm_mp_state *mp_state)
 +{
 +    int r;
 +
 +    r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_MP_STATE);
 +    if (r > 0) {
 +        return kvm_vcpu_ioctl(env, KVM_SET_MP_STATE, mp_state);
 +    }
 +    return -ENOSYS;
 +}
 +#endif
 +
 +static int handle_mmio(CPUState *env)
 +{
 +    unsigned long addr = env->kvm_run->mmio.phys_addr;
 +    struct kvm_run *kvm_run = env->kvm_run;
 +    void *data = kvm_run->mmio.data;
 +
 +    /* hack: Red Hat 7.1 generates these weird accesses. */
 +    if ((addr > 0xa0000 - 4 && addr <= 0xa0000) && kvm_run->mmio.len == 3) {
 +        return 0;
 +    }
 +
 +    cpu_physical_memory_rw(addr, data, kvm_run->mmio.len, kvm_run->mmio.is_write);
 +    return 0;
 +}
 +
 +int handle_io_window(kvm_context_t kvm)
 +{
 +    return 1;
 +}
 +
 +int handle_shutdown(kvm_context_t kvm, CPUState *env)
 +{
 +    /* stop the current vcpu from going back to guest mode */
 +    env->stopped = 1;
 +
 +    qemu_system_reset_request();
 +    return 1;
 +}
 +
 +static inline void push_nmi(kvm_context_t kvm)
 +{
 +#ifdef KVM_CAP_USER_NMI
 +    kvm_arch_push_nmi(kvm->opaque);
 +#endif                          /* KVM_CAP_USER_NMI */
 +}
 +
 +void post_kvm_run(kvm_context_t kvm, CPUState *env)
 +{
 +    pthread_mutex_lock(&qemu_mutex);
 +    kvm_arch_post_run(env, env->kvm_run);
 +    cpu_single_env = env;
 +}
 +
 +int pre_kvm_run(kvm_context_t kvm, CPUState *env)
 +{
 +    kvm_arch_pre_run(env, env->kvm_run);
 +
 +    pthread_mutex_unlock(&qemu_mutex);
 +    return 0;
 +}
 +
 +int kvm_is_ready_for_interrupt_injection(CPUState *env)
 +{
 +    return env->kvm_run->ready_for_interrupt_injection;
 +}
 +
 +int kvm_run(CPUState *env)
 +{
 +    int r;
 +    kvm_context_t kvm = &env->kvm_state->kvm_context;
 +    struct kvm_run *run = env->kvm_run;
 +    int fd = env->kvm_fd;
 +
 +  again:
 +    if (env->kvm_vcpu_dirty) {
 +        kvm_arch_load_regs(env, KVM_PUT_RUNTIME_STATE);
 +        env->kvm_vcpu_dirty = 0;
 +    }
 +    push_nmi(kvm);
 +#if !defined(__s390__)
 +    if (!kvm->irqchip_in_kernel) {
 +        run->request_interrupt_window = kvm_arch_try_push_interrupts(env);
 +    }
 +#endif
 +
 +    r = pre_kvm_run(kvm, env);
 +    if (r) {
 +        return r;
 +    }
 +    if (env->exit_request) {
 +        env->exit_request = 0;
 +        pthread_kill(env->kvm_cpu_state.thread, SIG_IPI);
 +    }
 +    r = ioctl(fd, KVM_RUN, 0);
 +
 +    if (r == -1 && errno != EINTR && errno != EAGAIN) {
 +        r = -errno;
 +        post_kvm_run(kvm, env);
 +        fprintf(stderr, "kvm_run: %s\n", strerror(-r));
 +        return r;
 +    }
 +
 +    post_kvm_run(kvm, env);
 +
 +    kvm_flush_coalesced_mmio_buffer();
 +
 +#if !defined(__s390__)
 +    if (r == -1) {
 +        r = handle_io_window(kvm);
 +        goto more;
 +    }
 +#endif
 +    if (1) {
 +        switch (run->exit_reason) {
 +        case KVM_EXIT_UNKNOWN:
 +            r = handle_unhandled(run->hw.hardware_exit_reason);
 +            break;
 +        case KVM_EXIT_FAIL_ENTRY:
 +            r = handle_failed_vmentry(run->fail_entry.hardware_entry_failure_reason);
 +            break;
 +        case KVM_EXIT_EXCEPTION:
 +            fprintf(stderr, "exception %d (%x)\n", run->ex.exception,
 +                    run->ex.error_code);
 +            kvm_show_regs(env);
 +            kvm_show_code(env);
 +            abort();
 +            break;
 +        case KVM_EXIT_IO:
 +            r = kvm_handle_io(run->io.port,
 +                                (uint8_t *)run + run->io.data_offset,
 +                                run->io.direction,
 +                                run->io.size,
 +                                run->io.count);
 +            r = 0;
 +            break;
 +        case KVM_EXIT_DEBUG:
 +            r = handle_debug(env);
 +            break;
 +        case KVM_EXIT_MMIO:
 +            r = handle_mmio(env);
 +            break;
 +        case KVM_EXIT_HLT:
 +            r = kvm_arch_halt(env);
 +            break;
 +        case KVM_EXIT_IRQ_WINDOW_OPEN:
 +            break;
 +        case KVM_EXIT_SHUTDOWN:
 +            r = handle_shutdown(kvm, env);
 +            break;
 +#if defined(__s390__)
 +        case KVM_EXIT_S390_SIEIC:
 +            r = kvm_s390_handle_intercept(kvm, env, run);
 +            break;
 +        case KVM_EXIT_S390_RESET:
 +            r = kvm_s390_handle_reset(kvm, env, run);
 +            break;
 +#endif
 +	case KVM_EXIT_INTERNAL_ERROR:
 +            kvm_handle_internal_error(env, run);
 +            r = 1;
 +	    break;
 +        default:
 +            if (kvm_arch_run(env)) {
 +                fprintf(stderr, "unhandled vm exit: 0x%x\n", run->exit_reason);
 +                kvm_show_regs(env);
 +                abort();
 +            }
 +            break;
 +        }
 +    }
 +more:
 +    if (!r) {
 +        goto again;
 +    }
 +    return r;
 +}
 +
 +int kvm_inject_irq(CPUState *env, unsigned irq)
 +{
 +    struct kvm_interrupt intr;
 +
 +    intr.irq = irq;
 +    return kvm_vcpu_ioctl(env, KVM_INTERRUPT, &intr);
 +}
 +
 +int kvm_inject_nmi(CPUState *env)
 +{
 +#ifdef KVM_CAP_USER_NMI
 +    return kvm_vcpu_ioctl(env, KVM_NMI);
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_init_coalesced_mmio(kvm_context_t kvm)
 +{
 +    int r = 0;
 +    kvm_state->coalesced_mmio = 0;
 +#ifdef KVM_CAP_COALESCED_MMIO
 +    r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO);
 +    if (r > 0) {
 +        kvm_state->coalesced_mmio = r;
 +        return 0;
 +    }
 +#endif
 +    return r;
 +}
 +
 +#ifdef KVM_CAP_DEVICE_ASSIGNMENT
 +int kvm_assign_pci_device(kvm_context_t kvm,
 +                          struct kvm_assigned_pci_dev *assigned_dev)
 +{
 +    return kvm_vm_ioctl(kvm_state, KVM_ASSIGN_PCI_DEVICE, assigned_dev);
 +}
 +
 +static int kvm_old_assign_irq(kvm_context_t kvm,
 +                              struct kvm_assigned_irq *assigned_irq)
 +{
 +    return kvm_vm_ioctl(kvm_state, KVM_ASSIGN_IRQ, assigned_irq);
 +}
 +
 +#ifdef KVM_CAP_ASSIGN_DEV_IRQ
 +int kvm_assign_irq(kvm_context_t kvm, struct kvm_assigned_irq *assigned_irq)
 +{
 +    int ret;
 +
 +    ret = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_ASSIGN_DEV_IRQ);
 +    if (ret > 0) {
 +        return kvm_vm_ioctl(kvm_state, KVM_ASSIGN_DEV_IRQ, assigned_irq);
 +    }
 +
 +    return kvm_old_assign_irq(kvm, assigned_irq);
 +}
 +
 +int kvm_deassign_irq(kvm_context_t kvm, struct kvm_assigned_irq *assigned_irq)
 +{
 +    return kvm_vm_ioctl(kvm_state, KVM_DEASSIGN_DEV_IRQ, assigned_irq);
 +}
 +#else
 +int kvm_assign_irq(kvm_context_t kvm, struct kvm_assigned_irq *assigned_irq)
 +{
 +    return kvm_old_assign_irq(kvm, assigned_irq);
 +}
 +#endif
 +#endif
 +
 +#ifdef KVM_CAP_DEVICE_DEASSIGNMENT
 +int kvm_deassign_pci_device(kvm_context_t kvm,
 +                            struct kvm_assigned_pci_dev *assigned_dev)
 +{
 +    return kvm_vm_ioctl(kvm_state, KVM_DEASSIGN_PCI_DEVICE, assigned_dev);
 +}
 +#endif
 +
 +int kvm_reinject_control(kvm_context_t kvm, int pit_reinject)
 +{
 +#ifdef KVM_CAP_REINJECT_CONTROL
 +    int r;
 +    struct kvm_reinject_control control;
 +
 +    control.pit_reinject = pit_reinject;
 +
 +    r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_REINJECT_CONTROL);
 +    if (r > 0) {
 +        return kvm_vm_ioctl(kvm_state, KVM_REINJECT_CONTROL, &control);
 +    }
 +#endif
 +    return -ENOSYS;
 +}
 +
 +int kvm_has_gsi_routing(void)
 +{
 +    int r = 0;
 +
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    r = kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING);
 +#endif
 +    return r;
 +}
 +
 +int kvm_get_gsi_count(kvm_context_t kvm)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    return kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING);
 +#else
 +    return -EINVAL;
 +#endif
 +}
 +
 +int kvm_clear_gsi_routes(void)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    kvm_context_t kvm = kvm_context;
 +
 +    kvm->irq_routes->nr = 0;
 +    return 0;
 +#else
 +    return -EINVAL;
 +#endif
 +}
 +
 +int kvm_add_routing_entry(struct kvm_irq_routing_entry *entry)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    kvm_context_t kvm = kvm_context;
 +    struct kvm_irq_routing *z;
 +    struct kvm_irq_routing_entry *new;
 +    int n, size;
 +
 +    if (kvm->irq_routes->nr == kvm->nr_allocated_irq_routes) {
 +        n = kvm->nr_allocated_irq_routes * 2;
 +        if (n < 64) {
 +            n = 64;
 +        }
 +        size = sizeof(struct kvm_irq_routing);
 +        size += n * sizeof(*new);
 +        z = realloc(kvm->irq_routes, size);
 +        if (!z) {
 +            return -ENOMEM;
 +        }
 +        kvm->nr_allocated_irq_routes = n;
 +        kvm->irq_routes = z;
 +    }
 +    n = kvm->irq_routes->nr++;
 +    new = &kvm->irq_routes->entries[n];
 +    memset(new, 0, sizeof(*new));
 +    new->gsi = entry->gsi;
 +    new->type = entry->type;
 +    new->flags = entry->flags;
 +    new->u = entry->u;
 +
 +    set_gsi(kvm, entry->gsi);
 +
 +    return 0;
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_add_irq_route(int gsi, int irqchip, int pin)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    struct kvm_irq_routing_entry e;
 +
 +    e.gsi = gsi;
 +    e.type = KVM_IRQ_ROUTING_IRQCHIP;
 +    e.flags = 0;
 +    e.u.irqchip.irqchip = irqchip;
 +    e.u.irqchip.pin = pin;
 +    return kvm_add_routing_entry(&e);
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_del_routing_entry(struct kvm_irq_routing_entry *entry)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    kvm_context_t kvm = kvm_context;
 +    struct kvm_irq_routing_entry *e, *p;
 +    int i, gsi, found = 0;
 +
 +    gsi = entry->gsi;
 +
 +    for (i = 0; i < kvm->irq_routes->nr; ++i) {
 +        e = &kvm->irq_routes->entries[i];
 +        if (e->type == entry->type && e->gsi == gsi) {
 +            switch (e->type) {
 +            case KVM_IRQ_ROUTING_IRQCHIP:{
 +                    if (e->u.irqchip.irqchip ==
 +                        entry->u.irqchip.irqchip
 +                        && e->u.irqchip.pin == entry->u.irqchip.pin) {
 +                        p = &kvm->irq_routes->entries[--kvm->irq_routes->nr];
 +                        *e = *p;
 +                        found = 1;
 +                    }
 +                    break;
 +                }
 +            case KVM_IRQ_ROUTING_MSI:{
 +                    if (e->u.msi.address_lo ==
 +                        entry->u.msi.address_lo
 +                        && e->u.msi.address_hi ==
 +                        entry->u.msi.address_hi
 +                        && e->u.msi.data == entry->u.msi.data) {
 +                        p = &kvm->irq_routes->entries[--kvm->irq_routes->nr];
 +                        *e = *p;
 +                        found = 1;
 +                    }
 +                    break;
 +                }
 +            default:
 +                break;
 +            }
 +            if (found) {
 +                /* If there are no other users of this GSI
 +                 * mark it available in the bitmap */
 +                for (i = 0; i < kvm->irq_routes->nr; i++) {
 +                    e = &kvm->irq_routes->entries[i];
 +                    if (e->gsi == gsi)
 +                        break;
 +                }
 +                if (i == kvm->irq_routes->nr) {
 +                    clear_gsi(kvm, gsi);
 +                }
 +
 +                return 0;
 +            }
 +        }
 +    }
 +    return -ESRCH;
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_update_routing_entry(struct kvm_irq_routing_entry *entry,
 +                             struct kvm_irq_routing_entry *newentry)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    kvm_context_t kvm = kvm_context;
 +    struct kvm_irq_routing_entry *e;
 +    int i;
 +
 +    if (entry->gsi != newentry->gsi || entry->type != newentry->type) {
 +        return -EINVAL;
 +    }
 +
 +    for (i = 0; i < kvm->irq_routes->nr; ++i) {
 +        e = &kvm->irq_routes->entries[i];
 +        if (e->type != entry->type || e->gsi != entry->gsi) {
 +            continue;
 +        }
 +        switch (e->type) {
 +        case KVM_IRQ_ROUTING_IRQCHIP:
 +            if (e->u.irqchip.irqchip == entry->u.irqchip.irqchip &&
 +                e->u.irqchip.pin == entry->u.irqchip.pin) {
 +                memcpy(&e->u.irqchip, &newentry->u.irqchip,
 +                       sizeof e->u.irqchip);
 +                return 0;
 +            }
 +            break;
 +        case KVM_IRQ_ROUTING_MSI:
 +            if (e->u.msi.address_lo == entry->u.msi.address_lo &&
 +                e->u.msi.address_hi == entry->u.msi.address_hi &&
 +                e->u.msi.data == entry->u.msi.data) {
 +                memcpy(&e->u.msi, &newentry->u.msi, sizeof e->u.msi);
 +                return 0;
 +            }
 +            break;
 +        default:
 +            break;
 +        }
 +    }
 +    return -ESRCH;
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_del_irq_route(int gsi, int irqchip, int pin)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    struct kvm_irq_routing_entry e;
 +
 +    e.gsi = gsi;
 +    e.type = KVM_IRQ_ROUTING_IRQCHIP;
 +    e.flags = 0;
 +    e.u.irqchip.irqchip = irqchip;
 +    e.u.irqchip.pin = pin;
 +    return kvm_del_routing_entry(&e);
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_commit_irq_routes(void)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    kvm_context_t kvm = kvm_context;
 +
 +    kvm->irq_routes->flags = 0;
 +    return kvm_vm_ioctl(kvm_state, KVM_SET_GSI_ROUTING, kvm->irq_routes);
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_get_irq_route_gsi(void)
 +{
 +    kvm_context_t kvm = kvm_context;
 +    int i, bit;
 +    uint32_t *buf = kvm->used_gsi_bitmap;
 +
 +    /* Return the lowest unused GSI in the bitmap */
 +    for (i = 0; i < kvm->max_gsi / 32; i++) {
 +        bit = ffs(~buf[i]);
 +        if (!bit) {
 +            continue;
 +        }
 +
 +        return bit - 1 + i * 32;
 +    }
 +
 +    return -ENOSPC;
 +}
 +
 +static void kvm_msix_routing_entry(struct kvm_irq_routing_entry *e,
 +                                   uint32_t gsi, uint32_t addr_lo,
 +                                   uint32_t addr_hi, uint32_t data)
 +
 +{
 +    e->gsi = gsi;
 +    e->type = KVM_IRQ_ROUTING_MSI;
 +    e->flags = 0;
 +    e->u.msi.address_lo = addr_lo;
 +    e->u.msi.address_hi = addr_hi;
 +    e->u.msi.data = data;
 +}
 +
 +int kvm_add_msix(uint32_t gsi, uint32_t addr_lo,
 +                        uint32_t addr_hi, uint32_t data)
 +{
 +    struct kvm_irq_routing_entry e;
 +
 +    kvm_msix_routing_entry(&e, gsi, addr_lo, addr_hi, data);
 +    return kvm_add_routing_entry(&e);
 +}
 +
 +int kvm_del_msix(uint32_t gsi, uint32_t addr_lo,
 +                        uint32_t addr_hi, uint32_t data)
 +{
 +    struct kvm_irq_routing_entry e;
 +
 +    kvm_msix_routing_entry(&e, gsi, addr_lo, addr_hi, data);
 +    return kvm_del_routing_entry(&e);
 +}
 +
 +int kvm_update_msix(uint32_t old_gsi, uint32_t old_addr_lo,
 +                    uint32_t old_addr_hi, uint32_t old_data,
 +                    uint32_t new_gsi, uint32_t new_addr_lo,
 +                    uint32_t new_addr_hi, uint32_t new_data)
 +{
 +    struct kvm_irq_routing_entry e1, e2;
 +
 +    kvm_msix_routing_entry(&e1, old_gsi, old_addr_lo, old_addr_hi, old_data);
 +    kvm_msix_routing_entry(&e2, new_gsi, new_addr_lo, new_addr_hi, new_data);
 +    return kvm_update_routing_entry(&e1, &e2);
 +}
 +
 +
 +#ifdef KVM_CAP_DEVICE_MSIX
 +int kvm_assign_set_msix_nr(kvm_context_t kvm,
 +                           struct kvm_assigned_msix_nr *msix_nr)
 +{
 +    return kvm_vm_ioctl(kvm_state, KVM_ASSIGN_SET_MSIX_NR, msix_nr);
 +}
 +
 +int kvm_assign_set_msix_entry(kvm_context_t kvm,
 +                              struct kvm_assigned_msix_entry *entry)
 +{
 +    return kvm_vm_ioctl(kvm_state, KVM_ASSIGN_SET_MSIX_ENTRY, entry);
 +}
 +#endif
 +
 +#if defined(KVM_CAP_IRQFD) && defined(CONFIG_EVENTFD)
 +
 +#include <sys/eventfd.h>
 +
 +static int _kvm_irqfd(kvm_context_t kvm, int fd, int gsi, int flags)
 +{
 +    struct kvm_irqfd data = {
 +        .fd = fd,
 +        .gsi = gsi,
 +        .flags = flags,
 +    };
 +
 +    return kvm_vm_ioctl(kvm_state, KVM_IRQFD, &data);
 +}
 +
 +int kvm_irqfd(kvm_context_t kvm, int gsi, int flags)
 +{
 +    int r;
 +    int fd;
 +
 +    if (!kvm_check_extension(kvm_state, KVM_CAP_IRQFD))
 +        return -ENOENT;
 +
 +    fd = eventfd(0, 0);
 +    if (fd < 0) {
 +        return -errno;
 +    }
 +
 +    r = _kvm_irqfd(kvm, fd, gsi, 0);
 +    if (r < 0) {
 +        close(fd);
 +        return -errno;
 +    }
 +
 +    return fd;
 +}
 +
 +#else                           /* KVM_CAP_IRQFD */
 +
 +int kvm_irqfd(kvm_context_t kvm, int gsi, int flags)
 +{
 +    return -ENOSYS;
 +}
 +
 +#endif                          /* KVM_CAP_IRQFD */
 +unsigned long kvm_get_thread_id(void)
 +{
 +    return syscall(SYS_gettid);
 +}
 +
 +static void qemu_cond_wait(pthread_cond_t *cond)
 +{
 +    CPUState *env = cpu_single_env;
 +
 +    pthread_cond_wait(cond, &qemu_mutex);
 +    cpu_single_env = env;
 +}
 +
 +static void sig_ipi_handler(int n)
 +{
 +}
 +
 +static void sigbus_reraise(void)
 +{
 +    sigset_t set;
 +    struct sigaction action;
 +
 +    memset(&action, 0, sizeof(action));
 +    action.sa_handler = SIG_DFL;
 +    if (!sigaction(SIGBUS, &action, NULL)) {
 +        raise(SIGBUS);
 +        sigemptyset(&set);
 +        sigaddset(&set, SIGBUS);
 +        sigprocmask(SIG_UNBLOCK, &set, NULL);
 +    }
 +    perror("Failed to re-raise SIGBUS!\n");
 +    abort();
 +}
 +
 +static void sigbus_handler(int n, struct qemu_signalfd_siginfo *siginfo,
 +                           void *ctx)
 +{
 +    if (kvm_on_sigbus(siginfo->ssi_code, (void *)(intptr_t)siginfo->ssi_addr))
 +        sigbus_reraise();
 +}
 +
 +void on_vcpu(CPUState *env, void (*func)(void *data), void *data)
 +{
 +    struct qemu_work_item wi;
 +
 +    if (env == current_env) {
 +        func(data);
 +        return;
 +    }
 +
 +    wi.func = func;
 +    wi.data = data;
 +    if (!env->kvm_cpu_state.queued_work_first) {
 +        env->kvm_cpu_state.queued_work_first = &wi;
 +    } else {
 +        env->kvm_cpu_state.queued_work_last->next = &wi;
 +    }
 +    env->kvm_cpu_state.queued_work_last = &wi;
 +    wi.next = NULL;
 +    wi.done = false;
 +
 +    pthread_kill(env->kvm_cpu_state.thread, SIG_IPI);
 +    while (!wi.done) {
 +        qemu_cond_wait(&qemu_work_cond);
 +    }
 +}
 +
 +static void do_kvm_cpu_synchronize_state(void *_env)
 +{
 +    CPUState *env = _env;
 +
 +    if (!env->kvm_vcpu_dirty) {
 +        kvm_arch_save_regs(env);
 +        env->kvm_vcpu_dirty = 1;
 +    }
 +}
 +
 +void kvm_cpu_synchronize_state(CPUState *env)
 +{
 +    if (!env->kvm_vcpu_dirty) {
 +        on_vcpu(env, do_kvm_cpu_synchronize_state, env);
 +    }
 +}
 +
 +void kvm_cpu_synchronize_post_reset(CPUState *env)
 +{
 +    kvm_arch_load_regs(env, KVM_PUT_RESET_STATE);
 +    env->kvm_vcpu_dirty = 0;
 +}
 +
 +void kvm_cpu_synchronize_post_init(CPUState *env)
 +{
 +    kvm_arch_load_regs(env, KVM_PUT_FULL_STATE);
 +    env->kvm_vcpu_dirty = 0;
 +}
 +
 +static void inject_interrupt(void *data)
 +{
 +    cpu_interrupt(current_env, (long) data);
 +}
 +
 +void kvm_inject_interrupt(CPUState *env, int mask)
 +{
 +    on_vcpu(env, inject_interrupt, (void *) (long) mask);
 +}
 +
 +void kvm_update_interrupt_request(CPUState *env)
 +{
 +    int signal = 0;
 +
 +    if (env) {
 +        if (!current_env || !current_env->created) {
 +            signal = 1;
 +        }
 +        /*
 +         * Testing for created here is really redundant
 +         */
 +        if (current_env && current_env->created &&
 +            env != current_env && !env->kvm_cpu_state.signalled) {
 +            signal = 1;
 +        }
 +
 +        if (signal) {
 +            env->kvm_cpu_state.signalled = 1;
 +            if (env->kvm_cpu_state.thread) {
 +                pthread_kill(env->kvm_cpu_state.thread, SIG_IPI);
 +            }
 +        }
 +    }
 +}
 +
 +int kvm_cpu_exec(CPUState *env)
 +{
 +    int r;
 +
 +    r = kvm_run(env);
 +    if (r < 0) {
 +        printf("kvm_run returned %d\n", r);
 +        vm_stop(0);
 +    }
 +
 +    return 0;
 +}
 +
 +int kvm_cpu_is_stopped(CPUState *env)
 +{
 +    return !vm_running || env->stopped;
 +}
 +
 +static void flush_queued_work(CPUState *env)
 +{
 +    struct qemu_work_item *wi;
 +
 +    if (!env->kvm_cpu_state.queued_work_first) {
 +        return;
 +    }
 +
 +    while ((wi = env->kvm_cpu_state.queued_work_first)) {
 +        env->kvm_cpu_state.queued_work_first = wi->next;
 +        wi->func(wi->data);
 +        wi->done = true;
 +    }
 +    env->kvm_cpu_state.queued_work_last = NULL;
 +    pthread_cond_broadcast(&qemu_work_cond);
 +}
 +
 +static void kvm_main_loop_wait(CPUState *env, int timeout)
 +{
 +    struct timespec ts;
 +    int r, e;
 +    siginfo_t siginfo;
 +    sigset_t waitset;
 +    sigset_t chkset;
 +
 +    ts.tv_sec = timeout / 1000;
 +    ts.tv_nsec = (timeout % 1000) * 1000000;
 +    sigemptyset(&waitset);
 +    sigaddset(&waitset, SIG_IPI);
 +    sigaddset(&waitset, SIGBUS);
 +
 +    do {
 +        pthread_mutex_unlock(&qemu_mutex);
 +
 +        r = sigtimedwait(&waitset, &siginfo, &ts);
 +        e = errno;
 +
 +        pthread_mutex_lock(&qemu_mutex);
 +
 +        if (r == -1 && !(e == EAGAIN || e == EINTR)) {
 +            printf("sigtimedwait: %s\n", strerror(e));
 +            exit(1);
 +        }
 +
 +        switch (r) {
 +        case SIGBUS:
 +            if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr))
 +                sigbus_reraise();
 +            break;
 +        default:
 +            break;
 +        }
 +
 +        r = sigpending(&chkset);
 +        if (r == -1) {
 +            printf("sigpending: %s\n", strerror(e));
 +            exit(1);
 +        }
 +    } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
 +
 +    cpu_single_env = env;
 +    flush_queued_work(env);
 +
 +    if (env->stop) {
 +        env->stop = 0;
 +        env->stopped = 1;
 +        pthread_cond_signal(&qemu_pause_cond);
 +    }
 +
 +    env->kvm_cpu_state.signalled = 0;
 +}
 +
 +static int all_threads_paused(void)
 +{
 +    CPUState *penv = first_cpu;
 +
 +    while (penv) {
 +        if (penv->stop) {
 +            return 0;
 +        }
 +        penv = (CPUState *) penv->next_cpu;
 +    }
 +
 +    return 1;
 +}
 +
 +static void pause_all_threads(void)
 +{
 +    CPUState *penv = first_cpu;
 +
 +    while (penv) {
 +        if (penv != cpu_single_env) {
 +            penv->stop = 1;
 +            pthread_kill(penv->kvm_cpu_state.thread, SIG_IPI);
 +        } else {
 +            penv->stop = 0;
 +            penv->stopped = 1;
 +            cpu_exit(penv);
 +        }
 +        penv = (CPUState *) penv->next_cpu;
 +    }
 +
 +    while (!all_threads_paused()) {
 +        qemu_cond_wait(&qemu_pause_cond);
 +    }
 +}
 +
 +static void resume_all_threads(void)
 +{
 +    CPUState *penv = first_cpu;
 +
 +    assert(!cpu_single_env);
 +
 +    while (penv) {
 +        penv->stop = 0;
 +        penv->stopped = 0;
 +        pthread_kill(penv->kvm_cpu_state.thread, SIG_IPI);
 +        penv = (CPUState *) penv->next_cpu;
 +    }
 +}
 +
 +static void kvm_vm_state_change_handler(void *context, int running, int reason)
 +{
 +    if (running) {
 +        resume_all_threads();
 +    } else {
 +        pause_all_threads();
 +    }
 +}
 +
 +static void setup_kernel_sigmask(CPUState *env)
 +{
 +    sigset_t set;
 +
 +    sigemptyset(&set);
 +    sigaddset(&set, SIGUSR2);
 +    sigaddset(&set, SIGIO);
 +    sigaddset(&set, SIGALRM);
 +    sigprocmask(SIG_BLOCK, &set, NULL);
 +
 +    sigprocmask(SIG_BLOCK, NULL, &set);
 +    sigdelset(&set, SIG_IPI);
 +    sigdelset(&set, SIGBUS);
 +
 +    kvm_set_signal_mask(env, &set);
 +}
 +
 +static void qemu_kvm_system_reset(void)
 +{
 +    pause_all_threads();
 +
 +    qemu_system_reset();
 +
 +    resume_all_threads();
 +}
 +
 +static void process_irqchip_events(CPUState *env)
 +{
 +    kvm_arch_process_irqchip_events(env);
 +    if (kvm_arch_has_work(env))
 +        env->halted = 0;
 +}
 +
 +static int kvm_main_loop_cpu(CPUState *env)
 +{
 +    while (1) {
 +        int run_cpu = !kvm_cpu_is_stopped(env);
 +        if (run_cpu && !kvm_irqchip_in_kernel()) {
 +            process_irqchip_events(env);
 +            run_cpu = !env->halted;
 +        }
 +        if (run_cpu) {
 +            kvm_cpu_exec(env);
 +            kvm_main_loop_wait(env, 0);
 +        } else {
 +            kvm_main_loop_wait(env, 1000);
 +        }
 +    }
 +    pthread_mutex_unlock(&qemu_mutex);
 +    return 0;
 +}
 +
 +static void *ap_main_loop(void *_env)
 +{
 +    CPUState *env = _env;
 +    sigset_t signals;
 +#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
 +    struct ioperm_data *data = NULL;
 +#endif
 +
 +    current_env = env;
 +    env->thread_id = kvm_get_thread_id();
 +    sigfillset(&signals);
 +    sigprocmask(SIG_BLOCK, &signals, NULL);
 +
 +#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
 +    /* do ioperm for io ports of assigned devices */
 +    QLIST_FOREACH(data, &ioperm_head, entries)
 +        on_vcpu(env, kvm_arch_do_ioperm, data);
 +#endif
 +
 +    pthread_mutex_lock(&qemu_mutex);
 +    cpu_single_env = env;
 +
 +    kvm_create_vcpu(env, env->cpu_index);
 +    setup_kernel_sigmask(env);
 +
 +    /* signal VCPU creation */
 +    current_env->created = 1;
 +    pthread_cond_signal(&qemu_vcpu_cond);
 +
 +    /* and wait for machine initialization */
 +    while (!qemu_system_ready) {
 +        qemu_cond_wait(&qemu_system_cond);
 +    }
 +
 +    /* re-initialize cpu_single_env after re-acquiring qemu_mutex */
 +    cpu_single_env = env;
 +
 +    kvm_main_loop_cpu(env);
 +    return NULL;
 +}
 +
 +int kvm_init_vcpu(CPUState *env)
 +{
 +    pthread_create(&env->kvm_cpu_state.thread, NULL, ap_main_loop, env);
 +
 +    while (env->created == 0) {
 +        qemu_cond_wait(&qemu_vcpu_cond);
 +    }
 +
 +    return 0;
 +}
 +
 +int kvm_vcpu_inited(CPUState *env)
 +{
 +    return env->created;
 +}
 +
 +#ifdef TARGET_I386
 +void kvm_hpet_disable_kpit(void)
 +{
 +    struct kvm_pit_state2 ps2;
 +
 +    kvm_get_pit2(kvm_context, &ps2);
 +    ps2.flags |= KVM_PIT_FLAGS_HPET_LEGACY;
 +    kvm_set_pit2(kvm_context, &ps2);
 +}
 +
 +void kvm_hpet_enable_kpit(void)
 +{
 +    struct kvm_pit_state2 ps2;
 +
 +    kvm_get_pit2(kvm_context, &ps2);
 +    ps2.flags &= ~KVM_PIT_FLAGS_HPET_LEGACY;
 +    kvm_set_pit2(kvm_context, &ps2);
 +}
 +#endif
 +
 +int kvm_init_ap(void)
 +{
 +    struct sigaction action;
 +
 +    qemu_add_vm_change_state_handler(kvm_vm_state_change_handler, NULL);
 +
 +    signal(SIG_IPI, sig_ipi_handler);
 +
 +    memset(&action, 0, sizeof(action));
 +    action.sa_flags = SA_SIGINFO;
 +    action.sa_sigaction = (void (*)(int, siginfo_t*, void*))sigbus_handler;
 +    sigaction(SIGBUS, &action, NULL);
 +    prctl(PR_MCE_KILL, 1, 1, 0, 0);
 +    return 0;
 +}
 +
 +/* If we have signalfd, we mask out the signals we want to handle and then
 + * use signalfd to listen for them.  We rely on whatever the current signal
 + * handler is to dispatch the signals when we receive them.
 + */
 +
 +static void sigfd_handler(void *opaque)
 +{
 +    int fd = (unsigned long) opaque;
 +    struct qemu_signalfd_siginfo info;
 +    struct sigaction action;
 +    ssize_t len;
 +
 +    while (1) {
 +        do {
 +            len = read(fd, &info, sizeof(info));
 +        } while (len == -1 && errno == EINTR);
 +
 +        if (len == -1 && errno == EAGAIN) {
 +            break;
 +        }
 +
 +        if (len != sizeof(info)) {
 +            printf("read from sigfd returned %zd: %m\n", len);
 +            return;
 +        }
 +
 +        sigaction(info.ssi_signo, NULL, &action);
 +        if ((action.sa_flags & SA_SIGINFO) && action.sa_sigaction) {
 +            action.sa_sigaction(info.ssi_signo,
 +                                (siginfo_t *)&info, NULL);
 +        } else if (action.sa_handler) {
 +            action.sa_handler(info.ssi_signo);
 +        }
 +    }
 +}
 +
 +int kvm_main_loop(void)
 +{
 +    sigset_t mask;
 +    int sigfd;
 +
 +    io_thread = pthread_self();
 +    qemu_system_ready = 1;
 +
 +    sigemptyset(&mask);
 +    sigaddset(&mask, SIGIO);
 +    sigaddset(&mask, SIGALRM);
 +    sigaddset(&mask, SIGBUS);
 +    sigprocmask(SIG_BLOCK, &mask, NULL);
 +
 +    sigfd = qemu_signalfd(&mask);
 +    if (sigfd == -1) {
 +        fprintf(stderr, "failed to create signalfd\n");
 +        return -errno;
 +    }
 +
 +    fcntl(sigfd, F_SETFL, O_NONBLOCK);
 +
 +    qemu_set_fd_handler2(sigfd, NULL, sigfd_handler, NULL,
 +                         (void *)(unsigned long) sigfd);
 +
 +    pthread_cond_broadcast(&qemu_system_cond);
 +
 +    io_thread_sigfd = sigfd;
 +    cpu_single_env = NULL;
 +
 +    while (1) {
 +        main_loop_wait(0);
 +        if (qemu_shutdown_requested()) {
 +            monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
 +            if (qemu_no_shutdown()) {
 +                vm_stop(0);
 +            } else {
 +                break;
 +            }
 +        } else if (qemu_powerdown_requested()) {
 +            monitor_protocol_event(QEVENT_POWERDOWN, NULL);
 +            qemu_irq_raise(qemu_system_powerdown);
 +        } else if (qemu_reset_requested()) {
 +            qemu_kvm_system_reset();
 +        } else if (kvm_debug_cpu_requested) {
 +            gdb_set_stop_cpu(kvm_debug_cpu_requested);
 +            vm_stop(EXCP_DEBUG);
 +            kvm_debug_cpu_requested = NULL;
 +        }
 +    }
 +
 +    pause_all_threads();
 +    pthread_mutex_unlock(&qemu_mutex);
 +
 +    return 0;
 +}
 +
 +#if !defined(TARGET_I386)
 +int kvm_arch_init_irq_routing(void)
 +{
 +    return 0;
 +}
 +#endif
 +
 +extern int no_hpet;
 +
 +static int kvm_create_context(void)
 +{
 +    static const char upgrade_note[] =
 +    "Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n"
 +    "(see http://sourceforge.net/projects/kvm).\n";
 +
 +    int r;
 +
 +    if (!kvm_irqchip) {
 +        kvm_disable_irqchip_creation(kvm_context);
 +    }
 +    if (!kvm_pit) {
 +        kvm_disable_pit_creation(kvm_context);
 +    }
 +    if (kvm_create(kvm_context, 0, NULL) < 0) {
 +        kvm_finalize(kvm_state);
 +        return -1;
 +    }
 +    r = kvm_arch_qemu_create_context();
 +    if (r < 0) {
 +        kvm_finalize(kvm_state);
 +        return -1;
 +    }
 +    if (kvm_pit && !kvm_pit_reinject) {
 +        if (kvm_reinject_control(kvm_context, 0)) {
 +            fprintf(stderr, "failure to disable in-kernel PIT reinjection\n");
 +            return -1;
 +        }
 +    }
 +
 +    /* There was a nasty bug in < kvm-80 that prevents memory slots from being
 +     * destroyed properly.  Since we rely on this capability, refuse to work
 +     * with any kernel without this capability. */
 +    if (!kvm_check_extension(kvm_state, KVM_CAP_DESTROY_MEMORY_REGION_WORKS)) {
 +        fprintf(stderr,
 +                "KVM kernel module broken (DESTROY_MEMORY_REGION).\n%s",
 +                upgrade_note);
 +        return -EINVAL;
 +    }
 +
 +    r = kvm_arch_init_irq_routing();
 +    if (r < 0) {
 +        return r;
 +    }
 +
 +    kvm_state->vcpu_events = 0;
 +#ifdef KVM_CAP_VCPU_EVENTS
 +    kvm_state->vcpu_events = kvm_check_extension(kvm_state, KVM_CAP_VCPU_EVENTS);
 +#endif
 +
 +    kvm_state->debugregs = 0;
 +#ifdef KVM_CAP_DEBUGREGS
 +    kvm_state->debugregs = kvm_check_extension(kvm_state, KVM_CAP_DEBUGREGS);
 +#endif
 +
 +    kvm_state->xsave = 0;
 +#ifdef KVM_CAP_XSAVE
 +    kvm_state->xsave = kvm_check_extension(kvm_state, KVM_CAP_XSAVE);
 +#endif
 +
 +    kvm_state->xcrs = 0;
 +#ifdef KVM_CAP_XCRS
 +    kvm_state->xcrs = kvm_check_extension(kvm_state, KVM_CAP_XCRS);
 +#endif
 +
 +    kvm_state->many_ioeventfds = kvm_check_many_ioeventfds();
 +
 +    kvm_init_ap();
 +    if (kvm_irqchip) {
 +        if (!qemu_kvm_has_gsi_routing()) {
 +            irq0override = 0;
 +#ifdef TARGET_I386
 +            /* if kernel can't do irq routing, interrupt source
 +             * override 0->2 can not be set up as required by hpet,
 +             * so disable hpet.
 +             */
 +            no_hpet = 1;
 +        } else if (!qemu_kvm_has_pit_state2()) {
 +            no_hpet = 1;
 +        }
 +#else
 +        }
 +#endif
 +    }
 +
 +    return 0;
 +}
 +
 +#ifdef KVM_CAP_IRQCHIP
 +
 +int kvm_set_irq(int irq, int level, int *status)
 +{
 +    return kvm_set_irq_level(kvm_context, irq, level, status);
 +}
 +
 +#endif
 +
 +static void kvm_mutex_unlock(void)
 +{
 +    assert(!cpu_single_env);
 +    pthread_mutex_unlock(&qemu_mutex);
 +}
 +
 +static void kvm_mutex_lock(void)
 +{
 +    pthread_mutex_lock(&qemu_mutex);
 +    cpu_single_env = NULL;
 +}
 +
 +void qemu_mutex_unlock_iothread(void)
 +{
 +    if (kvm_enabled()) {
 +        kvm_mutex_unlock();
 +    }
 +}
 +
 +void qemu_mutex_lock_iothread(void)
 +{
 +    if (kvm_enabled()) {
 +        kvm_mutex_lock();
 +    }
 +}
 +
 +#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
 +void kvm_add_ioperm_data(struct ioperm_data *data)
 +{
 +    QLIST_INSERT_HEAD(&ioperm_head, data, entries);
 +}
 +
 +void kvm_remove_ioperm_data(unsigned long start_port, unsigned long num)
 +{
 +    struct ioperm_data *data;
 +
 +    data = QLIST_FIRST(&ioperm_head);
 +    while (data) {
 +        struct ioperm_data *next = QLIST_NEXT(data, entries);
 +
 +        if (data->start_port == start_port && data->num == num) {
 +            QLIST_REMOVE(data, entries);
 +            qemu_free(data);
 +        }
 +
 +        data = next;
 +    }
 +}
 +
 +void kvm_ioperm(CPUState *env, void *data)
 +{
 +    if (kvm_enabled() && qemu_system_ready) {
 +        on_vcpu(env, kvm_arch_do_ioperm, data);
 +    }
 +}
 +
 +#endif
 +
 +int kvm_set_boot_cpu_id(uint32_t id)
 +{
 +    return kvm_set_boot_vcpu_id(kvm_context, id);
 +}
 +
diff --cc qemu-kvm.h
index db4e340,0000000..88cf276
mode 100644,000000..100644
--- a/qemu-kvm.h
+++ b/qemu-kvm.h
@@@ -1,771 -1,0 +1,771 @@@
 +/*
 + * qemu/kvm integration
 + *
 + * Copyright (C) 2006-2008 Qumranet Technologies
 + *
 + * Licensed under the terms of the GNU GPL version 2 or higher.
 + */
 +#ifndef THE_ORIGINAL_AND_TRUE_QEMU_KVM_H
 +#define THE_ORIGINAL_AND_TRUE_QEMU_KVM_H
 +
 +#include "cpu.h"
 +
 +#include <signal.h>
 +#include <stdlib.h>
 +
 +#ifdef CONFIG_KVM
 +
 +#if defined(__s390__)
 +#include <asm/ptrace.h>
 +#endif
 +
 +#include <stdint.h>
 +
 +#ifndef __user
 +#define __user       /* temporary, until installed via make headers_install */
 +#endif
 +
 +#include <linux/kvm.h>
 +
 +#include <signal.h>
 +
 +/* FIXME: share this number with kvm */
 +/* FIXME: or dynamically alloc/realloc regions */
 +#ifdef __s390__
 +#define KVM_MAX_NUM_MEM_REGIONS 1u
 +#define MAX_VCPUS 64
 +#define LIBKVM_S390_ORIGIN (0UL)
 +#elif defined(__ia64__)
 +#define KVM_MAX_NUM_MEM_REGIONS 32u
 +#define MAX_VCPUS 256
 +#else
 +#define KVM_MAX_NUM_MEM_REGIONS 32u
 +#define MAX_VCPUS 16
 +#endif
 +
 +/* kvm abi verison variable */
 +extern int kvm_abi;
 +
 +/**
 + * \brief The KVM context
 + *
 + * The verbose KVM context
 + */
 +
 +struct kvm_context {
 +    void *opaque;
 +    /// is dirty pages logging enabled for all regions or not
 +    int dirty_pages_log_all;
 +    /// do not create in-kernel irqchip if set
 +    int no_irqchip_creation;
 +    /// in-kernel irqchip status
 +    int irqchip_in_kernel;
 +    /// ioctl to use to inject interrupts
 +    int irqchip_inject_ioctl;
 +    /// do not create in-kernel pit if set
 +    int no_pit_creation;
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    struct kvm_irq_routing *irq_routes;
 +    int nr_allocated_irq_routes;
 +#endif
 +    void *used_gsi_bitmap;
 +    int max_gsi;
 +};
 +
 +typedef struct kvm_context *kvm_context_t;
 +
 +#include "kvm.h"
 +int kvm_alloc_kernel_memory(kvm_context_t kvm, unsigned long memory,
 +                            void **vm_mem);
 +int kvm_alloc_userspace_memory(kvm_context_t kvm, unsigned long memory,
 +                               void **vm_mem);
 +
 +int kvm_arch_create(kvm_context_t kvm, unsigned long phys_mem_bytes,
 +                    void **vm_mem);
 +
 +int kvm_arch_run(CPUState *env);
 +
 +
 +void kvm_show_code(CPUState *env);
 +
 +int handle_halt(CPUState *env);
 +
 +int handle_shutdown(kvm_context_t kvm, CPUState *env);
 +void post_kvm_run(kvm_context_t kvm, CPUState *env);
 +int pre_kvm_run(kvm_context_t kvm, CPUState *env);
 +int handle_io_window(kvm_context_t kvm);
 +int try_push_interrupts(kvm_context_t kvm);
 +
 +#if defined(__x86_64__) || defined(__i386__)
 +struct kvm_x86_mce;
 +#endif
 +
 +/*!
 + * \brief Disable the in-kernel IRQCHIP creation
 + *
 + * In-kernel irqchip is enabled by default. If userspace irqchip is to be used,
 + * this should be called prior to kvm_create().
 + *
 + * \param kvm Pointer to the kvm_context
 + */
 +void kvm_disable_irqchip_creation(kvm_context_t kvm);
 +
 +/*!
 + * \brief Disable the in-kernel PIT creation
 + *
 + * In-kernel pit is enabled by default. If userspace pit is to be used,
 + * this should be called prior to kvm_create().
 + *
 + *  \param kvm Pointer to the kvm_context
 + */
 +void kvm_disable_pit_creation(kvm_context_t kvm);
 +
 +/*!
 + * \brief Create new virtual machine
 + *
 + * This creates a new virtual machine, maps physical RAM to it, and creates a
 + * virtual CPU for it.\n
 + * \n
 + * Memory gets mapped for addresses 0->0xA0000, 0xC0000->phys_mem_bytes
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param phys_mem_bytes The amount of physical ram you want the VM to have
 + * \param phys_mem This pointer will be set to point to the memory that
 + * kvm_create allocates for physical RAM
 + * \return 0 on success
 + */
 +int kvm_create(kvm_context_t kvm, unsigned long phys_mem_bytes,
 +               void **phys_mem);
 +int kvm_create_vm(kvm_context_t kvm);
 +void kvm_create_irqchip(kvm_context_t kvm);
 +
 +/*!
 + * \brief Start the VCPU
 + *
 + * This starts the VCPU and virtualization is started.\n
 + * \n
 + * This function will not return until any of these conditions are met:
 + * - An IO/MMIO handler does not return "0"
 + * - An exception that neither the guest OS, nor KVM can handle occurs
 + *
 + * \note This function will call the callbacks registered in kvm_init()
 + * to emulate those functions
 + * \note If you at any point want to interrupt the VCPU, kvm_run() will
 + * listen to the EINTR signal. This allows you to simulate external interrupts
 + * and asyncronous IO.
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param vcpu Which virtual CPU should be started
 + * \return 0 on success, but you really shouldn't expect this function to
 + * return except for when an error has occured, or when you have sent it
 + * an EINTR signal.
 + */
 +int kvm_run(CPUState *env);
 +
 +/*!
 + * \brief Check if a vcpu is ready for interrupt injection
 + *
 + * This checks if vcpu interrupts are not masked by mov ss or sti.
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param vcpu Which virtual CPU should get dumped
 + * \return boolean indicating interrupt injection readiness
 + */
 +int kvm_is_ready_for_interrupt_injection(CPUState *env);
 +
 +/*!
 + * \brief Read VCPU registers
 + *
 + * This gets the GP registers from the VCPU and outputs them
 + * into a kvm_regs structure
 + *
 + * \note This function returns a \b copy of the VCPUs registers.\n
 + * If you wish to modify the VCPUs GP registers, you should call kvm_set_regs()
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param vcpu Which virtual CPU should get dumped
 + * \param regs Pointer to a kvm_regs which will be populated with the VCPUs
 + * registers values
 + * \return 0 on success
 + */
 +int kvm_get_regs(CPUState *env, struct kvm_regs *regs);
 +
 +/*!
 + * \brief Write VCPU registers
 + *
 + * This sets the GP registers on the VCPU from a kvm_regs structure
 + *
 + * \note When this function returns, the regs pointer and the data it points to
 + * can be discarded
 + * \param kvm Pointer to the current kvm_context
 + * \param vcpu Which virtual CPU should get dumped
 + * \param regs Pointer to a kvm_regs which will be populated with the VCPUs
 + * registers values
 + * \return 0 on success
 + */
 +int kvm_set_regs(CPUState *env, struct kvm_regs *regs);
 +
 +#ifdef KVM_CAP_MP_STATE
 +/*!
 + *  * \brief Read VCPU MP state
 + *
 + */
 +int kvm_get_mpstate(CPUState *env, struct kvm_mp_state *mp_state);
 +
 +/*!
 + *  * \brief Write VCPU MP state
 + *
 + */
 +int kvm_set_mpstate(CPUState *env, struct kvm_mp_state *mp_state);
 +#endif
 +
 +#if defined(__i386__) || defined(__x86_64__)
 +/*!
 + * \brief Simulate an external vectored interrupt
 + *
 + * This allows you to simulate an external vectored interrupt.
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param vcpu Which virtual CPU should get dumped
 + * \param irq Vector number
 + * \return 0 on success
 + */
 +int kvm_inject_irq(CPUState *env, unsigned irq);
 +
 +
 +/*!
 + * \brief Setting the number of shadow pages to be allocated to the vm
 + *
 + * \param kvm pointer to kvm_context
 + * \param nrshadow_pages number of pages to be allocated
 + */
 +int kvm_set_shadow_pages(kvm_context_t kvm, unsigned int nrshadow_pages);
 +
 +/*!
 + * \brief Getting the number of shadow pages that are allocated to the vm
 + *
 + * \param kvm pointer to kvm_context
 + * \param nrshadow_pages number of pages to be allocated
 + */
 +int kvm_get_shadow_pages(kvm_context_t kvm, unsigned int *nrshadow_pages);
 +
 +#endif
 +
 +/*!
 + * \brief Dump VCPU registers
 + *
 + * This dumps some of the information that KVM has about a virtual CPU, namely:
 + * - GP Registers
 + *
 + * A much more verbose version of this is available as kvm_dump_vcpu()
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param vcpu Which virtual CPU should get dumped
 + * \return 0 on success
 + */
 +void kvm_show_regs(CPUState *env);
 +
 +
 +void *kvm_create_phys_mem(kvm_context_t, unsigned long phys_start,
 +                          unsigned long len, int log, int writable);
 +void kvm_destroy_phys_mem(kvm_context_t, unsigned long phys_start,
 +                          unsigned long len);
 +
 +int kvm_is_containing_region(kvm_context_t kvm, unsigned long phys_start,
 +                             unsigned long size);
 +int kvm_register_phys_mem(kvm_context_t kvm, unsigned long phys_start,
 +                          void *userspace_addr, unsigned long len, int log);
 +int kvm_get_dirty_pages_range(kvm_context_t kvm, unsigned long phys_addr,
 +                              unsigned long end_addr, void *opaque,
 +                              int (*cb)(unsigned long start,
 +                                        unsigned long len, void *bitmap,
 +                                        void *opaque));
 +int kvm_register_coalesced_mmio(kvm_context_t kvm, uint64_t addr,
 +                                uint32_t size);
 +int kvm_unregister_coalesced_mmio(kvm_context_t kvm, uint64_t addr,
 +                                  uint32_t size);
 +
 +/*!
 + * \brief Get a bitmap of guest ram pages which are allocated to the guest.
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param phys_addr Memory slot phys addr
 + * \param bitmap Long aligned address of a big enough bitmap (one bit per page)
 + */
 +int kvm_get_mem_map(kvm_context_t kvm, unsigned long phys_addr, void *bitmap);
 +int kvm_get_mem_map_range(kvm_context_t kvm, unsigned long phys_addr,
 +                          unsigned long len, void *buf, void *opaque,
 +                          int (*cb)(unsigned long start,
 +                                    unsigned long len, void *bitmap,
 +                                    void *opaque));
 +int kvm_set_irq_level(kvm_context_t kvm, int irq, int level, int *status);
 +
 +int kvm_dirty_pages_log_enable_slot(kvm_context_t kvm, uint64_t phys_start,
 +                                    uint64_t len);
 +int kvm_dirty_pages_log_disable_slot(kvm_context_t kvm, uint64_t phys_start,
 +                                     uint64_t len);
 +/*!
 + * \brief Enable dirty-pages-logging for all memory regions
 + *
 + * \param kvm Pointer to the current kvm_context
 + */
 +int kvm_dirty_pages_log_enable_all(kvm_context_t kvm);
 +
 +/*!
 + * \brief Disable dirty-page-logging for some memory regions
 + *
 + * Disable dirty-pages-logging for those memory regions that were
 + * created with dirty-page-logging disabled.
 + *
 + * \param kvm Pointer to the current kvm_context
 + */
 +int kvm_dirty_pages_log_reset(kvm_context_t kvm);
 +
 +#ifdef KVM_CAP_IRQCHIP
 +/*!
 + * \brief Dump in kernel IRQCHIP contents
 + *
 + * Dump one of the in kernel irq chip devices, including PIC (master/slave)
 + * and IOAPIC into a kvm_irqchip structure
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param chip The irq chip device to be dumped
 + */
 +int kvm_get_irqchip(kvm_context_t kvm, struct kvm_irqchip *chip);
 +
 +/*!
 + * \brief Set in kernel IRQCHIP contents
 + *
 + * Write one of the in kernel irq chip devices, including PIC (master/slave)
 + * and IOAPIC
 + *
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param chip THe irq chip device to be written
 + */
 +int kvm_set_irqchip(kvm_context_t kvm, struct kvm_irqchip *chip);
 +
 +#if defined(__i386__) || defined(__x86_64__)
 +/*!
 + * \brief Get in kernel local APIC for vcpu
 + *
 + * Save the local apic state including the timer of a virtual CPU
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param vcpu Which virtual CPU should be accessed
 + * \param s Local apic state of the specific virtual CPU
 + */
 +int kvm_get_lapic(CPUState *env, struct kvm_lapic_state *s);
 +
 +/*!
 + * \brief Set in kernel local APIC for vcpu
 + *
 + * Restore the local apic state including the timer of a virtual CPU
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param vcpu Which virtual CPU should be accessed
 + * \param s Local apic state of the specific virtual CPU
 + */
 +int kvm_set_lapic(CPUState *env, struct kvm_lapic_state *s);
 +
 +#endif
 +
 +/*!
 + * \brief Simulate an NMI
 + *
 + * This allows you to simulate a non-maskable interrupt.
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param vcpu Which virtual CPU should get dumped
 + * \return 0 on success
 + */
 +int kvm_inject_nmi(CPUState *env);
 +
 +#endif
 +
 +/*!
 + * \brief Initialize coalesced MMIO
 + *
 + * Check for coalesced MMIO capability and store in context
 + *
 + * \param kvm Pointer to the current kvm_context
 + */
 +int kvm_init_coalesced_mmio(kvm_context_t kvm);
 +
 +#ifdef KVM_CAP_PIT
 +
 +#if defined(__i386__) || defined(__x86_64__)
 +/*!
 + * \brief Get in kernel PIT of the virtual domain
 + *
 + * Save the PIT state.
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param s PIT state of the virtual domain
 + */
 +int kvm_get_pit(kvm_context_t kvm, struct kvm_pit_state *s);
 +
 +/*!
 + * \brief Set in kernel PIT of the virtual domain
 + *
 + * Restore the PIT state.
 + * Timer would be retriggerred after restored.
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param s PIT state of the virtual domain
 + */
 +int kvm_set_pit(kvm_context_t kvm, struct kvm_pit_state *s);
 +
 +int kvm_reinject_control(kvm_context_t kvm, int pit_reinject);
 +
 +#ifdef KVM_CAP_PIT_STATE2
 +/*!
 + * \brief Check for kvm support of kvm_pit_state2
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \return 0 on success
 + */
 +int kvm_has_pit_state2(kvm_context_t kvm);
 +
 +/*!
 + * \brief Set in kernel PIT state2 of the virtual domain
 + *
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param ps2 PIT state2 of the virtual domain
 + * \return 0 on success
 + */
 +int kvm_set_pit2(kvm_context_t kvm, struct kvm_pit_state2 *ps2);
 +
 +/*!
 + * \brief Get in kernel PIT state2 of the virtual domain
 + *
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param ps2 PIT state2 of the virtual domain
 + * \return 0 on success
 + */
 +int kvm_get_pit2(kvm_context_t kvm, struct kvm_pit_state2 *ps2);
 +
 +#endif
 +#endif
 +#endif
 +
 +#ifdef KVM_CAP_VAPIC
 +
 +int kvm_enable_vapic(CPUState *env, uint64_t vapic);
 +
 +#endif
 +
 +#if defined(__s390__)
 +int kvm_s390_initial_reset(kvm_context_t kvm, int slot);
 +int kvm_s390_interrupt(kvm_context_t kvm, int slot,
 +                       struct kvm_s390_interrupt *kvmint);
 +int kvm_s390_set_initial_psw(kvm_context_t kvm, int slot, psw_t psw);
 +int kvm_s390_store_status(kvm_context_t kvm, int slot, unsigned long addr);
 +#endif
 +
 +#ifdef KVM_CAP_DEVICE_ASSIGNMENT
 +/*!
 + * \brief Notifies host kernel about a PCI device to be assigned to a guest
 + *
 + * Used for PCI device assignment, this function notifies the host
 + * kernel about the assigning of the physical PCI device to a guest.
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param assigned_dev Parameters, like bus, devfn number, etc
 + */
 +int kvm_assign_pci_device(kvm_context_t kvm,
 +                          struct kvm_assigned_pci_dev *assigned_dev);
 +
 +/*!
 + * \brief Assign IRQ for an assigned device
 + *
 + * Used for PCI device assignment, this function assigns IRQ numbers for
 + * an physical device and guest IRQ handling.
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param assigned_irq Parameters, like dev id, host irq, guest irq, etc
 + */
 +int kvm_assign_irq(kvm_context_t kvm, struct kvm_assigned_irq *assigned_irq);
 +
 +#ifdef KVM_CAP_ASSIGN_DEV_IRQ
 +/*!
 + * \brief Deassign IRQ for an assigned device
 + *
 + * Used for PCI device assignment, this function deassigns IRQ numbers
 + * for an assigned device.
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param assigned_irq Parameters, like dev id, host irq, guest irq, etc
 + */
 +int kvm_deassign_irq(kvm_context_t kvm, struct kvm_assigned_irq *assigned_irq);
 +#endif
 +#endif
 +
 +#ifdef KVM_CAP_DEVICE_DEASSIGNMENT
 +/*!
 + * \brief Notifies host kernel about a PCI device to be deassigned from a guest
 + *
 + * Used for hot remove PCI device, this function notifies the host
 + * kernel about the deassigning of the physical PCI device from a guest.
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param assigned_dev Parameters, like bus, devfn number, etc
 + */
 +int kvm_deassign_pci_device(kvm_context_t kvm,
 +                            struct kvm_assigned_pci_dev *assigned_dev);
 +#endif
 +
 +/*!
 + * \brief Determines the number of gsis that can be routed
 + *
 + * Returns the number of distinct gsis that can be routed by kvm.  This is
 + * also the number of distinct routes (if a gsi has two routes, than another
 + * gsi cannot be used...)
 + *
 + * \param kvm Pointer to the current kvm_context
 + */
 +int kvm_get_gsi_count(kvm_context_t kvm);
 +
 +/*!
 + * \brief Clears the temporary irq routing table
 + *
 + * Clears the temporary irq routing table.  Nothing is committed to the
 + * running VM.
 + *
 + */
 +int kvm_clear_gsi_routes(void);
 +
 +/*!
 + * \brief Adds an irq route to the temporary irq routing table
 + *
 + * Adds an irq route to the temporary irq routing table.  Nothing is
 + * committed to the running VM.
 + */
 +int kvm_add_irq_route(int gsi, int irqchip, int pin);
 +
 +/*!
 + * \brief Removes an irq route from the temporary irq routing table
 + *
 + * Adds an irq route to the temporary irq routing table.  Nothing is
 + * committed to the running VM.
 + */
 +int kvm_del_irq_route(int gsi, int irqchip, int pin);
 +
 +struct kvm_irq_routing_entry;
 +/*!
 + * \brief Adds a routing entry to the temporary irq routing table
 + *
 + * Adds a filled routing entry to the temporary irq routing table. Nothing is
 + * committed to the running VM.
 + */
 +int kvm_add_routing_entry(struct kvm_irq_routing_entry *entry);
 +
 +/*!
 + * \brief Removes a routing from the temporary irq routing table
 + *
 + * Remove a routing to the temporary irq routing table.  Nothing is
 + * committed to the running VM.
 + */
 +int kvm_del_routing_entry(struct kvm_irq_routing_entry *entry);
 +
 +/*!
 + * \brief Updates a routing in the temporary irq routing table
 + *
 + * Update a routing in the temporary irq routing table
 + * with a new value. entry type and GSI can not be changed.
 + * Nothing is committed to the running VM.
 + */
 +int kvm_update_routing_entry(struct kvm_irq_routing_entry *entry,
 +                             struct kvm_irq_routing_entry *newentry);
 +
 +
 +/*!
 + * \brief Create a file descriptor for injecting interrupts
 + *
 + * Creates an eventfd based file-descriptor that maps to a specific GSI
 + * in the guest.  eventfd compliant signaling (write() from userspace, or
 + * eventfd_signal() from kernelspace) will cause the GSI to inject
 + * itself into the guest at the next available window.
 + *
 + * \param kvm Pointer to the current kvm_context
 + * \param gsi GSI to assign to this fd
 + * \param flags reserved, must be zero
 + */
 +int kvm_irqfd(kvm_context_t kvm, int gsi, int flags);
 +
 +#ifdef KVM_CAP_DEVICE_MSIX
 +int kvm_assign_set_msix_nr(kvm_context_t kvm,
 +                           struct kvm_assigned_msix_nr *msix_nr);
 +int kvm_assign_set_msix_entry(kvm_context_t kvm,
 +                              struct kvm_assigned_msix_entry *entry);
 +#endif
 +
 +#else                           /* !CONFIG_KVM */
 +
 +typedef struct kvm_context *kvm_context_t;
 +typedef struct kvm_vcpu_context *kvm_vcpu_context_t;
 +
 +struct kvm_pit_state {
 +};
 +
 +#endif                          /* !CONFIG_KVM */
 +
 +
 +/*!
 + * \brief Create new KVM context
 + *
 + * This creates a new kvm_context. A KVM context is a small area of data that
 + * holds information about the KVM instance that gets created by this call.\n
 + * This should always be your first call to KVM.
 + *
 + * \param opaque Not used
 + * \return NULL on failure
 + */
- int kvm_init(int smp_cpus);
++int kvm_init(void);
 +
 +int kvm_main_loop(void);
 +int kvm_init_ap(void);
 +int kvm_vcpu_inited(CPUState *env);
 +void kvm_save_lapic(CPUState *env);
 +void kvm_load_lapic(CPUState *env);
 +
 +void kvm_hpet_enable_kpit(void);
 +void kvm_hpet_disable_kpit(void);
 +
 +int kvm_physical_memory_set_dirty_tracking(int enable);
 +
 +void on_vcpu(CPUState *env, void (*func)(void *data), void *data);
 +void qemu_kvm_call_with_env(void (*func)(void *), void *data, CPUState *env);
 +void qemu_kvm_cpuid_on_env(CPUState *env);
 +void kvm_inject_interrupt(CPUState *env, int mask);
 +void kvm_update_after_sipi(CPUState *env);
 +void kvm_update_interrupt_request(CPUState *env);
 +#ifndef CONFIG_USER_ONLY
 +void *kvm_cpu_create_phys_mem(target_phys_addr_t start_addr, unsigned long size,
 +                              int log, int writable);
 +
 +void kvm_cpu_destroy_phys_mem(target_phys_addr_t start_addr,
 +                              unsigned long size);
 +void kvm_qemu_log_memory(target_phys_addr_t start, target_phys_addr_t size,
 +                         int log);
 +#endif
 +int kvm_qemu_create_memory_alias(uint64_t phys_start, uint64_t len,
 +                                 uint64_t target_phys);
 +int kvm_qemu_destroy_memory_alias(uint64_t phys_start);
 +
 +int kvm_arch_qemu_create_context(void);
 +
 +void kvm_arch_save_regs(CPUState *env);
 +void kvm_arch_load_regs(CPUState *env, int level);
 +int kvm_arch_has_work(CPUState *env);
 +void kvm_arch_process_irqchip_events(CPUState *env);
 +int kvm_arch_try_push_interrupts(void *opaque);
 +void kvm_arch_push_nmi(void *opaque);
 +void kvm_arch_cpu_reset(CPUState *env);
 +int kvm_set_boot_cpu_id(uint32_t id);
 +
 +void qemu_kvm_aio_wait_start(void);
 +void qemu_kvm_aio_wait(void);
 +void qemu_kvm_aio_wait_end(void);
 +
 +void kvm_tpr_access_report(CPUState *env, uint64_t rip, int is_write);
 +
 +int kvm_arch_init_irq_routing(void);
 +
 +int kvm_mmio_read(void *opaque, uint64_t addr, uint8_t * data, int len);
 +int kvm_mmio_write(void *opaque, uint64_t addr, uint8_t * data, int len);
 +
 +#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
 +struct ioperm_data;
 +
 +void kvm_ioperm(CPUState *env, void *data);
 +void kvm_add_ioperm_data(struct ioperm_data *data);
 +void kvm_remove_ioperm_data(unsigned long start_port, unsigned long num);
 +void kvm_arch_do_ioperm(void *_data);
 +#endif
 +
 +#define ALIGN(x, y)  (((x)+(y)-1) & ~((y)-1))
 +#define BITMAP_SIZE(m) (ALIGN(((m)>>TARGET_PAGE_BITS), HOST_LONG_BITS) / 8)
 +
 +#ifdef CONFIG_KVM
 +#include "qemu-queue.h"
 +
 +extern int kvm_irqchip;
 +extern int kvm_pit;
 +extern int kvm_pit_reinject;
 +extern int kvm_nested;
 +extern kvm_context_t kvm_context;
 +
 +struct ioperm_data {
 +    unsigned long start_port;
 +    unsigned long num;
 +    int turn_on;
 +    QLIST_ENTRY(ioperm_data) entries;
 +};
 +
 +void qemu_kvm_cpu_stop(CPUState *env);
 +int kvm_arch_halt(CPUState *env);
 +int handle_tpr_access(void *opaque, CPUState *env, uint64_t rip,
 +                      int is_write);
 +
 +#define qemu_kvm_has_gsi_routing() kvm_has_gsi_routing()
 +#ifdef TARGET_I386
 +#define qemu_kvm_has_pit_state2() kvm_has_pit_state2(kvm_context)
 +#endif
 +#else
 +#define kvm_nested 0
 +#define qemu_kvm_has_gsi_routing() (0)
 +#ifdef TARGET_I386
 +#define qemu_kvm_has_pit_state2() (0)
 +#endif
 +#define qemu_kvm_cpu_stop(env) do {} while(0)
 +#endif
 +
 +#ifdef CONFIG_KVM
 +
 +typedef struct KVMSlot {
 +    target_phys_addr_t start_addr;
 +    ram_addr_t memory_size;
 +    ram_addr_t phys_offset;
 +    int slot;
 +    int flags;
 +} KVMSlot;
 +
 +typedef struct kvm_dirty_log KVMDirtyLog;
 +
 +struct KVMState {
 +    KVMSlot slots[32];
 +    int fd;
 +    int vmfd;
 +    int coalesced_mmio;
 +#ifdef KVM_CAP_COALESCED_MMIO
 +    struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
 +#endif
 +    int broken_set_mem_region;
 +    int migration_log;
 +    int vcpu_events;
 +    int robust_singlestep;
 +    int debugregs;
 +#ifdef KVM_CAP_SET_GUEST_DEBUG
 +    QTAILQ_HEAD(, kvm_sw_breakpoint) kvm_sw_breakpoints;
 +#endif
 +    int irqchip_in_kernel;
 +    int pit_in_kernel;
 +    int xsave, xcrs;
 +    int many_ioeventfds;
 +
 +    struct kvm_context kvm_context;
 +};
 +
 +extern struct KVMState *kvm_state;
 +
 +int kvm_tpr_enable_vapic(CPUState *env);
 +
 +unsigned long kvm_get_thread_id(void);
 +int kvm_cpu_is_stopped(CPUState *env);
 +
 +#endif
 +
 +#endif
diff --cc vl.c
index 3b4cd60,33f844f..420a548
--- a/vl.c
+++ b/vl.c
@@@ -2897,19 -2836,15 +2897,19 @@@ int main(int argc, char **argv, char **
      }
  
      if (kvm_allowed) {
-         int ret = kvm_init(smp_cpus);
+         int ret = kvm_init();
          if (ret < 0) {
 -            if (!kvm_available()) {
 -                printf("KVM not supported for this target\n");
 -            } else {
 -                fprintf(stderr, "failed to initialize KVM: %s\n", strerror(-ret));
 +            if (kvm_allowed > 0) {
 +                if (!kvm_available()) {
 +                    printf("KVM not supported for this target\n");
 +                } else {
 +                    fprintf(stderr, "failed to initialize KVM: %s\n", strerror(-ret));
 +                }
 +                exit(1);
              }
 -            exit(1);
 +            fprintf(stderr, "Could not initialize KVM, will disable KVM support\n");
          }
 +        kvm_allowed = ret >= 0;
      }
  
      if (qemu_init_main_loop()) {
commit b13181147c92a61768ed7dd030830c35585456eb
Merge: 509573a... c3a3a7d...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Feb 2 18:47:30 2011 -0200

    Merge commit 'c3a3a7d356c4df2fe145037172ae52cba5f545a5' into upstream-merge
    
    * commit 'c3a3a7d356c4df2fe145037172ae52cba5f545a5':
      kvm: x86: Refactor msr_star/hsave_pa setup and checks
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --cc target-i386/kvm.c
index ff218df,454ddb1..4c30a98
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@@ -479,13 -461,10 +481,12 @@@ void kvm_arch_reset_vcpu(CPUState *env
      }
  }
  
- int has_msr_star;
- int has_msr_hsave_pa;
++#ifdef OBSOLETE_KVM_IMPL
 +
- static void kvm_supported_msrs(CPUState *env)
+ static int kvm_get_supported_msrs(KVMState *s)
  {
      static int kvm_supported_msrs;
-     int ret;
+     int ret = 0;
  
      /* first time */
      if (kvm_supported_msrs == 0) {
commit 509573a62753ca2263aca029b82f24e3b4731826
Merge: 5347982... 1a5e9d2...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Feb 2 18:35:42 2011 -0200

    Merge commit '1a5e9d2fafa5d31587e218cea462637bfad52b53' into upstream-merge
    
    * commit '1a5e9d2fafa5d31587e218cea462637bfad52b53':
      kvm: x86: Fix xcr0 reset mismerge
    
    Conflicts:
    	target-i386/kvm.c
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

commit 5347982c9243c789a7768ec52c35ff1de41858b4
Merge: 0620648... 3390e7f...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Feb 2 18:27:32 2011 -0200

    Merge commit '3390e7f79784cbc75df408740cda4edbcf57ac58' into upstream-merge
    
    * commit '3390e7f79784cbc75df408740cda4edbcf57ac58':
      kvm: x86: Remove redundant mp_state initialization
      kvm: x86: Prepare kvm_get_mp_state for in-kernel irqchip
      kvm: x86: Align kvm_arch_put_registers code with comment
      x86: Optionally dump code bytes on cpu_dump_state
      kvm: Improve reporting of fatal errors
      kvm: Stop on all fatal exit reasons
      kvm: x86: Swallow KVM_EXIT_SET_TPR
      kvm: Fix coding style violations
    
    Conflicts:
    	target-i386/kvm.c
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --cc kvm-all.c
index 7418372,41decde..a334ae8
--- a/kvm-all.c
+++ b/kvm-all.c
@@@ -640,19 -631,11 +639,19 @@@ static int kvm_client_migration_log(str
  }
  
  static CPUPhysMemoryClient kvm_cpu_phys_memory_client = {
- 	.set_memory = kvm_client_set_memory,
- 	.sync_dirty_bitmap = kvm_client_sync_dirty_bitmap,
- 	.migration_log = kvm_client_migration_log,
+     .set_memory = kvm_client_set_memory,
+     .sync_dirty_bitmap = kvm_client_sync_dirty_bitmap,
+     .migration_log = kvm_client_migration_log,
  };
  
 +
 +void kvm_cpu_register_phys_memory_client(void)
 +{
 +    cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client);
 +}
 +
 +#ifdef OBSOLETE_KVM_IMPL
 +
  int kvm_init(int smp_cpus)
  {
      static const char upgrade_note[] =
diff --cc target-i386/kvm.c
index 28b13fc,07c75c0..3817dd1
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@@ -324,17 -321,6 +324,11 @@@ int kvm_arch_init_vcpu(CPUState *env
      uint32_t signature[3];
  #endif
  
 +    r = _kvm_arch_init_vcpu(env);
 +    if (r < 0) {
 +        return r;
 +    }
 +
- #ifdef OBSOLETE_KVM_IMPL
- 
-     env->mp_state = KVM_MP_STATE_RUNNABLE;
- 
- #endif
- 
      env->cpuid_features &= kvm_arch_get_supported_cpuid(env, 1, 0, R_EDX);
  
      i = env->cpuid_ext_features & CPUID_EXT_HYPERVISOR;
@@@ -1228,9 -1196,11 +1222,12 @@@ static int kvm_get_mp_state(CPUState *e
          return ret;
      }
      env->mp_state = mp_state.mp_state;
+     if (kvm_irqchip_in_kernel()) {
+         env->halted = (mp_state.mp_state == KVM_MP_STATE_HALTED);
+     }
      return 0;
  }
 +#endif
  
  static int kvm_put_vcpu_events(CPUState *env, int level)
  {
commit 06206483986326dec6425fda889615ba10f5b78b
Merge: a508e1f... b9bec74...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Feb 2 17:52:54 2011 -0200

    Merge commit 'b9bec74bcb16519a876ec21cd5277c526a9b512d' into upstream-merge
    
    * commit 'b9bec74bcb16519a876ec21cd5277c526a9b512d':
      kvm: x86: Fix a few coding style violations
      kvm: x86: Prevent sign extension of DR7 in guest debugging mode
      kvm: x86: Remove obsolete SS.RPL/DPL aligment
      kvm: x86: Fix DPL write back of segment registers
    
    Conflicts:
    	target-i386/kvm.c
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --cc target-i386/kvm.c
index c7c3499,fda07d2..28b13fc
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@@ -605,8 -581,6 +608,8 @@@ int kvm_arch_init(KVMState *s, int smp_
      return kvm_init_identity_map_page(s);
  }
  
 +#endif
-                     
++
  static void set_v8086_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
  {
      lhs->selector = rhs->selector;
@@@ -645,24 -619,23 +648,24 @@@ static void get_seg(SegmentCache *lhs, 
      lhs->selector = rhs->selector;
      lhs->base = rhs->base;
      lhs->limit = rhs->limit;
-     lhs->flags =
- 	(rhs->type << DESC_TYPE_SHIFT)
- 	| (rhs->present * DESC_P_MASK)
- 	| (rhs->dpl << DESC_DPL_SHIFT)
- 	| (rhs->db << DESC_B_SHIFT)
- 	| (rhs->s * DESC_S_MASK)
- 	| (rhs->l << DESC_L_SHIFT)
- 	| (rhs->g * DESC_G_MASK)
- 	| (rhs->avl * DESC_AVL_MASK);
+     lhs->flags = (rhs->type << DESC_TYPE_SHIFT) |
+                  (rhs->present * DESC_P_MASK) |
+                  (rhs->dpl << DESC_DPL_SHIFT) |
+                  (rhs->db << DESC_B_SHIFT) |
+                  (rhs->s * DESC_S_MASK) |
+                  (rhs->l << DESC_L_SHIFT) |
+                  (rhs->g * DESC_G_MASK) |
+                  (rhs->avl * DESC_AVL_MASK);
  }
  
 +
  static void kvm_getput_reg(__u64 *kvm_reg, target_ulong *qemu_reg, int set)
  {
-     if (set)
+     if (set) {
          *kvm_reg = *qemu_reg;
-     else
+     } else {
          *qemu_reg = *kvm_reg;
+     }
  }
  
  static int kvm_getput_regs(CPUState *env, int set)
commit a508e1f8868c3c9a7565b18b208e4296315c5a30
Merge: 920eafd... 7cc2cc3...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Feb 2 17:43:06 2011 -0200

    Merge commit '7cc2cc3e2608b182f1e0fc7ecae6e3b1fa4f46e0' into upstream-merge
    
    * commit '7cc2cc3e2608b182f1e0fc7ecae6e3b1fa4f46e0':
      kvm: introduce kvm_inject_x86_mce_on
      kvm: kvm_mce_inj_* subroutines for templated error injections
      kvm: introduce kvm_mce_in_progress
      Add function for checking mca broadcast of CPU
    
    Conflicts:
    	target-i386/kvm.c
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --cc target-i386/kvm.c
index 1e41c44,9a4bf98..c7c3499
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@@ -265,6 -263,23 +263,23 @@@ static void kvm_do_inject_x86_mce(void 
      }
  }
  
+ static void kvm_inject_x86_mce_on(CPUState *env, struct kvm_x86_mce *mce,
+                                   int flag)
+ {
+     struct kvm_x86_mce_data data = {
+         .env = env,
+         .mce = mce,
+         .abort_on_error = (flag & ABORT_ON_ERROR),
+     };
+ 
+     if (!env->mcg_cap) {
+         fprintf(stderr, "MCE support is not enabled!\n");
+         return;
+     }
+ 
 -    run_on_cpu(env, kvm_do_inject_x86_mce, &data);
++    on_vcpu(env, kvm_do_inject_x86_mce, &data);
+ }
+ 
  static void kvm_mce_broadcast_rest(CPUState *env);
  #endif
  
commit 920eafdc87e867a7da8af21b4512ca5372da60de
Merge: 99f4953... 31ce5e0...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Feb 2 16:57:21 2011 -0200

    Merge commit '31ce5e0c49821d92fb30cce2f3055ef33613b287' into upstream-merge
    
    * commit '31ce5e0c49821d92fb30cce2f3055ef33613b287':
      Add "broadcast" option for mce command
      Clean up cpu_inject_x86_mce()
      kvm: convert kvm_ioctl(KVM_CHECK_EXTENSION) to kvm_check_extension()
      kvm: Enable user space NMI injection for kvm guest
    
    Conflicts:
    	target-i386/kvm.c
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --cc target-i386/kvm.c
index 272594d,8b868ad..1e41c44
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@@ -288,10 -290,15 +290,15 @@@ void kvm_inject_x86_mce(CPUState *cenv
          return;
      }
  
+     if (flag & MCE_BROADCAST) {
+         kvm_mce_broadcast_rest(cenv);
+     }
+ 
 -    run_on_cpu(cenv, kvm_do_inject_x86_mce, &data);
 +    on_vcpu(cenv, kvm_do_inject_x86_mce, &data);
  #else
-     if (abort_on_error)
+     if (flag & ABORT_ON_ERROR) {
          abort();
+     }
  #endif
  }
  
commit 99f49536370b440c45c5b6e962b12b1ad95451ed
Merge: 6f32e3d... 225d02c...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Wed Feb 2 16:46:27 2011 -0200

    Merge commit '225d02cd1a34d5d87e8acefbf8e244a5d12f5f8c' into upstream-merge
    
    * commit '225d02cd1a34d5d87e8acefbf8e244a5d12f5f8c':
      Avoid deadlock whith iothread and icount
      microblaze: cleanup helper_addkc
      microblaze: Improve subkc
      microblaze: Fix 3rd addkc arg when rd is r0
      microblaze: Improve addkc
      microblaze: Remove debug leftovers.
      microblaze: Reorganize for future patches
      ppc: Correct BookE tlb reads
      checkpatch: Fix bracing false positives on #else
    
    Conflicts:
    	qemu-timer.c
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --cc qemu-timer.c
index d29d2cd,db1ec49..c250706
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@@ -1079,9 -1075,17 +1075,18 @@@ void quit_timers(void
  
  int qemu_calculate_timeout(void)
  {
- #ifndef CONFIG_IOTHREAD
      int timeout;
  
 -#ifdef CONFIG_IOTHREAD
++#define QEMUKVM 1
++#if defined (CONFIG_IOTHREAD) || defined (QEMUKVM)
+     /* When using icount, making forward progress with qemu_icount when the
+        guest CPU is idle is critical. We only use the static io-thread timeout
+        for non icount runs.  */
+     if (!use_icount) {
+         return 1000;
+     }
+ #endif
+ 
      if (!vm_running)
          timeout = 5000;
      else {
commit bfddb47a343b4718e5768aa80bce8adead0f7fca
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Feb 2 08:39:28 2011 +0100

    Open up the 0.15 development branch
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/VERSION b/VERSION
index 0c123d0..d07c6d0 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.13.90
+0.14.50
commit 0e192fae3c79e7d2830f8b1fa694cd8e128084cf
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Feb 1 16:59:46 2011 -0600

    Update version for 0.14.0-rc0
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/VERSION b/VERSION
index d82f77b..0c123d0 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.13.50
+0.13.90
commit f487d6278f75f84378833b8c3a67443346d639dc
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Feb 1 16:57:00 2011 -0600

    Update SeaBIOS to 0.6.1.2
    
     - 06d0bdd Minor build fixes.
     - 33abfc0 Update version to 0.6.1.2.
     - 484dd56 fix virtio-blk failure after reboot
     - dd9c0d3 Update version to 0.6.1.1.
     - 50ecfa8 mark irq9 active high in DSDT
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index f79c342..e191908 100644
Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ
diff --git a/roms/seabios b/roms/seabios
index 0ff9051..06d0bdd 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit 0ff9051f756ba739bc2edca77925191c3c6cbc2f
+Subproject commit 06d0bdd9e2e20377b3180e4986b14c8549b393e4
commit 5430a28fe452907c9e1b2097e073bc1ea4b29f39
Author: mst at redhat.com <mst at redhat.com>
Date:   Tue Feb 1 22:13:42 2011 +0200

    vhost: force vhost off for non-MSI guests
    
    When MSI is off, each interrupt needs to be bounced through the io
    thread when it's set/cleared, so vhost-net causes more context switches and
    higher CPU utilization than userspace virtio which handles networking in
    the same thread.
    
    We'll need to fix this by adding level irq support in kvm irqfd,
    for now disable vhost-net in these configurations.
    
    Added a vhostforce flag to force vhost-net back on.
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/vhost.c b/hw/vhost.c
index 6082da2..38cc3b3 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -581,7 +581,7 @@ static void vhost_virtqueue_cleanup(struct vhost_dev *dev,
                               0, virtio_queue_get_desc_size(vdev, idx));
 }
 
-int vhost_dev_init(struct vhost_dev *hdev, int devfd)
+int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
 {
     uint64_t features;
     int r;
@@ -613,6 +613,7 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd)
     hdev->log_enabled = false;
     hdev->started = false;
     cpu_register_phys_memory_client(&hdev->client);
+    hdev->force = force;
     return 0;
 fail:
     r = -errno;
@@ -627,6 +628,13 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
     close(hdev->control);
 }
 
+bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev)
+{
+    return !vdev->binding->query_guest_notifiers ||
+        vdev->binding->query_guest_notifiers(vdev->binding_opaque) ||
+        hdev->force;
+}
+
 int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
 {
     int i, r;
diff --git a/hw/vhost.h b/hw/vhost.h
index 86dd834..c8c595a 100644
--- a/hw/vhost.h
+++ b/hw/vhost.h
@@ -38,10 +38,12 @@ struct vhost_dev {
     bool log_enabled;
     vhost_log_chunk_t *log;
     unsigned long long log_size;
+    bool force;
 };
 
-int vhost_dev_init(struct vhost_dev *hdev, int devfd);
+int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force);
 void vhost_dev_cleanup(struct vhost_dev *hdev);
+bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev);
 int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
 void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev);
 
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
index c068be1..420e05f 100644
--- a/hw/vhost_net.c
+++ b/hw/vhost_net.c
@@ -81,7 +81,8 @@ static int vhost_net_get_fd(VLANClientState *backend)
     }
 }
 
-struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
+struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd,
+                                 bool force)
 {
     int r;
     struct vhost_net *net = qemu_malloc(sizeof *net);
@@ -98,7 +99,7 @@ struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
         (1 << VHOST_NET_F_VIRTIO_NET_HDR);
     net->backend = r;
 
-    r = vhost_dev_init(&net->dev, devfd);
+    r = vhost_dev_init(&net->dev, devfd, force);
     if (r < 0) {
         goto fail;
     }
@@ -121,6 +122,11 @@ fail:
     return NULL;
 }
 
+bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
+{
+    return vhost_dev_query(&net->dev, dev);
+}
+
 int vhost_net_start(struct vhost_net *net,
                     VirtIODevice *dev)
 {
@@ -188,15 +194,21 @@ void vhost_net_cleanup(struct vhost_net *net)
     qemu_free(net);
 }
 #else
-struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
+struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd,
+                                 bool force)
+{
+    return NULL;
+}
+
+bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
 {
-	return NULL;
+    return false;
 }
 
 int vhost_net_start(struct vhost_net *net,
 		    VirtIODevice *dev)
 {
-	return -ENOSYS;
+    return -ENOSYS;
 }
 void vhost_net_stop(struct vhost_net *net,
 		    VirtIODevice *dev)
@@ -209,7 +221,7 @@ void vhost_net_cleanup(struct vhost_net *net)
 
 unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
 {
-	return features;
+    return features;
 }
 void vhost_net_ack_features(struct vhost_net *net, unsigned features)
 {
diff --git a/hw/vhost_net.h b/hw/vhost_net.h
index 6c18ff7..91e40b1 100644
--- a/hw/vhost_net.h
+++ b/hw/vhost_net.h
@@ -6,8 +6,9 @@
 struct vhost_net;
 typedef struct vhost_net VHostNetState;
 
-VHostNetState *vhost_net_init(VLANClientState *backend, int devfd);
+VHostNetState *vhost_net_init(VLANClientState *backend, int devfd, bool force);
 
+bool vhost_net_query(VHostNetState *net, VirtIODevice *dev);
 int vhost_net_start(VHostNetState *net, VirtIODevice *dev);
 void vhost_net_stop(VHostNetState *net, VirtIODevice *dev);
 
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 161f114..671d952 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -119,7 +119,11 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
         return;
     }
     if (!n->vhost_started) {
-        int r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
+        int r;
+        if (!vhost_net_query(tap_get_vhost_net(n->nic->nc.peer), &n->vdev)) {
+            return;
+        }
+        r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
         if (r < 0) {
             error_report("unable to start vhost net: %d: "
                          "falling back on userspace virtio", -r);
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index d07ff97..3911b09 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -595,6 +595,12 @@ static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
     return 0;
 }
 
+static bool virtio_pci_query_guest_notifiers(void *opaque)
+{
+    VirtIOPCIProxy *proxy = opaque;
+    return msix_enabled(&proxy->pci_dev);
+}
+
 static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
 {
     VirtIOPCIProxy *proxy = opaque;
@@ -658,6 +664,7 @@ static const VirtIOBindings virtio_pci_bindings = {
     .save_queue = virtio_pci_save_queue,
     .load_queue = virtio_pci_load_queue,
     .get_features = virtio_pci_get_features,
+    .query_guest_notifiers = virtio_pci_query_guest_notifiers,
     .set_host_notifier = virtio_pci_set_host_notifier,
     .set_guest_notifiers = virtio_pci_set_guest_notifiers,
     .vmstate_change = virtio_pci_vmstate_change,
diff --git a/hw/virtio.h b/hw/virtio.h
index d8546d5..31d16e1 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -93,6 +93,7 @@ typedef struct {
     int (*load_config)(void * opaque, QEMUFile *f);
     int (*load_queue)(void * opaque, int n, QEMUFile *f);
     unsigned (*get_features)(void * opaque);
+    bool (*query_guest_notifiers)(void * opaque);
     int (*set_guest_notifiers)(void * opaque, bool assigned);
     int (*set_host_notifier)(void * opaque, int n, bool assigned);
     void (*vmstate_change)(void * opaque, bool running);
diff --git a/net/tap.c b/net/tap.c
index eada34a..b8cd252 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -491,8 +491,10 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
         }
     }
 
-    if (qemu_opt_get_bool(opts, "vhost", !!qemu_opt_get(opts, "vhostfd"))) {
+    if (qemu_opt_get_bool(opts, "vhost", !!qemu_opt_get(opts, "vhostfd") ||
+                          qemu_opt_get_bool(opts, "vhostforce", false))) {
         int vhostfd, r;
+        bool force = qemu_opt_get_bool(opts, "vhostforce", false);
         if (qemu_opt_get(opts, "vhostfd")) {
             r = net_handle_fd_param(mon, qemu_opt_get(opts, "vhostfd"));
             if (r == -1) {
@@ -502,7 +504,7 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
         } else {
             vhostfd = -1;
         }
-        s->vhost_net = vhost_net_init(&s->nc, vhostfd);
+        s->vhost_net = vhost_net_init(&s->nc, vhostfd, force);
         if (!s->vhost_net) {
             error_report("vhost-net requested but could not be initialized");
             return -1;
diff --git a/qemu-options.hx b/qemu-options.hx
index 598a1bd..945edf3 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1050,7 +1050,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][,ifname=name][,script=file][,downscript=dfile][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h]\n"
+    "-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostforce=on|off]\n"
     "                connect the host TAP network interface to VLAN 'n' and use the\n"
     "                network scripts 'file' (default=" DEFAULT_NETWORK_SCRIPT ")\n"
     "                and 'dfile' (default=" DEFAULT_NETWORK_DOWN_SCRIPT ")\n"
@@ -1061,6 +1061,8 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "                use vnet_hdr=off to avoid enabling the IFF_VNET_HDR tap flag\n"
     "                use vnet_hdr=on to make the lack of IFF_VNET_HDR support an error condition\n"
     "                use vhost=on to enable experimental in kernel accelerator\n"
+    "                    (only has effect for virtio guests which use MSIX)\n"
+    "                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"
 #endif
     "-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n"
commit f157ed202e51dc2492b201dc34ed28e89c973fb7
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Tue Feb 1 14:25:40 2011 +0200

    tap: safe sndbuf default
    
    With current sndbuf default value, a blocked
    target guest can prevent another guest from
    transmitting any packets. While current
    sndbuf value (1M) is reported to help some
    UDP based workloads, the default should
    be safe (0).
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/net/tap-linux.c b/net/tap-linux.c
index f7aa904..ff8cad0 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -82,12 +82,17 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
     return fd;
 }
 
-/* sndbuf should be set to a value lower than the tx queue
- * capacity of any destination network interface.
+/* sndbuf implements a kind of flow control for tap.
+ * Unfortunately when it's enabled, and packets are sent
+ * to other guests on the same host, the receiver
+ * can lock up the transmitter indefinitely.
+ *
+ * To avoid packet loss, sndbuf should be set to a value lower than the tx
+ * queue capacity of any destination network interface.
  * Ethernet NICs generally have txqueuelen=1000, so 1Mb is
- * a good default, given a 1500 byte MTU.
+ * a good value, given a 1500 byte MTU.
  */
-#define TAP_DEFAULT_SNDBUF 1024*1024
+#define TAP_DEFAULT_SNDBUF 0
 
 int tap_set_sndbuf(int fd, QemuOpts *opts)
 {
diff --git a/qemu-options.hx b/qemu-options.hx
index 939297a..598a1bd 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1057,7 +1057,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "                use '[down]script=no' to disable script execution\n"
     "                use 'fd=h' to connect to an already opened TAP interface\n"
     "                use 'sndbuf=nbytes' to limit the size of the send buffer (the\n"
-    "                default of 'sndbuf=1048576' can be disabled using 'sndbuf=0')\n"
+    "                default is disabled 'sndbuf=0' to enable flow control set 'sndbuf=1048576')\n"
     "                use vnet_hdr=off to avoid enabling the IFF_VNET_HDR tap flag\n"
     "                use vnet_hdr=on to make the lack of IFF_VNET_HDR support an error condition\n"
     "                use vhost=on to enable experimental in kernel accelerator\n"
commit 466b58648a7b2ba7edb280b585e0b0c26e3be31e
Author: Gleb Natapov <gleb at redhat.com>
Date:   Sun Jan 30 12:29:19 2011 +0200

    Add boot index documentation.
    
    Signed-off-by: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/docs/bootindex.txt b/docs/bootindex.txt
new file mode 100644
index 0000000..16083b3
--- /dev/null
+++ b/docs/bootindex.txt
@@ -0,0 +1,43 @@
+= Bootindex propery =
+
+Block and net devices have bootindex property. This property is used to
+determine the order in which firmware will consider devices for booting
+the guest OS. If the bootindex property is not set for a device, it gets
+lowest boot priority. There is no particular order in which devices with
+unset bootindex property will be considered for booting, but they will
+still be bootable.
+
+== Example ==
+
+Lets assume we have QEMU machine with two NICs (virtio, e1000) and two
+disks (IDE, virtio):
+
+qemu -drive file=disk1.img,if=none,id=disk1
+     -device ide-drive,drive=disk1,bootindex=4
+     -drive file=disk2.img,if=none,id=disk2
+     -device virtio-blk-pci,drive=disk2,bootindex=3
+     -netdev type=user,id=net0 -device virtio-net-pci,netdev=net0,bootindex=2
+     -netdev type=user,id=net1 -device e1000,netdev=net1,bootindex=1
+
+Given the command above, firmware should try to boot from the e1000 NIC
+first.  If this fails, it should try the virtio NIC next, if this fails
+too, it should try the virtio disk, and then the IDE disk.
+
+== Limitations ==
+
+1. Some firmware has limitations on which devices can be considered for
+booting.  For instance, the PC BIOS boot specification allows only one
+disk to be bootable.  If boot from disk fails for some reason, the BIOS
+won't retry booting from other disk.  It still can try to boot from
+floppy or net, though.
+
+2. Sometimes, firmware cannot map the device path QEMU wants firmware to
+boot from to a boot method.  It doesn't happen for devices the firmware
+can natively boot from, but if firmware relies on an option ROM for
+booting, and the same option ROM is used for booting from more then one
+device, the firmware may not be able to ask the option ROM to boot from
+a particular device reliably.  For instance with PC BIOS, if a SCSI HBA
+has three bootable devices target1, target3, target5 connected to it,
+the option ROM will have a boot method for each of them, but it is not
+possible to map from boot method back to a specific target.  This is a
+shortcoming of PC BIOS boot specification.
commit cf8ce30d03339861a46c31aa44c11279c282f2b0
Author: Gleb Natapov <gleb at redhat.com>
Date:   Sun Jan 30 12:29:18 2011 +0200

    Add bootindex handling into usb storage device.
    
    Signed-off-by: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Gleb Natapov <gleb at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 97d1e4a..76f5b02 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -532,6 +532,7 @@ static int usb_msd_initfn(USBDevice *dev)
         }
     }
 
+    add_boot_device_path(s->conf.bootindex, &dev->qdev, "/disk at 0,0");
     return 0;
 }
 
@@ -595,6 +596,7 @@ static USBDevice *usb_msd_init(const char *filename)
 static struct USBDeviceInfo msd_info = {
     .product_desc   = "QEMU USB MSD",
     .qdev.name      = "usb-storage",
+    .qdev.fw_name      = "storage",
     .qdev.size      = sizeof(MSDState),
     .usb_desc       = &desc,
     .init           = usb_msd_initfn,
commit 363f8cb9bcd308bd03d28e04ea5f5557dea5d5e8
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 23 13:42:54 2010 +0100

    fix QemuOpts leak
    
    Now that no backend's open function saves the passed QemuOpts, fix a leak
    in the qemu_chr_open backwards-compatible parser.
    
    Signed-off-by: Paolo Bonzini <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 bb0c32d..ee4f4ca 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2559,6 +2559,7 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*i
     if (chr && qemu_opt_get_bool(opts, "mux", 0)) {
         monitor_init(chr, MONITOR_USE_READLINE);
     }
+    qemu_opts_del(opts);
     return chr;
 }
 
commit 44b37b933745a9005504427dec06f4066af9762e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 23 13:42:53 2010 +0100

    remove text_console_opts
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/console.c b/console.c
index 60b80ee..57d6eb5 100644
--- a/console.c
+++ b/console.c
@@ -1437,7 +1437,6 @@ void console_color_init(DisplayState *ds)
 
 static int n_text_consoles;
 static CharDriverState *text_consoles[128];
-static QemuOpts *text_console_opts[128];
 
 static void text_console_set_echo(CharDriverState *chr, bool echo)
 {
@@ -1446,7 +1445,7 @@ static void text_console_set_echo(CharDriverState *chr, bool echo)
     s->echo = echo;
 }
 
-static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpts *opts)
+static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
 {
     TextConsole *s;
     static int color_inited;
@@ -1520,7 +1519,6 @@ CharDriverState *text_console_init(QemuOpts *opts)
         exit(1);
     }
     text_consoles[n_text_consoles] = chr;
-    text_console_opts[n_text_consoles] = opts;
     n_text_consoles++;
 
     width = qemu_opt_get_number(opts, "width", 0);
@@ -1555,9 +1553,7 @@ void text_consoles_set_display(DisplayState *ds)
     int i;
 
     for (i = 0; i < n_text_consoles; i++) {
-        text_console_do_init(text_consoles[i], ds, text_console_opts[i]);
-        qemu_opts_del(text_console_opts[i]);
-        text_console_opts[i] = NULL;
+        text_console_do_init(text_consoles[i], ds);
     }
 
     n_text_consoles = 0;
commit 4104833f51e9c2e7a3def0411e48159e77bf7906
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 23 13:42:52 2010 +0100

    add set_echo implementation for text consoles
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/console.c b/console.c
index 42c2ee3..60b80ee 100644
--- a/console.c
+++ b/console.c
@@ -137,6 +137,7 @@ struct TextConsole {
     TextAttributes t_attrib; /* currently active text attributes */
     TextCell *cells;
     int text_x[2], text_y[2], cursor_invalidate;
+    int echo;
 
     int update_x0;
     int update_y0;
@@ -1177,8 +1178,14 @@ void kbd_put_keysym(int keysym)
             *q++ = '\033';
             *q++ = '[';
             *q++ = keysym & 0xff;
+        } else if (s->echo && (keysym == '\r' || keysym == '\n')) {
+            console_puts(s->chr, (const uint8_t *) "\r", 1);
+            *q++ = '\n';
         } else {
-                *q++ = keysym;
+            *q++ = keysym;
+        }
+        if (s->echo) {
+            console_puts(s->chr, buf, q - buf);
         }
         if (s->chr->chr_read) {
             qemu_fifo_write(&s->out_fifo, buf, q - buf);
@@ -1432,6 +1439,13 @@ static int n_text_consoles;
 static CharDriverState *text_consoles[128];
 static QemuOpts *text_console_opts[128];
 
+static void text_console_set_echo(CharDriverState *chr, bool echo)
+{
+    TextConsole *s = chr->opaque;
+
+    s->echo = echo;
+}
+
 static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpts *opts)
 {
     TextConsole *s;
@@ -1532,6 +1546,7 @@ CharDriverState *text_console_init(QemuOpts *opts)
     s->g_width = width;
     s->g_height = height;
     chr->opaque = s;
+    chr->chr_set_echo = text_console_set_echo;
     return chr;
 }
 
commit 491e114a953d746b5787e72516d052aef0b67bc4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 23 13:42:51 2010 +0100

    create TextConsole together with the CharDeviceState
    
    A nicer solution would be to get rid of the opaque pointer and
    use containment, but it would also be a much bigger patch.
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/console.c b/console.c
index c1728b1..42c2ee3 100644
--- a/console.c
+++ b/console.c
@@ -1435,35 +1435,13 @@ static QemuOpts *text_console_opts[128];
 static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpts *opts)
 {
     TextConsole *s;
-    unsigned width;
-    unsigned height;
     static int color_inited;
 
-    width = qemu_opt_get_number(opts, "width", 0);
-    if (width == 0)
-        width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH;
-
-    height = qemu_opt_get_number(opts, "height", 0);
-    if (height == 0)
-        height = qemu_opt_get_number(opts, "rows", 0) * FONT_HEIGHT;
-
-    if (width == 0 || height == 0) {
-        s = new_console(ds, TEXT_CONSOLE);
-        width = ds_get_width(s->ds);
-        height = ds_get_height(s->ds);
-    } else {
-        s = new_console(ds, TEXT_CONSOLE_FIXED_SIZE);
-    }
+    s = chr->opaque;
 
-    if (!s) {
-        free(chr);
-        return;
-    }
-    chr->opaque = s;
     chr->chr_write = console_puts;
     chr->chr_send_event = console_send_event;
 
-    s->chr = chr;
     s->out_fifo.buf = s->out_fifo_buf;
     s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
     s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
@@ -1478,8 +1456,10 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpt
     s->total_height = DEFAULT_BACKSCROLL;
     s->x = 0;
     s->y = 0;
-    s->g_width = width;
-    s->g_height = height;
+    if (s->console_type == TEXT_CONSOLE) {
+        s->g_width = ds_get_width(s->ds);
+        s->g_height = ds_get_height(s->ds);
+    }
 
     s->hw_invalidate = text_console_invalidate;
     s->hw_text_update = text_console_update;
@@ -1515,6 +1495,9 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpt
 CharDriverState *text_console_init(QemuOpts *opts)
 {
     CharDriverState *chr;
+    TextConsole *s;
+    unsigned width;
+    unsigned height;
 
     chr = qemu_mallocz(sizeof(CharDriverState));
 
@@ -1526,6 +1509,29 @@ CharDriverState *text_console_init(QemuOpts *opts)
     text_console_opts[n_text_consoles] = opts;
     n_text_consoles++;
 
+    width = qemu_opt_get_number(opts, "width", 0);
+    if (width == 0)
+        width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH;
+
+    height = qemu_opt_get_number(opts, "height", 0);
+    if (height == 0)
+        height = qemu_opt_get_number(opts, "rows", 0) * FONT_HEIGHT;
+
+    if (width == 0 || height == 0) {
+        s = new_console(NULL, TEXT_CONSOLE);
+    } else {
+        s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE);
+    }
+
+    if (!s) {
+        free(chr);
+        return NULL;
+    }
+
+    s->chr = chr;
+    s->g_width = width;
+    s->g_height = height;
+    chr->opaque = s;
     return chr;
 }
 
commit bb002513a9bd2bff169c3d431a8f00c5b2e3aa99
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 23 13:42:50 2010 +0100

    add set_echo implementation for qemu_chr_stdio
    
    This also requires moving QemuOpts out of term_init.
    
    Clearing ISIG is independent of whether echo is enabled or disabled.
    
    Signed-off-by: Paolo Bonzini <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 a6ea516..bb0c32d 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -716,6 +716,7 @@ static void stdio_read(void *opaque)
 /* init terminal so that we can grab keys */
 static struct termios oldtty;
 static int old_fd0_flags;
+static bool stdio_allow_signal;
 
 static void term_exit(void)
 {
@@ -723,22 +724,24 @@ static void term_exit(void)
     fcntl(0, F_SETFL, old_fd0_flags);
 }
 
-static void term_init(QemuOpts *opts)
+static void qemu_chr_set_echo_stdio(CharDriverState *chr, bool echo)
 {
     struct termios tty;
 
     tty = oldtty;
-    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+    if (!echo) {
+        tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
                           |INLCR|IGNCR|ICRNL|IXON);
-    tty.c_oflag |= OPOST;
-    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+        tty.c_oflag |= OPOST;
+        tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+        tty.c_cflag &= ~(CSIZE|PARENB);
+        tty.c_cflag |= CS8;
+        tty.c_cc[VMIN] = 1;
+        tty.c_cc[VTIME] = 0;
+    }
     /* if graphical mode, we allow Ctrl-C handling */
-    if (!qemu_opt_get_bool(opts, "signal", display_type != DT_NOGRAPHIC))
+    if (!stdio_allow_signal)
         tty.c_lflag &= ~ISIG;
-    tty.c_cflag &= ~(CSIZE|PARENB);
-    tty.c_cflag |= CS8;
-    tty.c_cc[VMIN] = 1;
-    tty.c_cc[VTIME] = 0;
 
     tcsetattr (0, TCSANOW, &tty);
 }
@@ -766,9 +769,12 @@ static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
 
     chr = qemu_chr_open_fd(0, 1);
     chr->chr_close = qemu_chr_close_stdio;
+    chr->chr_set_echo = qemu_chr_set_echo_stdio;
     qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr);
     stdio_nb_clients++;
-    term_init(opts);
+    stdio_allow_signal = qemu_opt_get_bool(opts, "signal",
+                                           display_type != DT_NOGRAPHIC);
+    qemu_chr_set_echo(chr, false);
 
     return chr;
 }
commit 0369364be871f9c4b4429a69ddcd2ba21be34ea3
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 23 13:42:49 2010 +0100

    move atexit(term_exit) and O_NONBLOCK to qemu_chr_open_stdio
    
    In the next patch, term_init will be changed to enable or disable
    echo at will.  Move extraneous stuff out of it.
    
    Signed-off-by: Paolo Bonzini <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 b95cfdc..a6ea516 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -716,7 +716,6 @@ static void stdio_read(void *opaque)
 /* init terminal so that we can grab keys */
 static struct termios oldtty;
 static int old_fd0_flags;
-static int term_atexit_done;
 
 static void term_exit(void)
 {
@@ -728,10 +727,7 @@ static void term_init(QemuOpts *opts)
 {
     struct termios tty;
 
-    tcgetattr (0, &tty);
-    oldtty = tty;
-    old_fd0_flags = fcntl(0, F_GETFL);
-
+    tty = oldtty;
     tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
                           |INLCR|IGNCR|ICRNL|IXON);
     tty.c_oflag |= OPOST;
@@ -745,11 +741,6 @@ static void term_init(QemuOpts *opts)
     tty.c_cc[VTIME] = 0;
 
     tcsetattr (0, TCSANOW, &tty);
-
-    if (!term_atexit_done++)
-        atexit(term_exit);
-
-    fcntl(0, F_SETFL, O_NONBLOCK);
 }
 
 static void qemu_chr_close_stdio(struct CharDriverState *chr)
@@ -766,6 +757,13 @@ static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
 
     if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
         return NULL;
+    if (stdio_nb_clients == 0) {
+        old_fd0_flags = fcntl(0, F_GETFL);
+        tcgetattr (0, &oldtty);
+        fcntl(0, F_SETFL, O_NONBLOCK);
+        atexit(term_exit);
+    }
+
     chr = qemu_chr_open_fd(0, 1);
     chr->chr_close = qemu_chr_close_stdio;
     qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr);
commit c48855e1404e9b5857e07b7839f806fa98b4abdc
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 23 13:42:48 2010 +0100

    add qemu_chr_set_echo
    
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/monitor.c b/monitor.c
index 34c347c..7fc311d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -5175,6 +5175,7 @@ void monitor_init(CharDriverState *chr, int flags)
         /* Control mode requires special handlers */
         qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
                               monitor_control_event, mon);
+        qemu_chr_set_echo(chr, true);
     } else {
         qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
                               monitor_event, mon);
diff --git a/qemu-char.c b/qemu-char.c
index b570d60..b95cfdc 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2558,6 +2558,13 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*i
     return chr;
 }
 
+void qemu_chr_set_echo(struct CharDriverState *chr, bool echo)
+{
+    if (chr->chr_set_echo) {
+        chr->chr_set_echo(chr, echo);
+    }
+}
+
 void qemu_chr_close(CharDriverState *chr)
 {
     QTAILQ_REMOVE(&chardevs, chr, next);
diff --git a/qemu-char.h b/qemu-char.h
index e6ee6c4..56d9954 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -64,6 +64,7 @@ struct CharDriverState {
     void (*chr_send_event)(struct CharDriverState *chr, int event);
     void (*chr_close)(struct CharDriverState *chr);
     void (*chr_accept_input)(struct CharDriverState *chr);
+    void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
     void *opaque;
     QEMUBH *bh;
     char *label;
@@ -76,6 +77,7 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
 CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
                                     void (*init)(struct CharDriverState *s));
 CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s));
+void qemu_chr_set_echo(struct CharDriverState *chr, bool echo);
 void qemu_chr_close(CharDriverState *chr);
 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
     GCC_FMT_ATTR(2, 3);
commit d55dbc3acdaf92b42c7fd077c8b6c1392131c043
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Thu Dec 23 13:42:47 2010 +0100

    remove broken code for tty
    
    This code is taking the settings for a serial port and moving it to
    fd 0 when qemu exits.  This is likely just cut-and-paste, rip it.
    
    Signed-off-by: Paolo Bonzini <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 acc7130..b570d60 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1013,9 +1013,6 @@ static void tty_serial_init(int fd, int speed,
            speed, parity, data_bits, stop_bits);
 #endif
     tcgetattr (fd, &tty);
-    if (!term_atexit_done) {
-        oldtty = tty;
-    }
 
 #define check_speed(val) if (speed <= val) { spd = B##val; break; }
     speed = speed * 10 / 11;
@@ -1187,11 +1184,6 @@ static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg)
     return 0;
 }
 
-static void tty_exit(void)
-{
-    tcsetattr(0, TCSANOW, &oldtty);
-}
-
 static void qemu_chr_close_tty(CharDriverState *chr)
 {
     FDCharDriver *s = chr->opaque;
@@ -1226,8 +1218,6 @@ static CharDriverState *qemu_chr_open_tty(QemuOpts *opts)
     }
     chr->chr_ioctl = tty_serial_ioctl;
     chr->chr_close = qemu_chr_close_tty;
-    if (!term_atexit_done++)
-        atexit(tty_exit);
     return chr;
 }
 #else  /* ! __linux__ && ! __sun__ */
commit b3a98367eec7b2d87acca54ef5e4de3b0e0a7ed5
Merge: 9363ee3... c5999bf...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Feb 1 15:23:24 2011 -0600

    Merge remote branch 'qemu-kvm/uq/master' into staging
    
    aliguori: fix build with !defined(KVM_CAP_ASYNC_PF)
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --cc target-i386/kvm.c
index 7dfc357,8e8880a..05010bb
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@@ -170,14 -160,15 +160,17 @@@ struct kvm_para_features 
  
  static int get_para_features(CPUState *env)
  {
-         int i, features = 0;
+     int i, features = 0;
  
-         for (i = 0; i < ARRAY_SIZE(para_features) - 1; i++) {
-                 if (kvm_check_extension(env->kvm_state, para_features[i].cap))
-                         features |= (1 << para_features[i].feature);
+     for (i = 0; i < ARRAY_SIZE(para_features) - 1; i++) {
+         if (kvm_check_extension(env->kvm_state, para_features[i].cap)) {
+             features |= (1 << para_features[i].feature);
          }
- 
-         return features;
+     }
++#ifdef KVM_CAP_ASYNC_PF
+     has_msr_async_pf_en = features & (1 << KVM_FEATURE_ASYNC_PF);
++#endif
+     return features;
  }
  #endif
  
commit 9363ee31ab53fc0fd39fbe5936d9c00a2f4e54a4
Merge: cfb41c8... cbcc633...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Feb 1 15:22:48 2011 -0600

    Merge remote branch 'spice/spice.v29.pull' into staging
    
    Conflicts:
    	trace-events

diff --cc trace-events
index c75a7a9,ed754f5..e6138ea
--- a/trace-events
+++ b/trace-events
@@@ -225,26 -225,8 +225,32 @@@ disable qed_aio_write_prefill(void *s, 
  disable qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64""
  disable qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu"
  
 +# hw/grlib_gptimer.c
 +disable grlib_gptimer_enable(int id, uint32_t count) "timer:%d set count 0x%x and run"
 +disable grlib_gptimer_disabled(int id, uint32_t config) "timer:%d Timer disable config 0x%x"
 +disable grlib_gptimer_restart(int id, uint32_t reload) "timer:%d reload val: 0x%x"
 +disable grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) "scaler:0x%x freq: 0x%x"
 +disable grlib_gptimer_hit(int id) "timer:%d HIT"
 +disable grlib_gptimer_readl(int id, const char *s, uint32_t val) "timer:%d %s 0x%x"
 +disable grlib_gptimer_writel(int id, const char *s, uint32_t val) "timer:%d %s 0x%x"
 +disable grlib_gptimer_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
 +
 +# hw/grlib_irqmp.c
 +disable grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uint32_t lvl1, uint32_t lvl2) "pend:0x%04x force:0x%04x mask:0x%04x lvl1:0x%04x lvl0:0x%04x\n"
 +disable grlib_irqmp_ack(int intno) "interrupt:%d"
 +disable grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d"
 +disable grlib_irqmp_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
 +
 +# hw/grlib_apbuart.c
 +disable grlib_apbuart_event(int event) "event:%d"
 +disable grlib_apbuart_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
 +
 +# hw/leon3.c
 +disable leon3_set_irq(int intno) "Set CPU IRQ %d"
 +disable leon3_reset_irq(int intno) "Reset CPU IRQ %d"
++
+ # spice-qemu-char.c
+ disable spice_vmc_write(ssize_t out, int len) "spice wrottn %lu of requested %zd"
+ disable spice_vmc_read(int bytes, int len) "spice read %lu of requested %zd"
+ disable spice_vmc_register_interface(void *scd) "spice vmc registered interface %p"
+ disable spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p"
commit cfb41c82ab9c468e599d3603ffcebeb81b6577ca
Merge: e54b7f5... ea87e95...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Feb 1 15:21:23 2011 -0600

    Merge remote branch 'spice/usb.5' into staging

commit e54b7f5256659dddaf6b5c021847859829d7ebd7
Merge: 1cd20f8... 37f95bf...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Feb 1 15:20:56 2011 -0600

    Merge remote branch 'amit/for-anthony' into staging

commit 1cd20f8bf0ecb9d1d1bd5e2ffab3b88835380c9b
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jan 31 14:27:36 2011 -0600

    vnc: Fix password expiration through 'change vnc ""' (v2)
    
    commit 52c18be9e99dabe295321153fda7fce9f76647ac introduced a regression in the
    change vnc password command that changed the behavior of setting the VNC
    password to an empty string from disabling login to disabling authentication.
    
    This commit refactors the code to eliminate this overloaded semantics in
    vnc_display_password and instead introduces the vnc_display_disable_login.   The
    monitor implementation then determines the behavior of an empty or missing
    string.
    
    Recently, a set_password command was added that allows both the Spice and VNC
    password to be set.  This command has not shown up in a release yet so the
    behavior is not yet defined.
    
    This patch proposes that an empty password be treated as an empty password with
    no special handling.  For specifically disabling login, I believe a new command
    should be introduced instead of overloading semantics.
    
    I'm not sure how Spice handles this but I would recommend that we have Spice
    and VNC have consistent semantics here for the 0.14.0 release.
    
    Reported-by: Neil Wilson <neil at aldur.co.uk>
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    ---
    v1 -> v2
     - Add a proper return to make sure that login is really disabled instead of
       relying on the VNC server to treat empty passwords specially

diff --git a/console.h b/console.h
index 3157330..f4e4741 100644
--- a/console.h
+++ b/console.h
@@ -369,6 +369,7 @@ void vnc_display_init(DisplayState *ds);
 void vnc_display_close(DisplayState *ds);
 int vnc_display_open(DisplayState *ds, const char *display);
 int vnc_display_password(DisplayState *ds, const char *password);
+int vnc_display_disable_login(DisplayState *ds);
 int vnc_display_pw_expire(DisplayState *ds, time_t expires);
 void do_info_vnc_print(Monitor *mon, const QObject *data);
 void do_info_vnc(Monitor *mon, QObject **ret_data);
diff --git a/monitor.c b/monitor.c
index c5f54f4..64e41e3 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1018,6 +1018,14 @@ static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
 
 static int change_vnc_password(const char *password)
 {
+    if (!password || !password[0]) {
+        if (vnc_display_disable_login(NULL)) {
+            qerror_report(QERR_SET_PASSWD_FAILED);
+            return -1;
+        }
+        return 0;
+    }
+
     if (vnc_display_password(NULL, password) < 0) {
         qerror_report(QERR_SET_PASSWD_FAILED);
         return -1;
@@ -1117,6 +1125,8 @@ static int set_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
             qerror_report(QERR_INVALID_PARAMETER, "connected");
             return -1;
         }
+        /* Note that setting an empty password will not disable login through
+         * this interface. */
         rc = vnc_display_password(NULL, password);
         if (rc != 0) {
             qerror_report(QERR_SET_PASSWD_FAILED);
diff --git a/ui/vnc.c b/ui/vnc.c
index 495d6d6..8067b31 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2084,7 +2084,7 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
     unsigned char key[8];
     time_t now = time(NULL);
 
-    if (!vs->vd->password || !vs->vd->password[0]) {
+    if (!vs->vd->password) {
         VNC_DEBUG("No password configured on server");
         goto reject;
     }
@@ -2484,6 +2484,24 @@ void vnc_display_close(DisplayState *ds)
 #endif
 }
 
+int vnc_display_disable_login(DisplayState *ds)
+{
+    VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+
+    if (!vs) {
+        return -1;
+    }
+
+    if (vs->password) {
+        qemu_free(vs->password);
+    }
+
+    vs->password = NULL;
+    vs->auth = VNC_AUTH_VNC;
+
+    return 0;
+}
+
 int vnc_display_password(DisplayState *ds, const char *password)
 {
     VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
@@ -2492,19 +2510,18 @@ int vnc_display_password(DisplayState *ds, const char *password)
         return -1;
     }
 
+    if (!password) {
+        /* This is not the intention of this interface but err on the side
+           of being safe */
+        return vnc_display_disable_login(ds);
+    }
+
     if (vs->password) {
         qemu_free(vs->password);
         vs->password = NULL;
     }
-    if (password && password[0]) {
-        if (!(vs->password = qemu_strdup(password)))
-            return -1;
-        if (vs->auth == VNC_AUTH_NONE) {
-            vs->auth = VNC_AUTH_VNC;
-        }
-    } else {
-        vs->auth = VNC_AUTH_NONE;
-    }
+    vs->password = qemu_strdup(password);
+    vs->auth = VNC_AUTH_VNC;
 
     return 0;
 }
commit e321c34aa1d2560bea4d525af66417147467c515
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Tue Feb 1 15:54:52 2011 +0000

    linux-user: avoid gcc array overrun warning for sparc
    
    Suppress a gcc array bounds overrun warning when filling in the SPARC
    signal frame by adjusting our definition of the structure so that the
    fp and callers_pc membes are part of the ins[] array rather than
    separate fields; since qemu has no need to access the fields individually
    there is no need to follow the kernel's structure field naming exactly.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 0664770..b01bd64 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1817,9 +1817,10 @@ struct target_sigcontext {
 /* A Sparc stack frame */
 struct sparc_stackf {
         abi_ulong locals[8];
-        abi_ulong ins[6];
-        struct sparc_stackf *fp;
-        abi_ulong callers_pc;
+        abi_ulong ins[8];
+        /* It's simpler to treat fp and callers_pc as elements of ins[]
+         * since we never need to access them ourselves.
+         */
         char *structptr;
         abi_ulong xargs[6];
         abi_ulong xxargs[1];
commit c84a88d8cb298b6757ad01a12a8bbba66cb6eaa2
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Mon Jan 31 10:42:26 2011 +0000

    hw/slavio_intctl.c: fix gcc warning about array bounds overrun
    
    The Ubuntu 10.10 gcc for ARM complains that we might be overrunning
    the cpu_irqs[][] array: silence this by correcting the bounds on the
    loop. (In fact we would not have overrun the array because bit
    MAX_PILS in pil_pending and irl_out will always be 0.)
    
    Also add a comment about why the loop's lower bound is OK.
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index fd69354..a83e5b8 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -289,7 +289,12 @@ static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs)
         pil_pending |= (s->slaves[i].intreg_pending & CPU_SOFTIRQ_MASK) >> 16;
 
         if (set_irqs) {
-            for (j = MAX_PILS; j > 0; j--) {
+            /* Since there is not really an interrupt 0 (and pil_pending
+             * and irl_out bit zero are thus always zero) there is no need
+             * to do anything with cpu_irqs[i][0] and it is OK not to do
+             * the j=0 iteration of this loop.
+             */
+            for (j = MAX_PILS-1; j > 0; j--) {
                 if (pil_pending & (1 << j)) {
                     if (!(s->slaves[i].irl_out & (1 << j))) {
                         qemu_irq_raise(s->cpu_irqs[i][j]);
commit 60f356e86d66a4a22530ec7570f7582af602d200
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Mon Jan 31 11:36:54 2011 +0100

    SPARC: Fix Leon3 cache control
    
    The "leon3_cache_control_int" (op_helper.c) function is called within leon3.c
    which leads to segfault error with the global "env".
    
    Now cache control is a CPU feature and everything is handled in op_helper.c.
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/leon3.c b/hw/leon3.c
index 69d8f3b..919f49f 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -56,10 +56,9 @@ static void main_cpu_reset(void *opaque)
     env->npc    = s->entry + 4;
 }
 
-static void leon3_irq_ack(void *irq_manager, int intno)
+void leon3_irq_ack(void *irq_manager, int intno)
 {
     grlib_irqmp_ack((DeviceState *)irq_manager, intno);
-    leon3_cache_control_int();
 }
 
 static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
@@ -130,7 +129,7 @@ static void leon3_generic_hw_init(ram_addr_t  ram_size,
     /* Allocate IRQ manager */
     grlib_irqmp_create(0x80000200, env, &cpu_irqs, MAX_PILS, &leon3_set_pil_in);
 
-    env->qemu_irq_ack = leon3_irq_ack;
+    env->qemu_irq_ack = leon3_irq_manager;
 
     /* Allocate RAM */
     if ((uint64_t)ram_size > (1UL << 30)) {
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 6f5990b..320530e 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -268,6 +268,8 @@ typedef struct sparc_def_t {
 #define CPU_FEATURE_GL           (1 << 13)
 #define CPU_FEATURE_TA0_SHUTDOWN (1 << 14) /* Shutdown on "ta 0x0" */
 #define CPU_FEATURE_ASR17        (1 << 15)
+#define CPU_FEATURE_CACHE_CTRL   (1 << 16)
+
 #ifndef TARGET_SPARC64
 #define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP |  \
                               CPU_FEATURE_MUL | CPU_FEATURE_DIV |     \
@@ -476,12 +478,14 @@ void cpu_put_cwp64(CPUState *env1, int cwp);
 int cpu_cwp_inc(CPUState *env1, int cwp);
 int cpu_cwp_dec(CPUState *env1, int cwp);
 void cpu_set_cwp(CPUState *env1, int new_cwp);
-
-void leon3_cache_control_int(void);
+void leon3_irq_manager(void *irq_manager, int intno);
 
 /* sun4m.c, sun4u.c */
 void cpu_check_irqs(CPUSPARCState *env);
 
+/* leon3.c */
+void leon3_irq_ack(void *irq_manager, int intno);
+
 #if defined (TARGET_SPARC64)
 
 static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 2f3d1e6..b2d4d70 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -1289,7 +1289,7 @@ static const sparc_def_t sparc_defs[] = {
         .mmu_trcr_mask = 0xffffffff,
         .nwindows = 8,
         .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
-        CPU_FEATURE_ASR17,
+        CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
     },
 #endif
 };
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index d3e1b63..854f168 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -1653,7 +1653,7 @@ static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
 
 /* Leon3 cache control */
 
-void leon3_cache_control_int(void)
+static void leon3_cache_control_int(void)
 {
     uint32_t state = 0;
 
@@ -1741,11 +1741,17 @@ static uint64_t leon3_cache_control_ld(target_ulong addr, int size)
         DPRINTF_CACHE_CONTROL("read unknown register %08x\n", addr);
         break;
     };
-    DPRINTF_CACHE_CONTROL("st addr:%08x, ret:%" PRIx64 ", size:%d\n",
+    DPRINTF_CACHE_CONTROL("ld addr:%08x, ret:0x%" PRIx64 ", size:%d\n",
                           addr, ret, size);
     return ret;
 }
 
+void leon3_irq_manager(void *irq_manager, int intno)
+{
+    leon3_irq_ack(irq_manager, intno);
+    leon3_cache_control_int();
+}
+
 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
 {
     uint64_t ret = 0;
@@ -1760,7 +1766,9 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
         case 0x00:          /* Leon3 Cache Control */
         case 0x08:          /* Leon3 Instruction Cache config */
         case 0x0C:          /* Leon3 Date Cache config */
-            ret = leon3_cache_control_ld(addr, size);
+            if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
+                ret = leon3_cache_control_ld(addr, size);
+            }
             break;
         case 0x01c00a00: /* MXCC control register */
             if (size == 8)
@@ -1994,7 +2002,9 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
         case 0x00:          /* Leon3 Cache Control */
         case 0x08:          /* Leon3 Instruction Cache config */
         case 0x0C:          /* Leon3 Date Cache config */
-            leon3_cache_control_st(addr, val, size);
+            if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
+                leon3_cache_control_st(addr, val, size);
+            }
             break;
 
         case 0x01c00000: /* MXCC stream data register 0 */
commit 2685d2961b51437d0c7bc71f4ed7c320f6cbd010
Merge: 319ae52... 4c90051...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jan 31 12:07:17 2011 -0600

    Merge remote branch 'mst/for_anthony' into staging

commit 319ae529b8d55ea60b1036809aaab2130048d0e1
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 28 11:21:46 2011 +0100

    blockdev: Fix drive_add for drives without media
    
    Watch this:
    
        (qemu) drive_add 0 if=none
        (qemu) info block
        none0: type=hd removable=0 [not inserted]
        (qemu) drive_del none0
        Segmentation fault (core dumped)
    
    add_init_drive() is confused about drive_init()'s failure modes, and
    cleans up when it shouldn't.  This leaves the DriveInfo with member
    opts dangling.  drive_del attempts to free it, and dies.
    
    drive_init() behaves as follows:
    
    * If it created a drive with media, it returns its DriveInfo.
    
    * If it created a drive without media, it clears *fatal_error and
      returns NULL.
    
    * If it couldn't create a drive, it sets *fatal_error and returns
      NULL.
    
    Of its three callers:
    
    * drive_init_func() is correct.
    
    * usb_msd_init() assumes drive_init() failed when it returns NULL.
      This is correct only because it always passes option "file", and
      "drive without media" can't happen then.
    
    * add_init_drive() assumes drive_init() failed when it returns NULL.
      This is incorrect.
    
    Clean up drive_init() to return NULL on failure and only on failure.
    Drop its parameter fatal_error.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 4b2145c..1c56da0 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -203,7 +203,7 @@ static int parse_block_error_action(const char *buf, int is_read)
     }
 }
 
-DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
+DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
 {
     const char *buf;
     const char *file = NULL;
@@ -225,8 +225,6 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
     int snapshot = 0;
     int ret;
 
-    *fatal_error = 1;
-
     translation = BIOS_ATA_TRANSLATION_AUTO;
 
     if (default_to_scsi) {
@@ -499,8 +497,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
         abort();
     }
     if (!file || !*file) {
-        *fatal_error = 0;
-        return NULL;
+        return dinfo;
     }
     if (snapshot) {
         /* always use cache=unsafe with snapshot */
@@ -529,7 +526,6 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
 
     if (bdrv_key_required(dinfo->bdrv))
         autostart = 0;
-    *fatal_error = 0;
     return dinfo;
 }
 
diff --git a/blockdev.h b/blockdev.h
index e5d8c56..84e462a 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -48,7 +48,7 @@ DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
 QemuOpts *drive_def(const char *optstr);
 QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
                     const char *optstr);
-DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi, int *fatal_error);
+DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi);
 
 /* device-hotplug */
 
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index 95a6372..8b2ed7a 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -29,7 +29,6 @@
 
 DriveInfo *add_init_drive(const char *optstr)
 {
-    int fatal_error;
     DriveInfo *dinfo;
     QemuOpts *opts;
 
@@ -37,7 +36,7 @@ DriveInfo *add_init_drive(const char *optstr)
     if (!opts)
         return NULL;
 
-    dinfo = drive_init(opts, current_machine->use_scsi, &fatal_error);
+    dinfo = drive_init(opts, current_machine->use_scsi);
     if (!dinfo) {
         qemu_opts_del(opts);
         return NULL;
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 11722c7..97d1e4a 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -542,7 +542,6 @@ static USBDevice *usb_msd_init(const char *filename)
     QemuOpts *opts;
     DriveInfo *dinfo;
     USBDevice *dev;
-    int fatal_error;
     const char *p1;
     char fmt[32];
 
@@ -572,7 +571,7 @@ static USBDevice *usb_msd_init(const char *filename)
     qemu_opt_set(opts, "if", "none");
 
     /* create host drive */
-    dinfo = drive_init(opts, 0, &fatal_error);
+    dinfo = drive_init(opts, 0);
     if (!dinfo) {
         qemu_opts_del(opts);
         return NULL;
diff --git a/vl.c b/vl.c
index f86724f..ce5708b 100644
--- a/vl.c
+++ b/vl.c
@@ -631,13 +631,8 @@ static int bt_parse(const char *opt)
 static int drive_init_func(QemuOpts *opts, void *opaque)
 {
     int *use_scsi = opaque;
-    int fatal_error = 0;
 
-    if (drive_init(opts, *use_scsi, &fatal_error) == NULL) {
-        if (fatal_error)
-            return 1;
-    }
-    return 0;
+    return drive_init(opts, *use_scsi) == NULL;
 }
 
 static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
@@ -666,7 +661,7 @@ static void default_drive(int enable, int snapshot, int use_scsi,
     if (snapshot) {
         drive_enable_snapshot(opts, NULL);
     }
-    if (drive_init_func(opts, &use_scsi)) {
+    if (!drive_init(opts, use_scsi)) {
         exit(1);
     }
 }
commit 5645b0f4f2185437d8df03810ce9c102cc4c90db
Author: Markus Armbruster <armbru at redhat.com>
Date:   Mon Jan 31 11:50:09 2011 +0100

    blockdev: Replace drive_add()'s fmt, ... by optstr parameter
    
    Let the callers build the optstr.  Only one wants to.  All the others
    become simpler, because they don't have to worry about escaping '%'.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 3f7b560..4b2145c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -93,17 +93,11 @@ QemuOpts *drive_def(const char *optstr)
 }
 
 QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
-                    const char *fmt, ...)
+                    const char *optstr)
 {
-    va_list ap;
-    char optstr[1024];
     QemuOpts *opts;
     char buf[32];
 
-    va_start(ap, fmt);
-    vsnprintf(optstr, sizeof(optstr), fmt, ap);
-    va_end(ap);
-
     opts = drive_def(optstr);
     if (!opts) {
         return NULL;
diff --git a/blockdev.h b/blockdev.h
index 18278cc..e5d8c56 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -47,10 +47,7 @@ DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
 
 QemuOpts *drive_def(const char *optstr);
 QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
-                    const char *fmt, ...) /*GCC_FMT_ATTR(4, 5)*/;
-    /* GCC_FMT_ATTR() commented out to avoid the (pretty useless)
-     * "zero-length gnu_printf format string" warning we insist to
-     * enable */
+                    const char *optstr);
 DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi, int *fatal_error);
 
 /* device-hotplug */
diff --git a/vl.c b/vl.c
index 99f5bfe..f86724f 100644
--- a/vl.c
+++ b/vl.c
@@ -621,7 +621,6 @@ static int bt_parse(const char *opt)
 /***********************************************************/
 /* QEMU Block devices */
 
-/* Any % in the following strings must be escaped as %% */
 #define HD_OPTS "media=disk"
 #define CDROM_OPTS "media=cdrom"
 #define FD_OPTS ""
@@ -2050,17 +2049,21 @@ int main(int argc, char **argv, char **envp)
                 initrd_filename = optarg;
                 break;
             case QEMU_OPTION_hda:
-                if (cyls == 0)
-                    hda_opts = drive_add(IF_DEFAULT, 0, optarg, HD_OPTS);
-                else
-                    hda_opts = drive_add(IF_DEFAULT, 0, optarg, HD_OPTS
-			     ",cyls=%d,heads=%d,secs=%d%s",
-                             cyls, heads, secs,
-                             translation == BIOS_ATA_TRANSLATION_LBA ?
+                {
+                    char buf[256];
+                    if (cyls == 0)
+                        snprintf(buf, sizeof(buf), "%s", HD_OPTS);
+                    else
+                        snprintf(buf, sizeof(buf),
+                                 "%s,cyls=%d,heads=%d,secs=%d%s",
+                                 HD_OPTS , cyls, heads, secs,
+                                 translation == BIOS_ATA_TRANSLATION_LBA ?
                                  ",trans=lba" :
-                             translation == BIOS_ATA_TRANSLATION_NONE ?
+                                 translation == BIOS_ATA_TRANSLATION_NONE ?
                                  ",trans=none" : "");
-                 break;
+                    drive_add(IF_DEFAULT, 0, optarg, buf);
+                    break;
+                }
             case QEMU_OPTION_hdb:
             case QEMU_OPTION_hdc:
             case QEMU_OPTION_hdd:
commit 4e5d9b578f5d5ffbf7ef7e26abed23a0548a853a
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 28 11:21:45 2011 +0100

    blockdev: Reject multiple definitions for the same drive
    
    We silently ignore multiple definitions for the same drive:
    
        $ qemu-system-x86_64 -nodefaults -vnc :1 -S -monitor stdio -drive if=ide,index=1,file=tmp.qcow2 -drive if=ide,index=1,file=nonexistant
        QEMU 0.13.50 monitor - type 'help' for more information
        (qemu) info block
        ide0-hd1: type=hd removable=0 file=tmp.qcow2 backing_file=tmp.img ro=0 drv=qcow2 encrypted=0
    
    With if=none, this can become quite confusing:
    
        $ qemu-system-x86_64 -nodefaults -vnc :1 -S -monitor stdio -drive if=none,index=1,file=tmp.qcow2,id=eins -drive if=none,index=1,file=nonexistant,id=zwei -device ide-drive,drive=eins -device ide-drive,drive=zwei
        qemu-system-x86_64: -device ide-drive,drive=zwei: Property 'ide-drive.drive' can't find value 'zwei'
    
    The second -device fails, because it refers to drive zwei, which got
    silently ignored.
    
    Make multiple drive definitions fail cleanly.
    
    Unfortunately, there's code that relies on multiple drive definitions
    being silently ignored: main() merrily adds default drives even when
    the user already defined these drives.  Fix that up.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 01228f6..3f7b560 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -429,11 +429,12 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
     }
 
     /*
-     * ignore multiple definitions
+     * catch multiple definitions
      */
 
     if (drive_get(type, bus_id, unit_id) != NULL) {
-        *fatal_error = 0;
+        error_report("drive with bus=%d, unit=%d (index=%d) exists",
+                     bus_id, unit_id, index);
         return NULL;
     }
 
diff --git a/vl.c b/vl.c
index 5399e33..99f5bfe 100644
--- a/vl.c
+++ b/vl.c
@@ -649,6 +649,29 @@ static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
     return 0;
 }
 
+static void default_drive(int enable, int snapshot, int use_scsi,
+                          BlockInterfaceType type, int index,
+                          const char *optstr)
+{
+    QemuOpts *opts;
+
+    if (type == IF_DEFAULT) {
+        type = use_scsi ? IF_SCSI : IF_IDE;
+    }
+
+    if (!enable || drive_get_by_index(type, index)) {
+        return;
+    }
+
+    opts = drive_add(type, index, NULL, optstr);
+    if (snapshot) {
+        drive_enable_snapshot(opts, NULL);
+    }
+    if (drive_init_func(opts, &use_scsi)) {
+        exit(1);
+    }
+}
+
 void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
 {
     boot_set_handler = func;
@@ -2893,27 +2916,19 @@ int main(int argc, char **argv, char **envp)
 
     blk_mig_init();
 
-    if (default_cdrom) {
-        /* we always create the cdrom drive, even if no disk is there */
-        drive_add(IF_DEFAULT, 2, NULL, CDROM_OPTS);
-    }
-
-    if (default_floppy) {
-        /* we always create at least one floppy */
-        drive_add(IF_FLOPPY, 0, NULL, FD_OPTS);
-    }
-
-    if (default_sdcard) {
-        /* we always create one sd slot, even if no card is in it */
-        drive_add(IF_SD, 0, NULL, SD_OPTS);
-    }
-
     /* open the virtual block devices */
     if (snapshot)
         qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, 0);
     if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func, &machine->use_scsi, 1) != 0)
         exit(1);
 
+    default_drive(default_cdrom, snapshot, machine->use_scsi,
+                  IF_DEFAULT, 2, CDROM_OPTS);
+    default_drive(default_floppy, snapshot, machine->use_scsi,
+                  IF_FLOPPY, 0, FD_OPTS);
+    default_drive(default_sdcard, snapshot, machine->use_scsi,
+                  IF_SD, 0, SD_OPTS);
+
     register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL,
                          ram_load, NULL);
 
commit f1bd51ac2b6e6ccd3d13dfd52c1c381a68bf261c
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 28 11:21:44 2011 +0100

    blockdev: New drive_get_by_index()
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index a42c5e4..01228f6 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -136,6 +136,13 @@ DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
     return NULL;
 }
 
+DriveInfo *drive_get_by_index(BlockInterfaceType type, int index)
+{
+    return drive_get(type,
+                     drive_index_to_bus_id(type, index),
+                     drive_index_to_unit_id(type, index));
+}
+
 int drive_get_max_bus(BlockInterfaceType type)
 {
     int max_bus;
diff --git a/blockdev.h b/blockdev.h
index 0c01e08..18278cc 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -39,6 +39,7 @@ struct DriveInfo {
 };
 
 DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
+DriveInfo *drive_get_by_index(BlockInterfaceType type, int index);
 int drive_get_max_bus(BlockInterfaceType type);
 DriveInfo *drive_get_next(BlockInterfaceType type);
 void drive_uninit(DriveInfo *dinfo);
commit 505a7fb1b1bfa732117d526a8d3a0f27741155d6
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 28 11:21:43 2011 +0100

    blockdev: Factor drive_index_to_{bus,unit}_id out of drive_init()
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 6d828f2..a42c5e4 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -75,6 +75,18 @@ void blockdev_auto_del(BlockDriverState *bs)
     }
 }
 
+static int drive_index_to_bus_id(BlockInterfaceType type, int index)
+{
+    int max_devs = if_max_devs[type];
+    return max_devs ? index / max_devs : 0;
+}
+
+static int drive_index_to_unit_id(BlockInterfaceType type, int index)
+{
+    int max_devs = if_max_devs[type];
+    return max_devs ? index % max_devs : index;
+}
+
 QemuOpts *drive_def(const char *optstr)
 {
     return qemu_opts_parse(qemu_find_opts("drive"), optstr, 0);
@@ -382,14 +394,8 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
             error_report("index cannot be used with bus and unit");
             return NULL;
         }
-        if (max_devs == 0)
-        {
-            unit_id = index;
-            bus_id = 0;
-        } else {
-            unit_id = index % max_devs;
-            bus_id = index / max_devs;
-        }
+        bus_id = drive_index_to_bus_id(type, index);
+        unit_id = drive_index_to_unit_id(type, index);
     }
 
     /* if user doesn't specify a unit_id,
commit 2292ddaeab3467c68efd9e07e17ca0c9fc510fdc
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 28 11:21:41 2011 +0100

    blockdev: Make drive_add() take explicit type, index parameters
    
    Before, type & index were hidden in printf-like fmt, ... parameters,
    which get expanded into an option string.  Rather inconvenient for
    uses later in this series.
    
    New IF_DEFAULT to ask for the machine's default interface.  Before,
    that was done by having no option "if" in the option string.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index fba53f9..6d828f2 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -75,20 +75,34 @@ void blockdev_auto_del(BlockDriverState *bs)
     }
 }
 
-QemuOpts *drive_add(const char *file, const char *fmt, ...)
+QemuOpts *drive_def(const char *optstr)
+{
+    return qemu_opts_parse(qemu_find_opts("drive"), optstr, 0);
+}
+
+QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
+                    const char *fmt, ...)
 {
     va_list ap;
     char optstr[1024];
     QemuOpts *opts;
+    char buf[32];
 
     va_start(ap, fmt);
     vsnprintf(optstr, sizeof(optstr), fmt, ap);
     va_end(ap);
 
-    opts = qemu_opts_parse(qemu_find_opts("drive"), optstr, 0);
+    opts = drive_def(optstr);
     if (!opts) {
         return NULL;
     }
+    if (type != IF_DEFAULT) {
+        qemu_opt_set(opts, "if", if_name[type]);
+    }
+    if (index >= 0) {
+        snprintf(buf, sizeof(buf), "%d", index);
+        qemu_opt_set(opts, "index", buf);
+    }
     if (file)
         qemu_opt_set(opts, "file", file);
     return opts;
@@ -473,7 +487,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
         if (devaddr)
             qemu_opt_set(opts, "addr", devaddr);
         break;
-    case IF_COUNT:
+    default:
         abort();
     }
     if (!file || !*file) {
diff --git a/blockdev.h b/blockdev.h
index cf8fc01..0c01e08 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -19,6 +19,7 @@ void blockdev_auto_del(BlockDriverState *bs);
 #define BLOCK_SERIAL_STRLEN 20
 
 typedef enum {
+    IF_DEFAULT = -1,            /* for use with drive_add() only */
     IF_NONE,
     IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
     IF_COUNT
@@ -43,7 +44,12 @@ DriveInfo *drive_get_next(BlockInterfaceType type);
 void drive_uninit(DriveInfo *dinfo);
 DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
 
-QemuOpts *drive_add(const char *file, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
+QemuOpts *drive_def(const char *optstr);
+QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
+                    const char *fmt, ...) /*GCC_FMT_ATTR(4, 5)*/;
+    /* GCC_FMT_ATTR() commented out to avoid the (pretty useless)
+     * "zero-length gnu_printf format string" warning we insist to
+     * enable */
 DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi, int *fatal_error);
 
 /* device-hotplug */
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index 9704e2f..95a6372 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -33,7 +33,7 @@ DriveInfo *add_init_drive(const char *optstr)
     DriveInfo *dinfo;
     QemuOpts *opts;
 
-    opts = drive_add(NULL, "%s", optstr);
+    opts = drive_def(optstr);
     if (!opts)
         return NULL;
 
diff --git a/vl.c b/vl.c
index 14255c4..5399e33 100644
--- a/vl.c
+++ b/vl.c
@@ -621,12 +621,13 @@ static int bt_parse(const char *opt)
 /***********************************************************/
 /* QEMU Block devices */
 
-#define HD_ALIAS "index=%d,media=disk"
-#define CDROM_ALIAS "index=2,media=cdrom"
-#define FD_ALIAS "index=%d,if=floppy"
-#define PFLASH_ALIAS "if=pflash"
-#define MTD_ALIAS "if=mtd"
-#define SD_ALIAS "index=0,if=sd"
+/* Any % in the following strings must be escaped as %% */
+#define HD_OPTS "media=disk"
+#define CDROM_OPTS "media=cdrom"
+#define FD_OPTS ""
+#define PFLASH_OPTS ""
+#define MTD_OPTS ""
+#define SD_OPTS ""
 
 static int drive_init_func(QemuOpts *opts, void *opaque)
 {
@@ -1987,7 +1988,7 @@ int main(int argc, char **argv, char **envp)
         if (optind >= argc)
             break;
         if (argv[optind][0] != '-') {
-	    hda_opts = drive_add(argv[optind++], HD_ALIAS, 0);
+	    hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS);
         } else {
             const QEMUOption *popt;
 
@@ -2027,11 +2028,11 @@ int main(int argc, char **argv, char **envp)
                 break;
             case QEMU_OPTION_hda:
                 if (cyls == 0)
-                    hda_opts = drive_add(optarg, HD_ALIAS, 0);
+                    hda_opts = drive_add(IF_DEFAULT, 0, optarg, HD_OPTS);
                 else
-                    hda_opts = drive_add(optarg, HD_ALIAS
+                    hda_opts = drive_add(IF_DEFAULT, 0, optarg, HD_OPTS
 			     ",cyls=%d,heads=%d,secs=%d%s",
-                             0, cyls, heads, secs,
+                             cyls, heads, secs,
                              translation == BIOS_ATA_TRANSLATION_LBA ?
                                  ",trans=lba" :
                              translation == BIOS_ATA_TRANSLATION_NONE ?
@@ -2040,10 +2041,11 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_hdb:
             case QEMU_OPTION_hdc:
             case QEMU_OPTION_hdd:
-                drive_add(optarg, HD_ALIAS, popt->index - QEMU_OPTION_hda);
+                drive_add(IF_DEFAULT, popt->index - QEMU_OPTION_hda, optarg,
+                          HD_OPTS);
                 break;
             case QEMU_OPTION_drive:
-                drive_add(NULL, "%s", optarg);
+                drive_def(optarg);
 	        break;
             case QEMU_OPTION_set:
                 if (qemu_set_option(optarg) != 0)
@@ -2054,13 +2056,13 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
 	        break;
             case QEMU_OPTION_mtdblock:
-                drive_add(optarg, MTD_ALIAS);
+                drive_add(IF_MTD, -1, optarg, MTD_OPTS);
                 break;
             case QEMU_OPTION_sd:
-                drive_add(optarg, SD_ALIAS);
+                drive_add(IF_SD, 0, optarg, SD_OPTS);
                 break;
             case QEMU_OPTION_pflash:
-                drive_add(optarg, PFLASH_ALIAS);
+                drive_add(IF_PFLASH, -1, optarg, PFLASH_OPTS);
                 break;
             case QEMU_OPTION_snapshot:
                 snapshot = 1;
@@ -2139,7 +2141,7 @@ int main(int argc, char **argv, char **envp)
                 kernel_cmdline = optarg;
                 break;
             case QEMU_OPTION_cdrom:
-                drive_add(optarg, CDROM_ALIAS);
+                drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS);
                 break;
             case QEMU_OPTION_boot:
                 {
@@ -2192,7 +2194,8 @@ int main(int argc, char **argv, char **envp)
                 break;
             case QEMU_OPTION_fda:
             case QEMU_OPTION_fdb:
-                drive_add(optarg, FD_ALIAS, popt->index - QEMU_OPTION_fda);
+                drive_add(IF_FLOPPY, popt->index - QEMU_OPTION_fda,
+                          optarg, FD_OPTS);
                 break;
             case QEMU_OPTION_no_fd_bootchk:
                 fd_bootchk = 0;
@@ -2892,17 +2895,17 @@ int main(int argc, char **argv, char **envp)
 
     if (default_cdrom) {
         /* we always create the cdrom drive, even if no disk is there */
-        drive_add(NULL, CDROM_ALIAS);
+        drive_add(IF_DEFAULT, 2, NULL, CDROM_OPTS);
     }
 
     if (default_floppy) {
         /* we always create at least one floppy */
-        drive_add(NULL, FD_ALIAS, 0);
+        drive_add(IF_FLOPPY, 0, NULL, FD_OPTS);
     }
 
     if (default_sdcard) {
         /* we always create one sd slot, even if no card is in it */
-        drive_add(NULL, SD_ALIAS);
+        drive_add(IF_SD, 0, NULL, SD_OPTS);
     }
 
     /* open the virtual block devices */
commit 27d6bf40edc346a61ade6d4c5d4f27f6b40acc81
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 28 11:21:40 2011 +0100

    blockdev: Fix regression in -drive if=scsi,index=N
    
    Before commit 622b520f, index=12 meant bus=1,unit=5.
    
    Since the commit, it means bus=0,unit=12.  The drive is created, but
    not the guest device.  That's because the controllers we use with
    if=scsi drives (lsi53c895a and esp) support only 7 units, and
    scsi_bus_legacy_handle_cmdline() ignores drives with unit numbers
    exceeding that limit.
    
    Changing the mapping of index to bus, unit is a regression.  Breaking
    -drive invocations that used to work just makes it worse.
    
    Revert the part of commit 622b520f that causes this, and clean up
    some.
    
    Note that the fix only affects if=scsi.  You can still put more than 7
    units on a SCSI bus with -device & friends.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 9c883ce..fba53f9 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -32,8 +32,22 @@ static const char *const if_name[IF_COUNT] = {
 };
 
 static const int if_max_devs[IF_COUNT] = {
-    [IF_IDE] = MAX_IDE_DEVS,
-    [IF_SCSI] = MAX_SCSI_DEVS,
+    /*
+     * Do not change these numbers!  They govern how drive option
+     * index maps to unit and bus.  That mapping is ABI.
+     *
+     * All controllers used to imlement if=T drives need to support
+     * if_max_devs[T] units, for any T with if_max_devs[T] != 0.
+     * Otherwise, some index values map to "impossible" bus, unit
+     * values.
+     *
+     * For instance, if you change [IF_SCSI] to 255, -drive
+     * if=scsi,index=12 no longer means bus=1,unit=5, but
+     * bus=0,unit=12.  With an lsi53c895a controller (7 units max),
+     * the drive can't be set up.  Regression.
+     */
+    [IF_IDE] = 2,
+    [IF_SCSI] = 7,
 };
 
 /*
diff --git a/blockdev.h b/blockdev.h
index 2cbbb87..cf8fc01 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -37,9 +37,6 @@ struct DriveInfo {
     QTAILQ_ENTRY(DriveInfo) next;
 };
 
-#define MAX_IDE_DEVS	2
-#define MAX_SCSI_DEVS	255
-
 DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
 int drive_get_max_bus(BlockInterfaceType type);
 DriveInfo *drive_get_next(BlockInterfaceType type);
diff --git a/hw/ide.h b/hw/ide.h
index 2b5ae7c..73fb550 100644
--- a/hw/ide.h
+++ b/hw/ide.h
@@ -4,6 +4,8 @@
 #include "isa.h"
 #include "pci.h"
 
+#define MAX_IDE_DEVS	2
+
 /* ide-isa.c */
 ISADevice *isa_ide_init(int iobase, int iobase2, int isairq,
                         DriveInfo *hd0, DriveInfo *hd1);
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 433171c..671b4df 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -70,7 +70,6 @@
 #include "monitor.h"
 #include "dma.h"
 #include "cpu-common.h"
-#include "blockdev.h"
 #include "internal.h"
 #include <hw/ide/pci.h>
 
diff --git a/hw/qdev.c b/hw/qdev.c
index 0c94fb2..c7fec44 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -29,7 +29,6 @@
 #include "qdev.h"
 #include "sysemu.h"
 #include "monitor.h"
-#include "blockdev.h"
 
 static int qdev_hotplug = 0;
 static bool qdev_hot_added = false;
diff --git a/hw/scsi.h b/hw/scsi.h
index 846fbba..d3b5d56 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -3,9 +3,10 @@
 
 #include "qdev.h"
 #include "block.h"
-#include "blockdev.h"
 #include "block_int.h"
 
+#define MAX_SCSI_DEVS	255
+
 #define SCSI_CMD_BUF_SIZE     16
 
 /* scsi-disk.c */
diff --git a/savevm.c b/savevm.c
index fcd8db4..4453217 100644
--- a/savevm.c
+++ b/savevm.c
@@ -78,7 +78,6 @@
 #include "sysemu.h"
 #include "qemu-timer.h"
 #include "qemu-char.h"
-#include "blockdev.h"
 #include "audio/audio.h"
 #include "migration.h"
 #include "qemu_socket.h"
commit 1960966d1b57628f730b66fe33cd2005846092e0
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 28 11:21:39 2011 +0100

    blockdev: Put BlockInterfaceType names and max_devs in tables
    
    Turns drive_init()'s lengthy conditional into a concise loop, and
    makes the data available elsewhere.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 699f312..9c883ce 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -19,6 +19,23 @@
 
 static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
 
+static const char *const if_name[IF_COUNT] = {
+    [IF_NONE] = "none",
+    [IF_IDE] = "ide",
+    [IF_SCSI] = "scsi",
+    [IF_FLOPPY] = "floppy",
+    [IF_PFLASH] = "pflash",
+    [IF_MTD] = "mtd",
+    [IF_SD] = "sd",
+    [IF_VIRTIO] = "virtio",
+    [IF_XEN] = "xen",
+};
+
+static const int if_max_devs[IF_COUNT] = {
+    [IF_IDE] = MAX_IDE_DEVS,
+    [IF_SCSI] = MAX_SCSI_DEVS,
+};
+
 /*
  * We automatically delete the drive when a device using it gets
  * unplugged.  Questionable feature, but we can't just drop it.
@@ -173,11 +190,9 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
 
     if (default_to_scsi) {
         type = IF_SCSI;
-        max_devs = MAX_SCSI_DEVS;
         pstrcpy(devname, sizeof(devname), "scsi");
     } else {
         type = IF_IDE;
-        max_devs = MAX_IDE_DEVS;
         pstrcpy(devname, sizeof(devname), "ide");
     }
     media = MEDIA_DISK;
@@ -199,38 +214,14 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
 
     if ((buf = qemu_opt_get(opts, "if")) != NULL) {
         pstrcpy(devname, sizeof(devname), buf);
-        if (!strcmp(buf, "ide")) {
-	    type = IF_IDE;
-            max_devs = MAX_IDE_DEVS;
-        } else if (!strcmp(buf, "scsi")) {
-	    type = IF_SCSI;
-            max_devs = MAX_SCSI_DEVS;
-        } else if (!strcmp(buf, "floppy")) {
-	    type = IF_FLOPPY;
-            max_devs = 0;
-        } else if (!strcmp(buf, "pflash")) {
-	    type = IF_PFLASH;
-            max_devs = 0;
-	} else if (!strcmp(buf, "mtd")) {
-	    type = IF_MTD;
-            max_devs = 0;
-	} else if (!strcmp(buf, "sd")) {
-	    type = IF_SD;
-            max_devs = 0;
-        } else if (!strcmp(buf, "virtio")) {
-            type = IF_VIRTIO;
-            max_devs = 0;
-	} else if (!strcmp(buf, "xen")) {
-	    type = IF_XEN;
-            max_devs = 0;
-	} else if (!strcmp(buf, "none")) {
-	    type = IF_NONE;
-            max_devs = 0;
-	} else {
+        for (type = 0; type < IF_COUNT && strcmp(buf, if_name[type]); type++)
+            ;
+        if (type == IF_COUNT) {
             error_report("unsupported bus type '%s'", buf);
             return NULL;
 	}
     }
+    max_devs = if_max_devs[type];
 
     if (cyls || heads || secs) {
         if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
commit 904ebffee5a7e7d246039ad5826195fe51ccf769
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 28 11:21:38 2011 +0100

    blockdev: Move BlockInterfaceType from qemu-common.h to blockdev.h
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.h b/blockdev.h
index 3ed6634..2cbbb87 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -18,6 +18,12 @@ void blockdev_auto_del(BlockDriverState *bs);
 
 #define BLOCK_SERIAL_STRLEN 20
 
+typedef enum {
+    IF_NONE,
+    IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
+    IF_COUNT
+} BlockInterfaceType;
+
 struct DriveInfo {
     BlockDriverState *bdrv;
     char *id;
diff --git a/qemu-common.h b/qemu-common.h
index 79e1149..c7ff280 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -274,12 +274,6 @@ typedef struct VirtIODevice VirtIODevice;
 
 typedef uint64_t pcibus_t;
 
-typedef enum {
-    IF_NONE,
-    IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
-    IF_COUNT
-} BlockInterfaceType;
-
 void cpu_exec_init_all(unsigned long tb_size);
 
 /* CPU save/load.  */
commit 13839974d14701626a2f9dcc5f8cf65783d51c11
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 28 11:21:37 2011 +0100

    blockdev: New drive_get_next(), replacing qdev_init_bdrv()
    
    qdev_init_bdrv() doesn't belong into qdev.c; it's about drives, not
    qdevs.  Rename to drive_get_next, move to blockdev.c, drop the bogus
    DeviceState argument, and return DriveInfo instead of
    BlockDriverState.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index e48d33d..699f312 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -93,6 +93,16 @@ int drive_get_max_bus(BlockInterfaceType type)
     return max_bus;
 }
 
+/* Get a block device.  This should only be used for single-drive devices
+   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
+   appropriate bus.  */
+DriveInfo *drive_get_next(BlockInterfaceType type)
+{
+    static int next_block_unit[IF_COUNT];
+
+    return drive_get(type, 0, next_block_unit[type]++);
+}
+
 DriveInfo *drive_get_by_blockdev(BlockDriverState *bs)
 {
     DriveInfo *dinfo;
diff --git a/blockdev.h b/blockdev.h
index b8a88bf..3ed6634 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -36,6 +36,7 @@ struct DriveInfo {
 
 DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
 int drive_get_max_bus(BlockInterfaceType type);
+DriveInfo *drive_get_next(BlockInterfaceType type);
 void drive_uninit(DriveInfo *dinfo);
 DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
 
diff --git a/hw/pl181.c b/hw/pl181.c
index 3e5f92f..36d9d02 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -7,6 +7,7 @@
  * This code is licenced under the GPL.
  */
 
+#include "blockdev.h"
 #include "sysbus.h"
 #include "sd.h"
 
@@ -449,15 +450,15 @@ static int pl181_init(SysBusDevice *dev)
 {
     int iomemtype;
     pl181_state *s = FROM_SYSBUS(pl181_state, dev);
-    BlockDriverState *bd;
+    DriveInfo *dinfo;
 
     iomemtype = cpu_register_io_memory(pl181_readfn, pl181_writefn, s,
                                        DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio(dev, 0x1000, iomemtype);
     sysbus_init_irq(dev, &s->irq[0]);
     sysbus_init_irq(dev, &s->irq[1]);
-    bd = qdev_init_bdrv(&dev->qdev, IF_SD);
-    s->card = sd_init(bd, 0);
+    dinfo = drive_get_next(IF_SD);
+    s->card = sd_init(dinfo ? dinfo->bdrv : NULL, 0);
     qemu_register_reset(pl181_reset, s);
     pl181_reset(s);
     /* ??? Save/restore.  */
diff --git a/hw/qdev.c b/hw/qdev.c
index 5b8d374..0c94fb2 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -458,20 +458,6 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
     }
 }
 
-static int next_block_unit[IF_COUNT];
-
-/* Get a block device.  This should only be used for single-drive devices
-   (e.g. SD/Floppy/MTD).  Multi-disk devices (scsi/ide) should use the
-   appropriate bus.  */
-BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
-{
-    int unit = next_block_unit[type]++;
-    DriveInfo *dinfo;
-
-    dinfo = drive_get(type, 0, unit);
-    return dinfo ? dinfo->bdrv : NULL;
-}
-
 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
 {
     BusState *bus;
diff --git a/hw/qdev.h b/hw/qdev.h
index e520aaa..9808f85 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -137,8 +137,6 @@ bool qdev_machine_modified(void);
 qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
 void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
 
-BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type);
-
 BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
 
 /*** Device API.  ***/
diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c
index a1a63b2..fb4b649 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -7,6 +7,7 @@
  * This code is licenced under the GNU GPL v2.
  */
 
+#include "blockdev.h"
 #include "ssi.h"
 #include "sd.h"
 
@@ -231,11 +232,11 @@ static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
 static int ssi_sd_init(SSISlave *dev)
 {
     ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, dev);
-    BlockDriverState *bs;
+    DriveInfo *dinfo;
 
     s->mode = SSI_SD_CMD;
-    bs = qdev_init_bdrv(&dev->qdev, IF_SD);
-    s->sd = sd_init(bs, 1);
+    dinfo = drive_get_next(IF_SD);
+    s->sd = sd_init(dinfo ? dinfo->bdrv : NULL, 1);
     register_savevm(&dev->qdev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
     return 0;
 }
commit 1869a65385e9d81f490b4203dd070cc49b7749c9
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Jan 29 08:19:15 2011 +0000

    qcow2-refcount: remove write-only variables
    
    Variables l2_modified and l2_size are not really used, remove them.
    Spotted by GCC 4.6.0:
      CC    block/qcow2-refcount.o
    /src/qemu/block/qcow2-refcount.c: In function 'qcow2_update_snapshot_refcount':
    /src/qemu/block/qcow2-refcount.c:708:37: error: variable 'l2_modified' set but not used [-Werror=unused-but-set-variable]
    /src/qemu/block/qcow2-refcount.c:708:9: error: variable 'l2_size' set but not used [-Werror=unused-but-set-variable]
    
    CC: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index e37e226..915d85a 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -705,7 +705,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
     BDRVQcowState *s = bs->opaque;
     uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated;
     int64_t old_offset, old_l2_offset;
-    int l2_size, i, j, l1_modified, l2_modified, nb_csectors, refcount;
+    int i, j, l1_modified, nb_csectors, refcount;
     int ret;
 
     l2_table = NULL;
@@ -729,14 +729,12 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
         l1_allocated = 0;
     }
 
-    l2_size = s->l2_size * sizeof(uint64_t);
     l1_modified = 0;
     for(i = 0; i < l1_size; i++) {
         l2_offset = l1_table[i];
         if (l2_offset) {
             old_l2_offset = l2_offset;
             l2_offset &= ~QCOW_OFLAG_COPIED;
-            l2_modified = 0;
 
             ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset,
                 (void**) &l2_table);
@@ -788,7 +786,6 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                                 s->refcount_block_cache);
                         }
                         l2_table[j] = cpu_to_be64(offset);
-                        l2_modified = 1;
                         qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
                     }
                 }
commit 31e1ea3ee7d05ab1aa134fe07a8f33b42417641f
Author: Markus Armbruster <armbru at redhat.com>
Date:   Fri Jan 28 11:21:36 2011 +0100

    scsi hotplug: Set DriveInfo member bus correctly
    
    drive_init() picks the first free bus and unit number, unless the user
    specifies them.
    
    This isn't a good fit for the drive_add monitor command, because there
    we specify the controller by PCI address instead of using bus number
    set by drive_init().
    
    scsi_hot_add() takes care to replace the unit number set by
    drive_init() by the real one, but it neglects to replace the bus
    number.  Thus, bus/unit in DriveInfo may be bogus.  Affects
    drive_get() and drive_get_max_bus().  I'm not aware of anything bad
    happening because of that; looks like by the time we're hot-plugging,
    the two functions aren't used anymore.  Fix it anyway.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 270a982..b6dcbda 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -90,6 +90,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
      * specified).
      */
     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);
     if (!scsidev) {
         return -1;
commit 1b40bbd13a2d37dcd88763b84d01ec68bc96ff14
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Jan 28 15:57:39 2011 +0100

    raw-win32: Fix bdrv_flush return value
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/raw-win32.c b/block/raw-win32.c
index 06c9710..c204a80 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -153,7 +153,7 @@ static int raw_flush(BlockDriverState *bs)
     int ret;
 
     ret = FlushFileBuffers(s->hfile);
-    if (ret != 0) {
+    if (ret == 0) {
         return -EIO;
     }
 
commit 0d09c7970063ecdabdc2841ffa32e1cf3e032336
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Fri Jan 28 17:11:59 2011 +0000

    qed: Images with backing file do not require QED_F_NEED_CHECK
    
    The consistency check on open is necessary in order to fix inconsistent
    table offsets left as a result of a crash mid-operation.  Images with a
    backing file actually flush before updating table offsets and are
    therefore guaranteed to be consistent.  Do not mark these images dirty.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qed.c b/block/qed.c
index a46f9ef..3273448 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -977,6 +977,19 @@ static void qed_aio_write_prefill(void *opaque, int ret)
 }
 
 /**
+ * Check if the QED_F_NEED_CHECK bit should be set during allocating write
+ */
+static bool qed_should_set_need_check(BDRVQEDState *s)
+{
+    /* The flush before L2 update path ensures consistency */
+    if (s->bs->backing_hd) {
+        return false;
+    }
+
+    return !(s->header.features & QED_F_NEED_CHECK);
+}
+
+/**
  * Write new data cluster
  *
  * @acb:        Write request
@@ -1001,15 +1014,12 @@ static void qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
     acb->cur_cluster = qed_alloc_clusters(s, acb->cur_nclusters);
     qemu_iovec_copy(&acb->cur_qiov, acb->qiov, acb->qiov_offset, len);
 
-    /* Write new cluster if the image is already marked dirty */
-    if (s->header.features & QED_F_NEED_CHECK) {
+    if (qed_should_set_need_check(s)) {
+        s->header.features |= QED_F_NEED_CHECK;
+        qed_write_header(s, qed_aio_write_prefill, acb);
+    } else {
         qed_aio_write_prefill(acb, 0);
-        return;
     }
-
-    /* Mark the image dirty before writing the new cluster */
-    s->header.features |= QED_F_NEED_CHECK;
-    qed_write_header(s, qed_aio_write_prefill, acb);
 }
 
 /**
commit 5ea929e3d13622e5d06ca8795819f1590644cda2
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Jan 26 16:56:48 2011 +0100

    qcow2: Add bdrv_discard support
    
    This adds a bdrv_discard function to qcow2 that frees the discarded clusters.
    It does not yet pass the discard on to the underlying file system driver, but
    the space can be reused by future writes to the image.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 1c2003a..5fb8c66 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -888,3 +888,85 @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
     }
     return 0;
 }
+
+/*
+ * This discards as many clusters of nb_clusters as possible at once (i.e.
+ * all clusters in the same L2 table) and returns the number of discarded
+ * clusters.
+ */
+static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
+    unsigned int nb_clusters)
+{
+    BDRVQcowState *s = bs->opaque;
+    uint64_t l2_offset, *l2_table;
+    int l2_index;
+    int ret;
+    int i;
+
+    ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
+    if (ret < 0) {
+        return ret;
+    }
+
+    /* Limit nb_clusters to one L2 table */
+    nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
+
+    for (i = 0; i < nb_clusters; i++) {
+        uint64_t old_offset;
+
+        old_offset = be64_to_cpu(l2_table[l2_index + i]);
+        old_offset &= ~QCOW_OFLAG_COPIED;
+
+        if (old_offset == 0) {
+            continue;
+        }
+
+        /* First remove L2 entries */
+        qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
+        l2_table[l2_index + i] = cpu_to_be64(0);
+
+        /* Then decrease the refcount */
+        qcow2_free_any_clusters(bs, old_offset, 1);
+    }
+
+    ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return nb_clusters;
+}
+
+int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
+    int nb_sectors)
+{
+    BDRVQcowState *s = bs->opaque;
+    uint64_t end_offset;
+    unsigned int nb_clusters;
+    int ret;
+
+    end_offset = offset + (nb_sectors << BDRV_SECTOR_BITS);
+
+    /* Round start up and end down */
+    offset = align_offset(offset, s->cluster_size);
+    end_offset &= ~(s->cluster_size - 1);
+
+    if (offset > end_offset) {
+        return 0;
+    }
+
+    nb_clusters = size_to_clusters(s, end_offset - offset);
+
+    /* Each L2 table is handled by its own loop iteration */
+    while (nb_clusters > 0) {
+        ret = discard_single_l2(bs, offset, nb_clusters);
+        if (ret < 0) {
+            return ret;
+        }
+
+        nb_clusters -= ret;
+        offset += (ret * s->cluster_size);
+    }
+
+    return 0;
+}
diff --git a/block/qcow2.c b/block/qcow2.c
index 49bf7b9..dbe4fdd 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1084,6 +1084,13 @@ static int qcow2_make_empty(BlockDriverState *bs)
     return 0;
 }
 
+static int qcow2_discard(BlockDriverState *bs, int64_t sector_num,
+    int nb_sectors)
+{
+    return qcow2_discard_clusters(bs, sector_num << BDRV_SECTOR_BITS,
+        nb_sectors);
+}
+
 static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
 {
     BDRVQcowState *s = bs->opaque;
@@ -1349,6 +1356,7 @@ static BlockDriver bdrv_qcow2 = {
     .bdrv_aio_writev    = qcow2_aio_writev,
     .bdrv_aio_flush     = qcow2_aio_flush,
 
+    .bdrv_discard           = qcow2_discard,
     .bdrv_truncate          = qcow2_truncate,
     .bdrv_write_compressed  = qcow2_write_compressed,
 
diff --git a/block/qcow2.h b/block/qcow2.h
index 6d80120..a019831 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -209,6 +209,8 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
                                          int compressed_size);
 
 int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
+int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
+    int nb_sectors);
 
 /* qcow2-snapshot.c functions */
 int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
commit a9c49a6b023fd3706002fd8d549c58f0343932f8
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Wed Jan 26 16:56:34 2011 +0100

    qemu-io: Fix discard command
    
    qemu-io passed bytes where it's supposed to pass sectors, so discard requests
    were off.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qemu-io.c b/qemu-io.c
index 5b24c5e..4470e49 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1465,7 +1465,7 @@ discard_f(int argc, char **argv)
 	}
 
 	gettimeofday(&t1, NULL);
-	ret = bdrv_discard(bs, offset, count);
+	ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS, count >> BDRV_SECTOR_BITS);
 	gettimeofday(&t2, NULL);
 
 	if (ret < 0) {
commit b4447363469650fc98f67714336cb0baa6156a5e
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date:   Fri Jan 28 01:33:10 2011 +0900

    sheepdog: support creating images on remote hosts
    
    This patch parses the input filename in sd_create(), and enables us
    specifying a target server to create sheepdog images.
    
    Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/sheepdog.c b/block/sheepdog.c
index e62820a..a54e0de 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1294,12 +1294,23 @@ static int do_sd_create(char *filename, int64_t vdi_size,
 static int sd_create(const char *filename, QEMUOptionParameter *options)
 {
     int ret;
-    uint32_t vid = 0;
+    uint32_t vid = 0, base_vid = 0;
     int64_t vdi_size = 0;
     char *backing_file = NULL;
+    BDRVSheepdogState s;
+    char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
+    uint32_t snapid;
 
     strstart(filename, "sheepdog:", (const char **)&filename);
 
+    memset(&s, 0, sizeof(s));
+    memset(vdi, 0, sizeof(vdi));
+    memset(tag, 0, sizeof(tag));
+    if (parse_vdiname(&s, filename, vdi, &snapid, tag) < 0) {
+        error_report("invalid filename\n");
+        return -EINVAL;
+    }
+
     while (options && options->name) {
         if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
             vdi_size = options->value.n;
@@ -1338,11 +1349,11 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
             return -EINVAL;
         }
 
-        vid = s->inode.vdi_id;
+        base_vid = s->inode.vdi_id;
         bdrv_delete(bs);
     }
 
-    return do_sd_create((char *)filename, vdi_size, vid, NULL, 0, NULL, NULL);
+    return do_sd_create((char *)vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
 }
 
 static void sd_close(BlockDriverState *bs)
commit bf595021c765c8869cf2942874c419d7b73bbaf6
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jan 27 11:25:03 2011 +0100

    Reorganize struct Qcow2Cache for better struct packing
    
    Move size after the two pointers in struct Qcow2Cache to get better
    packing of struct elements on 64 bit architectures.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index 8f2955b..3824739 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -35,9 +35,9 @@ typedef struct Qcow2CachedTable {
 } Qcow2CachedTable;
 
 struct Qcow2Cache {
-    int                     size;
     Qcow2CachedTable*       entries;
     struct Qcow2Cache*      depends;
+    int                     size;
     bool                    depends_on_flush;
     bool                    writethrough;
 };
commit fe6ceac86041ecdf7b99a3d57991941277fa7694
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Wed Jan 26 10:24:56 2011 +0000

    ahci: Fix cpu_physical_memory_unmap() argument ordering
    
    The len and is_write arguments to cpu_physical_memory_unmap() were
    swapped.  This patch changes calls to use the correct argument ordering.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 968fdce..433171c 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -513,12 +513,12 @@ static void map_page(uint8_t **ptr, uint64_t addr, uint32_t wanted)
     target_phys_addr_t len = wanted;
 
     if (*ptr) {
-        cpu_physical_memory_unmap(*ptr, 1, len, len);
+        cpu_physical_memory_unmap(*ptr, len, 1, len);
     }
 
     *ptr = cpu_physical_memory_map(addr, &len, 1);
     if (len < wanted) {
-        cpu_physical_memory_unmap(*ptr, 1, len, len);
+        cpu_physical_memory_unmap(*ptr, len, 1, len);
         *ptr = NULL;
     }
 }
@@ -956,7 +956,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis)
     ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS);
 
     if (cmd_mapped) {
-        cpu_physical_memory_unmap(cmd_fis, 0, cmd_len, cmd_len);
+        cpu_physical_memory_unmap(cmd_fis, cmd_len, 0, cmd_len);
     }
 }
 
@@ -1002,7 +1002,7 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist)
     }
 
 out:
-    cpu_physical_memory_unmap(prdt, 0, prdt_len, prdt_len);
+    cpu_physical_memory_unmap(prdt, prdt_len, 0, prdt_len);
     return r;
 }
 
@@ -1228,7 +1228,7 @@ static int handle_cmd(AHCIState *s, int port, int slot)
     }
 
 out:
-    cpu_physical_memory_unmap(cmd_fis, 1, cmd_len, cmd_len);
+    cpu_physical_memory_unmap(cmd_fis, cmd_len, 1, cmd_len);
 
     if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) {
         /* async command, complete later */
commit d7142456c4c0a8793a7888e00ef7fbf0553f9c66
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Wed Jan 26 11:54:58 2011 +0100

    Add documentation for STRTOSZ_DEFSUFFIX_ macros
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Acked-by: Markus Armbruster <armbru at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-common.h b/qemu-common.h
index c351131..79e1149 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -153,6 +153,13 @@ int qemu_fls(int i);
 int qemu_fdatasync(int fd);
 int fcntl_setfl(int fd, int flag);
 
+/*
+ * strtosz() suffixes used to specify the default treatment of an
+ * argument passed to strtosz() without an explicit suffix.
+ * These should be defined using upper case characters in the range
+ * A-Z, as strtosz() will use qemu_toupper() on the given argument
+ * prior to comparison.
+ */
 #define STRTOSZ_DEFSUFFIX_TB	'T'
 #define STRTOSZ_DEFSUFFIX_GB	'G'
 #define STRTOSZ_DEFSUFFIX_MB	'M'
commit d0dcac833a767dade968a07aba4d116f162ebc72
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Tue Jan 25 16:17:14 2011 +0000

    virtio-pci: Disable virtio-ioeventfd when !CONFIG_IOTHREAD
    
    It is not possible to use virtio-ioeventfd when building without an I/O
    thread.  We rely on a signal to kick us out of vcpu execution.  Timers
    and AIO use SIGALRM and SIGUSR2 respectively.  Unfortunately eventfd
    does not support O_ASYNC (SIGIO) so eventfd cannot be used in a signal
    driven manner.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Acked-by: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 255b6fa..8f0e17c 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -449,10 +449,14 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
 
 static int kvm_check_many_ioeventfds(void)
 {
-    /* Older kernels have a 6 device limit on the KVM io bus.  Find out so we
+    /* Userspace can use ioeventfd for io notification.  This requires a host
+     * that supports eventfd(2) and an I/O thread; since eventfd does not
+     * support SIGIO it cannot interrupt the vcpu.
+     *
+     * Older kernels have a 6 device limit on the KVM io bus.  Find out so we
      * can avoid creating too many ioeventfds.
      */
-#ifdef CONFIG_EVENTFD
+#if defined(CONFIG_EVENTFD) && defined(CONFIG_IOTHREAD)
     int ioeventfds[7];
     int i, ret = 0;
     for (i = 0; i < ARRAY_SIZE(ioeventfds); i++) {
commit e5051fc70807750f7a4798d2d83e159793c466d3
Author: Christoph Hellwig <hch at lst.de>
Date:   Mon Jan 24 13:32:51 2011 +0100

    virtio-blk: tell the guest about size changes
    
    Raise a config change interrupt when the size changed.  This allows
    virtio-blk guest drivers to read-read the information from the
    config space once it got the config chaged interrupt.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 9f2a9c0..ffac5a4 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -514,6 +514,15 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
+static void virtio_blk_change_cb(void *opaque, int reason)
+{
+    VirtIOBlock *s = opaque;
+
+    if (reason & CHANGE_SIZE) {
+        virtio_notify_config(&s->vdev);
+    }
+}
+
 VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
 {
     VirtIOBlock *s;
@@ -556,6 +565,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
     register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
     bdrv_set_removable(s->bs, 0);
+    bdrv_set_change_cb(s->bs, virtio_blk_change_cb, s);
     s->bs->buffer_alignment = conf->logical_block_size;
 
     add_boot_device_path(conf->bootindex, dev, "/disk at 0,0");
commit db97ee6a976bacbb0d18818e951cfc41b39269a7
Author: Christoph Hellwig <hch at lst.de>
Date:   Mon Jan 24 13:32:41 2011 +0100

    block: tell drivers about an image resize
    
    Extend the change_cb callback with a reason argument, and use it
    to tell drivers about size changes.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index 7ad3ddf..998df1b 100644
--- a/block.c
+++ b/block.c
@@ -645,7 +645,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         /* call the change callback */
         bs->media_changed = 1;
         if (bs->change_cb)
-            bs->change_cb(bs->change_opaque);
+            bs->change_cb(bs->change_opaque, CHANGE_MEDIA);
     }
 
     return 0;
@@ -684,7 +684,7 @@ void bdrv_close(BlockDriverState *bs)
         /* call the change callback */
         bs->media_changed = 1;
         if (bs->change_cb)
-            bs->change_cb(bs->change_opaque);
+            bs->change_cb(bs->change_opaque, CHANGE_MEDIA);
     }
 }
 
@@ -1135,6 +1135,9 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
     ret = drv->bdrv_truncate(bs, offset);
     if (ret == 0) {
         ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
+        if (bs->change_cb) {
+            bs->change_cb(bs->change_opaque, CHANGE_SIZE);
+        }
     }
     return ret;
 }
@@ -1366,7 +1369,8 @@ int bdrv_enable_write_cache(BlockDriverState *bs)
 
 /* XXX: no longer used */
 void bdrv_set_change_cb(BlockDriverState *bs,
-                        void (*change_cb)(void *opaque), void *opaque)
+                        void (*change_cb)(void *opaque, int reason),
+                        void *opaque)
 {
     bs->change_cb = change_cb;
     bs->change_opaque = opaque;
@@ -1411,7 +1415,7 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
         /* call the change callback now, we skipped it on open */
         bs->media_changed = 1;
         if (bs->change_cb)
-            bs->change_cb(bs->change_opaque);
+            bs->change_cb(bs->change_opaque, CHANGE_MEDIA);
     }
     return ret;
 }
diff --git a/block.h b/block.h
index f923add..239f729 100644
--- a/block.h
+++ b/block.h
@@ -182,7 +182,8 @@ int bdrv_is_locked(BlockDriverState *bs);
 void bdrv_set_locked(BlockDriverState *bs, int locked);
 int bdrv_eject(BlockDriverState *bs, int eject_flag);
 void bdrv_set_change_cb(BlockDriverState *bs,
-                        void (*change_cb)(void *opaque), void *opaque);
+                        void (*change_cb)(void *opaque, int reason),
+                        void *opaque);
 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
 BlockDriverState *bdrv_find(const char *name);
 BlockDriverState *bdrv_next(BlockDriverState *bs);
diff --git a/block_int.h b/block_int.h
index 12663e8..6ebdc3e 100644
--- a/block_int.h
+++ b/block_int.h
@@ -153,7 +153,7 @@ struct BlockDriverState {
     int valid_key; /* if true, a valid encryption key has been set */
     int sg;        /* if true, the device is a /dev/sg* */
     /* event callback when inserting/removing */
-    void (*change_cb)(void *opaque);
+    void (*change_cb)(void *opaque, int reason);
     void *change_opaque;
 
     BlockDriver *drv; /* NULL means no media */
@@ -203,6 +203,9 @@ struct BlockDriverState {
     void *private;
 };
 
+#define CHANGE_MEDIA	0x01
+#define CHANGE_SIZE	0x02
+
 struct BlockDriverAIOCB {
     AIOPool *pool;
     BlockDriverState *bs;
diff --git a/hw/ide/core.c b/hw/ide/core.c
index e698c13..dd63664 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1584,11 +1584,15 @@ static void ide_cfata_metadata_write(IDEState *s)
 }
 
 /* called when the inserted state of the media has changed */
-static void cdrom_change_cb(void *opaque)
+static void cdrom_change_cb(void *opaque, int reason)
 {
     IDEState *s = opaque;
     uint64_t nb_sectors;
 
+    if (!(reason & CHANGE_MEDIA)) {
+        return;
+    }
+
     bdrv_get_geometry(s->bs, &nb_sectors);
     s->nb_sectors = nb_sectors;
 
diff --git a/hw/sd.c b/hw/sd.c
index 601545b..789ca84 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -422,9 +422,14 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv)
     sd->pwd_len = 0;
 }
 
-static void sd_cardchange(void *opaque)
+static void sd_cardchange(void *opaque, int reason)
 {
     SDState *sd = opaque;
+
+    if (!(reason & CHANGE_MEDIA)) {
+        return;
+    }
+
     qemu_set_irq(sd->inserted_cb, bdrv_is_inserted(sd->bdrv));
     if (bdrv_is_inserted(sd->bdrv)) {
         sd_reset(sd, sd->bdrv);
commit 6d4a2b3a47959f02e7f307f50396e70e8464f95e
Author: Christoph Hellwig <hch at lst.de>
Date:   Mon Jan 24 13:32:33 2011 +0100

    block: add block_resize monitor command
    
    Add a monitor command that allows resizing of block devices while
    qemu is running.  It uses the existing bdrv_truncate method already
    used by qemu-img to do it's work.  Compared to qemu-img the size
    parsing is very simplicistic, but I think having a properly numering
    object is more useful for non-humand monitor users than having
    the units and relative resize parsing.
    
    For SCSI devices the new size can be updated in Linux guests by
    doing the following shell command:
    
    	echo > /sys/class/scsi_device/0:0:0:0/device/rescan
    
    For ATA devices I don't know of a way to update the block device
    size in Linux system, and for virtio-blk the next two patches
    will provide an automatic update of the size when this command
    is issued on the host.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index f7f591f..e48d33d 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -705,3 +705,33 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 
     return 0;
 }
+
+/*
+ * XXX: replace the QERR_UNDEFINED_ERROR errors with real values once the
+ * existing QERR_ macro mess is cleaned up.  A good example for better
+ * error reports can be found in the qemu-img resize code.
+ */
+int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    const char *device = qdict_get_str(qdict, "device");
+    int64_t size = qdict_get_int(qdict, "size");
+    BlockDriverState *bs;
+
+    bs = bdrv_find(device);
+    if (!bs) {
+        qerror_report(QERR_DEVICE_NOT_FOUND, device);
+        return -1;
+    }
+
+    if (size < 0) {
+        qerror_report(QERR_UNDEFINED_ERROR);
+        return -1;
+    }
+
+    if (bdrv_truncate(bs, size)) {
+        qerror_report(QERR_UNDEFINED_ERROR);
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/blockdev.h b/blockdev.h
index 4536b5c..b8a88bf 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -53,5 +53,6 @@ int do_change_block(Monitor *mon, const char *device,
                     const char *filename, const char *fmt);
 int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 #endif
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 1cea572..8df4adf 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -53,6 +53,25 @@ Quit the emulator.
 ETEXI
 
     {
+        .name       = "block_resize",
+        .args_type  = "device:B,size:o",
+        .params     = "device size",
+        .help       = "resize a block image",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_block_resize,
+    },
+
+STEXI
+ at item block_resize
+ at findex block_resize
+Resize a block image while a guest is running.  Usually requires guest
+action to see the updated size.  Resize to a lower size is supported,
+but should be used with extreme caution.  Note that this command only
+resizes image files, it can not resize block devices like LVM volumes.
+ETEXI
+
+
+    {
         .name       = "eject",
         .args_type  = "force:-f,device:B",
         .params     = "[-f] device",
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 56c4d8b..9f79f5f 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -601,6 +601,34 @@ Example:
 -> { "execute": "netdev_del", "arguments": { "id": "netdev1" } }
 <- { "return": {} }
 
+
+EQMP
+
+    {
+        .name       = "block_resize",
+        .args_type  = "device:B,size:o",
+        .params     = "device size",
+        .help       = "resize a block image",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_block_resize,
+    },
+
+SQMP
+block_resize
+------------
+
+Resize a block image while a guest is running.
+
+Arguments:
+
+- "device": the device's ID, must be unique (json-string)
+- "size": new size
+
+Example:
+
+-> { "execute": "block_resize", "arguments": { "device": "scratch", "size": 1073741824 } }
+<- { "return": {} }
+
 EQMP
 
     {
commit 2be22ca5a8dd96c68ef0e90fd916aa6555ae915b
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Mon Jan 24 16:33:31 2011 +0100

    strtosz(): Use suffix macros in switch() statement
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/cutils.c b/cutils.c
index 369a016..8d562b2 100644
--- a/cutils.c
+++ b/cutils.c
@@ -324,26 +324,26 @@ int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
         }
     }
     switch (qemu_toupper(d)) {
-    case 'B':
+    case STRTOSZ_DEFSUFFIX_B:
         mul = 1;
         if (mul_required) {
             goto fail;
         }
         break;
-    case 'K':
+    case STRTOSZ_DEFSUFFIX_KB:
         mul = 1 << 10;
         break;
     case 0:
         if (mul_required) {
             goto fail;
         }
-    case 'M':
+    case STRTOSZ_DEFSUFFIX_MB:
         mul = 1ULL << 20;
         break;
-    case 'G':
+    case STRTOSZ_DEFSUFFIX_GB:
         mul = 1ULL << 30;
         break;
-    case 'T':
+    case STRTOSZ_DEFSUFFIX_TB:
         mul = 1ULL << 40;
         break;
     default:
commit 7eb053494c76bb417f83b6e6784a5dbb27638dba
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Mon Jan 24 16:33:30 2011 +0100

    strtosz(): Fix name confusion in use of modf()
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/cutils.c b/cutils.c
index 78d35e2..369a016 100644
--- a/cutils.c
+++ b/cutils.c
@@ -304,8 +304,8 @@ int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
     if (isnan(val) || endptr == nptr || errno != 0) {
         goto fail;
     }
-    integral = modf(val, &fraction);
-    if (integral != 0) {
+    fraction = modf(val, &integral);
+    if (fraction != 0) {
         mul_required = 1;
     }
     /*
commit a2afc2c16339a85176696738e4c58ed4ff36f8b5
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Mon Jan 24 16:33:29 2011 +0100

    strtosz() use qemu_toupper() to simplify switch statement
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/cutils.c b/cutils.c
index a067cf4..78d35e2 100644
--- a/cutils.c
+++ b/cutils.c
@@ -323,16 +323,14 @@ int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
             d = c;
         }
     }
-    switch (d) {
+    switch (qemu_toupper(d)) {
     case 'B':
-    case 'b':
         mul = 1;
         if (mul_required) {
             goto fail;
         }
         break;
     case 'K':
-    case 'k':
         mul = 1 << 10;
         break;
     case 0:
@@ -340,15 +338,12 @@ int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
             goto fail;
         }
     case 'M':
-    case 'm':
         mul = 1ULL << 20;
         break;
     case 'G':
-    case 'g':
         mul = 1ULL << 30;
         break;
     case 'T':
-    case 't':
         mul = 1ULL << 40;
         break;
     default:
commit f3bd362a1857c617a4154062cadd501fc52c4199
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Mon Jan 24 16:33:28 2011 +0100

    strtosz(): use unsigned char and switch to qemu_isspace()
    
    isspace() behavior is undefined for signed char.
    
    Bug pointed out by Eric Blake, thanks!
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/cutils.c b/cutils.c
index 4d2e27c..a067cf4 100644
--- a/cutils.c
+++ b/cutils.c
@@ -294,7 +294,8 @@ int fcntl_setfl(int fd, int flag)
 int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
 {
     int64_t retval = -1;
-    char *endptr, c, d;
+    char *endptr;
+    unsigned char c, d;
     int mul_required = 0;
     double val, mul, integral, fraction;
 
@@ -314,7 +315,7 @@ int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
      */
     c = *endptr;
     d = c;
-    if (isspace(c) || c == '\0' || c == ',') {
+    if (qemu_isspace(c) || c == '\0' || c == ',') {
         c = 0;
         if (default_suffix) {
             d = default_suffix;
@@ -361,7 +362,7 @@ int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
      */
     if (c != 0) {
         endptr++;
-        if (!isspace(*endptr) && *endptr != ',' && *endptr != 0) {
+        if (!qemu_isspace(*endptr) && *endptr != ',' && *endptr != 0) {
             goto fail;
         }
     }
commit 45d1aa828f8c94b082a0aa2dbf76535594ee45df
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Jan 30 13:10:10 2011 +0000

    Update OpenBIOS images to r1018
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/pc-bios/README b/pc-bios/README
index 4b019e0..3fc0944 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -11,7 +11,7 @@
   firmware implementation. The goal is to implement a 100% IEEE
   1275-1994 (referred to as Open Firmware) compliant firmware.
   The included image for PowerPC (for 32 and 64 bit PPC CPUs), Sparc32
-  and Sparc64 are built from OpenBIOS SVN revision 859.
+  and Sparc64 are built from OpenBIOS SVN revision 1018.
 
 - The PXE roms come from Rom-o-Matic gPXE 0.9.9 with BANNER_TIMEOUT=0
 
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index cb0af05..ee6f5ae 100644
Binary files a/pc-bios/openbios-ppc and b/pc-bios/openbios-ppc differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index aaff1f0..b2dc5c5 100644
Binary files a/pc-bios/openbios-sparc32 and b/pc-bios/openbios-sparc32 differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index a1b692e..70a223d 100644
Binary files a/pc-bios/openbios-sparc64 and b/pc-bios/openbios-sparc64 differ
commit 1b958498acaeee61f0db648b464c04f228f8aab6
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sat Jan 29 22:52:33 2011 +0000

    sdl: remove unused variable
    
    Variable rec is not used, remove it. Spotted by GCC 4.6.0:
      CC    ui/sdl.o
    /src/qemu/ui/sdl.c: In function 'sdl_setdata':
    /src/qemu/ui/sdl.c:90:14: error: variable 'rec' set but not used [-Werror=unused-but-set-variable]
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/ui/sdl.c b/ui/sdl.c
index f599d42..a1458ce 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -87,12 +87,6 @@ static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
 
 static void sdl_setdata(DisplayState *ds)
 {
-    SDL_Rect rec;
-    rec.x = 0;
-    rec.y = 0;
-    rec.w = real_screen->w;
-    rec.h = real_screen->h;
-
     if (guest_screen != NULL) SDL_FreeSurface(guest_screen);
 
     guest_screen = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), ds_get_width(ds), ds_get_height(ds),
commit 320fba2a1f384e17db150d74540a2cf005eb47b5
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Thu Jan 27 10:24:41 2011 +0100

    New trace-event backend: stderr
    
    This backend sends trace events to standard error output during the emulation.
    
    Also add a "--list-backends" option to tracetool, so configure script can
    display the list of available backends.
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Acked-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/configure b/configure
index 210670c..fcc5a71 100755
--- a/configure
+++ b/configure
@@ -907,7 +907,8 @@ echo "  --enable-docs            enable documentation build"
 echo "  --disable-docs           disable documentation build"
 echo "  --disable-vhost-net      disable vhost-net acceleration support"
 echo "  --enable-vhost-net       enable vhost-net acceleration support"
-echo "  --enable-trace-backend=B Trace backend nop simple ust dtrace"
+echo "  --enable-trace-backend=B Set trace backend"
+echo "                           Available backends:" $("$source_path"/scripts/tracetool --list-backends)
 echo "  --with-trace-file=NAME   Full PATH,NAME of file to store traces"
 echo "                           Default:trace-<pid>"
 echo "  --disable-spice          disable spice"
diff --git a/docs/tracing.txt b/docs/tracing.txt
index 963c504..21183f9 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -133,6 +133,11 @@ source tree.  It may not be as powerful as platform-specific or third-party
 trace backends but it is portable.  This is the recommended trace backend
 unless you have specific needs for more advanced backends.
 
+=== Stderr ===
+
+The "stderr" backend sends trace events directly to standard error output
+during emulation.
+
 ==== Monitor commands ====
 
 * info trace
diff --git a/scripts/tracetool b/scripts/tracetool
index fce491c..e046683 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -13,12 +13,13 @@ set -f
 usage()
 {
     cat >&2 <<EOF
-usage: $0 [--nop | --simple | --ust] [-h | -c]
+usage: $0 [--nop | --simple | --stderr | --ust | --dtrace] [-h | -c]
 Generate tracing code for a file on stdin.
 
 Backends:
   --nop     Tracing disabled
   --simple  Simple built-in backend
+  --stderr  Stderr built-in backend
   --ust     LTTng User Space Tracing backend
   --dtrace  DTrace/SystemTAP backend
 
@@ -236,6 +237,56 @@ linetoc_end_simple()
 EOF
 }
 
+#STDERR
+linetoh_begin_stderr()
+{
+    cat <<EOF
+#include <stdio.h>
+EOF
+}
+
+linetoh_stderr()
+{
+    local name args argnames argc fmt
+    name=$(get_name "$1")
+    args=$(get_args "$1")
+    argnames=$(get_argnames "$1" ",")
+    argc=$(get_argc "$1")
+    fmt=$(get_fmt "$1")
+
+    if [ "$argc" -gt 0 ]; then
+        argnames=", $argnames"
+    fi
+
+    cat <<EOF
+static inline void trace_$name($args)
+{
+    fprintf(stderr, "$name $fmt\n" $argnames);
+}
+EOF
+}
+
+linetoh_end_stderr()
+{
+return
+}
+
+linetoc_begin_stderr()
+{
+return
+}
+
+linetoc_stderr()
+{
+return
+}
+
+linetoc_end_stderr()
+{
+return
+}
+#END OF STDERR
+
 # Clean up after UST headers which pollute the namespace
 ust_clean_namespace() {
     cat <<EOF
@@ -546,7 +597,7 @@ targetarch=
 until [ -z "$1" ]
 do
   case "$1" in
-    "--nop" | "--simple" | "--ust" | "--dtrace") backend="${1#--}" ;;
+    "--nop" | "--simple" | "--stderr" | "--ust" | "--dtrace") backend="${1#--}" ;;
 
     "--binary") shift ; binary="$1" ;;
     "--target-arch") shift ; targetarch="$1" ;;
@@ -557,6 +608,11 @@ do
 
     "--check-backend") exit 0 ;; # used by ./configure to test for backend
 
+    "--list-backends") # used by ./configure to list available backends
+          echo "nop simple stderr ust dtrace"
+          exit 0
+          ;;
+
     *)
       usage;;
   esac
commit 491e2a338fdf8310c84f6ebaed1683a871a0700e
Author: Hervé Poussineau <hpoussin at reactos.org>
Date:   Tue Jan 18 22:43:56 2011 +0100

    prep: Disable second IDE channel, as long as ISA IDE emulation doesn't support same irq for both channels
    
    Cc: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 6b22122..6c1499a 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -690,7 +690,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
         hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
     }
 
-    for(i = 0; i < MAX_IDE_BUS; i++) {
+    for(i = 0; i < 1/*MAX_IDE_BUS*/; i++) {
         isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
                      hd[2 * i],
 		     hd[2 * i + 1]);
commit 74145374bfc0b7b02415184606236f0390479deb
Author: Andreas Färber <andreas.faerber at web.de>
Date:   Tue Jan 18 22:43:55 2011 +0100

    prep: Remove bogus BIOS size check
    
    r3480 added this check to account for the entry vector 0xfff00100 to be
    available for CPUs that need it. Today however, the NIP is not yet
    initialized at this point (zero), so the check always triggers.
    
    Moreover, BIOS size check is already done previously, so this part can
    be removed too.
    
    Cc: Alexander Graf <agraf at suse.de>
    Signed-off-by: Andreas Färber <andreas.faerber at web.de>
    Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 1492266..6b22122 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -600,9 +600,6 @@ static void ppc_prep_init (ram_addr_t ram_size,
     if (filename) {
         qemu_free(filename);
     }
-    if (env->nip < 0xFFF80000 && bios_size < 0x00100000) {
-        hw_error("PowerPC 601 / 620 / 970 need a 1MB BIOS\n");
-    }
 
     if (linux_boot) {
         kernel_base = KERNEL_LOAD_ADDR;
commit 51e08f3e4b8a3b6d27fde9a9e75c8fa32eaa72d0
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Jan 25 11:55:15 2011 +0100

    mc146818rtc: update registers after a format change
    
    For some unknown reason, the MIPS kernel briefly changes the RTC to
    binary mode during boot, switch back to BCD mode and read the time. As
    the registers are updated only every second, they may still be in the
    old format when they are read.
    
    This patch forces a register update immediately after a format change
    (BCD/binary or 12/24H). This avoid long fsck during boot due to time
    wrap.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index ec7c4ec..a1b0e31 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -247,7 +247,15 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
                     rtc_set_time(s);
                 }
             }
-            s->cmos_data[RTC_REG_B] = data;
+            if (((s->cmos_data[RTC_REG_B] ^ data) & (REG_B_DM | REG_B_24H)) &&
+                !(data & REG_B_SET)) {
+                /* If the time format has changed and not in set mode,
+                   update the registers immediately. */
+                s->cmos_data[RTC_REG_B] = data;
+                rtc_copy_date(s);
+            } else {
+                s->cmos_data[RTC_REG_B] = data;
+            }
             rtc_timer_update(s, qemu_get_clock(rtc_clock));
             break;
         case RTC_REG_C:
commit c29cd656a8fad633fb9ca45b88ade9838d35fd5c
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Jan 25 11:55:15 2011 +0100

    mc146818rtc: constantify
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 6466aff..ec7c4ec 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -72,6 +72,7 @@
 #define REG_B_UIE  0x10
 #define REG_B_SQWE 0x08
 #define REG_B_DM   0x04
+#define REG_B_24H  0x02
 
 #define REG_C_UF   0x10
 #define REG_C_IRQF 0x80
@@ -285,7 +286,7 @@ static void rtc_set_time(RTCState *s)
     tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
     tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
     tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
-    if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
+    if (!(s->cmos_data[RTC_REG_B] & REG_B_24H) &&
         (s->cmos_data[RTC_HOURS] & 0x80)) {
         tm->tm_hour += 12;
     }
@@ -304,7 +305,7 @@ static void rtc_copy_date(RTCState *s)
 
     s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec);
     s->cmos_data[RTC_MINUTES] = rtc_to_bcd(s, tm->tm_min);
-    if (s->cmos_data[RTC_REG_B] & 0x02) {
+    if (s->cmos_data[RTC_REG_B] & REG_B_24H) {
         /* 24 hour format */
         s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour);
     } else {
commit 46eece9d8969ac37bcdf0a3f056a9cceb20bc641
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date:   Thu Jan 27 19:18:35 2011 +0000

    target-arm: Fix Neon VQ(R)DMULH.S16 instructions
    
    Correct an error in the implementation of the 16 bit
    forms of VQ(R)DMULH, bringing them into line with the
    32 bit implementation.
    
    Signed-off-by: Juha Riihimäki <juha.riihimaki at nokia.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 20f3c16..fead152 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -880,8 +880,9 @@ uint32_t HELPER(neon_cnt_u8)(uint32_t x)
     if ((tmp ^ (tmp << 1)) & SIGNBIT) { \
         SET_QC(); \
         tmp = (tmp >> 31) ^ ~SIGNBIT; \
+    } else { \
+        tmp <<= 1; \
     } \
-    tmp <<= 1; \
     if (round) { \
         int32_t old = tmp; \
         tmp += 1 << 15; \
commit 92e3c2a39e95576dd215b063e493069c67ffaab8
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Jan 25 11:55:14 2011 +0100

    virtio-blk: fix cross-endianness targets
    
    virtio-blk doesn't work on cross-endian configuration, as endianness is
    not handled correctly.
    
    This patch adds missing endianness conversions to make virtio-blk
    working. Tested on the following configurations:
    - i386 guest on x86_64 host
    - ppc guest on x86_64 host
    - i386 guest on mips host
    - ppc guest on mips host
    
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index f62ccd1..9f2a9c0 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -55,7 +55,7 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)
 
     trace_virtio_blk_req_complete(req, status);
 
-    req->in->status = status;
+    stb_p(&req->in->status, status);
     virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in));
     virtio_notify(&s->vdev, s->vq);
 
@@ -94,7 +94,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret)
     trace_virtio_blk_rw_complete(req, ret);
 
     if (ret) {
-        int is_read = !(req->out->type & VIRTIO_BLK_T_OUT);
+        int is_read = !(ldl_p(&req->out->type) & VIRTIO_BLK_T_OUT);
         if (virtio_blk_handle_rw_error(req, -ret, is_read))
             return;
     }
@@ -223,10 +223,10 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
         status = VIRTIO_BLK_S_OK;
     }
 
-    req->scsi->errors = hdr.status;
-    req->scsi->residual = hdr.resid;
-    req->scsi->sense_len = hdr.sb_len_wr;
-    req->scsi->data_len = hdr.dxfer_len;
+    stl_p(&req->scsi->errors, hdr.status);
+    stl_p(&req->scsi->residual, hdr.resid);
+    stl_p(&req->scsi->sense_len, hdr.sb_len_wr);
+    stl_p(&req->scsi->data_len, hdr.dxfer_len);
 
     virtio_blk_req_complete(req, status);
 }
@@ -280,10 +280,13 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
 static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
 {
     BlockRequest *blkreq;
+    uint64_t sector;
 
-    trace_virtio_blk_handle_write(req, req->out->sector, req->qiov.size / 512);
+    sector = ldq_p(&req->out->sector);
 
-    if (req->out->sector & req->dev->sector_mask) {
+    trace_virtio_blk_handle_write(req, sector, req->qiov.size / 512);
+
+    if (sector & req->dev->sector_mask) {
         virtio_blk_rw_complete(req, -EIO);
         return;
     }
@@ -293,7 +296,7 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
     }
 
     blkreq = &mrb->blkreq[mrb->num_writes];
-    blkreq->sector = req->out->sector;
+    blkreq->sector = sector;
     blkreq->nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE;
     blkreq->qiov = &req->qiov;
     blkreq->cb = virtio_blk_rw_complete;
@@ -306,13 +309,16 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
 static void virtio_blk_handle_read(VirtIOBlockReq *req)
 {
     BlockDriverAIOCB *acb;
+    uint64_t sector;
+
+    sector = ldq_p(&req->out->sector);
 
-    if (req->out->sector & req->dev->sector_mask) {
+    if (sector & req->dev->sector_mask) {
         virtio_blk_rw_complete(req, -EIO);
         return;
     }
 
-    acb = bdrv_aio_readv(req->dev->bs, req->out->sector, &req->qiov,
+    acb = bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
                          req->qiov.size / BDRV_SECTOR_SIZE,
                          virtio_blk_rw_complete, req);
     if (!acb) {
@@ -323,6 +329,8 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
 static void virtio_blk_handle_request(VirtIOBlockReq *req,
     MultiReqBuffer *mrb)
 {
+    uint32_t type;
+
     if (req->elem.out_num < 1 || req->elem.in_num < 1) {
         error_report("virtio-blk missing headers");
         exit(1);
@@ -337,17 +345,19 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
     req->out = (void *)req->elem.out_sg[0].iov_base;
     req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
 
-    if (req->out->type & VIRTIO_BLK_T_FLUSH) {
+    type = ldl_p(&req->out->type);
+
+    if (type & VIRTIO_BLK_T_FLUSH) {
         virtio_blk_handle_flush(req, mrb);
-    } else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
+    } else if (type & VIRTIO_BLK_T_SCSI_CMD) {
         virtio_blk_handle_scsi(req);
-    } else if (req->out->type & VIRTIO_BLK_T_GET_ID) {
+    } else if (type & VIRTIO_BLK_T_GET_ID) {
         VirtIOBlock *s = req->dev;
 
         memcpy(req->elem.in_sg[0].iov_base, s->sn,
                MIN(req->elem.in_sg[0].iov_len, sizeof(s->sn)));
         virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
-    } else if (req->out->type & VIRTIO_BLK_T_OUT) {
+    } else if (type & VIRTIO_BLK_T_OUT) {
         qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
                                  req->elem.out_num - 1);
         virtio_blk_handle_write(req, mrb);
commit 44b15bc5c65ab6b3103f508504e4adf8ee9902d7
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Tue Jan 25 11:55:14 2011 +0100

    virtio-net: fix cross-endianness support
    
    virtio-net used to work on cross-endianness configurations, but doesn't
    anymore with recent guest kernels, as the new features don't handle
    endianness correctly.
    
    This patch fixes wrong conversion, and add missing ones to make
    virtio-net working. Tested on the following configurations:
    - i386 guest on x86_64 host
    - ppc guest on x86_64 host
    - i386 guest on mips host
    - ppc guest on mips host
    
    Cc: Anthony Liguori <aliguori at us.ibm.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index ccb3e63..161f114 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -79,7 +79,7 @@ static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
     VirtIONet *n = to_virtio_net(vdev);
     struct virtio_net_config netcfg;
 
-    netcfg.status = n->status;
+    netcfg.status = lduw_p(&n->status);
     memcpy(netcfg.mac, n->mac, ETH_ALEN);
     memcpy(config, &netcfg, sizeof(netcfg));
 }
@@ -338,7 +338,7 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
     n->mac_table.multi_overflow = 0;
     memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
 
-    mac_data.entries = ldl_le_p(elem->out_sg[1].iov_base);
+    mac_data.entries = ldl_p(elem->out_sg[1].iov_base);
 
     if (sizeof(mac_data.entries) +
         (mac_data.entries * ETH_ALEN) > elem->out_sg[1].iov_len)
@@ -354,7 +354,7 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
 
     n->mac_table.first_multi = n->mac_table.in_use;
 
-    mac_data.entries = ldl_le_p(elem->out_sg[2].iov_base);
+    mac_data.entries = ldl_p(elem->out_sg[2].iov_base);
 
     if (sizeof(mac_data.entries) +
         (mac_data.entries * ETH_ALEN) > elem->out_sg[2].iov_len)
@@ -384,7 +384,7 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
         return VIRTIO_NET_ERR;
     }
 
-    vid = lduw_le_p(elem->out_sg[1].iov_base);
+    vid = lduw_p(elem->out_sg[1].iov_base);
 
     if (vid >= MAX_VLAN)
         return VIRTIO_NET_ERR;
@@ -673,8 +673,9 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
         virtqueue_fill(n->rx_vq, &elem, total, i++);
     }
 
-    if (mhdr)
-        mhdr->num_buffers = i;
+    if (mhdr) {
+        mhdr->num_buffers = lduw_p(&i);
+    }
 
     virtqueue_flush(n->rx_vq, i);
     virtio_notify(&n->vdev, n->rx_vq);
commit f53671c054ba0b5d5b10e2a7294786fa2f73479e
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Thu Jan 27 08:21:35 2011 +0100

    escc: fix interrupt flags
    
    Recent PowerPC kernel end up in kernel panic during boot in -nographic
    mode. In this mode the second serial port is used as the udbg console,
    and thus a few characters are sent on this port. This activates the
    tx interrupt flag, and later choke the Linux kernel, as it was not
    expecting such a flag to be set.
    
    The problem here comes from the fact that contrary to most devices the
    interrupt flags are only set if the interrupt is enabled. Quoting the
    datasheet: "If the corresponding IE bit is not set, the IP for that
    source of interrupt will never be set."
    
    This patch fixes that by enabling the interrupt flag only when the
    corresponding interrupt is enabled.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/escc.c b/hw/escc.c
index ba60636..f6fd919 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -369,14 +369,18 @@ static inline void set_txint(ChannelState *s)
     if (!s->rxint_under_svc) {
         s->txint_under_svc = 1;
         if (s->chn == chn_a) {
-            s->rregs[R_INTR] |= INTR_TXINTA;
+            if (s->wregs[W_INTR] & INTR_TXINT) {
+                s->rregs[R_INTR] |= INTR_TXINTA;
+            }
             if (s->wregs[W_MINTR] & MINTR_STATUSHI)
                 s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
             else
                 s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
         } else {
             s->rregs[R_IVEC] = IVEC_TXINTB;
-            s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
+            if (s->wregs[W_INTR] & INTR_TXINT) {
+                s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
+            }
         }
     escc_update_irq(s);
     }
commit 0bb533374a110f22412d95e75768afb8212f8243
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Fri Jan 21 19:57:50 2011 +0300

    pxa2xx_gpio: switch to using qdev
    
    As noted by Markus Armbruster pxa2xx_gpio vmstate version bumped
    because of a change in the or .ilevel / .olevel arrays are saved,
    for convenience.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/gumstix.c b/hw/gumstix.c
index af8b464..ee63f63 100644
--- a/hw/gumstix.c
+++ b/hw/gumstix.c
@@ -78,7 +78,7 @@ static void connex_init(ram_addr_t ram_size,
 
     /* Interrupt line of NIC is connected to GPIO line 36 */
     smc91c111_init(&nd_table[0], 0x04000300,
-                    pxa2xx_gpio_in_get(cpu->gpio)[36]);
+                    qdev_get_gpio_in(cpu->gpio, 36));
 }
 
 static void verdex_init(ram_addr_t ram_size,
@@ -117,7 +117,7 @@ static void verdex_init(ram_addr_t ram_size,
 
     /* Interrupt line of NIC is connected to GPIO line 99 */
     smc91c111_init(&nd_table[0], 0x04000300,
-                    pxa2xx_gpio_in_get(cpu->gpio)[99]);
+                    qdev_get_gpio_in(cpu->gpio, 99));
 }
 
 static QEMUMachine connex_machine = {
diff --git a/hw/pxa.h b/hw/pxa.h
index 8d6a8c3..f73d33b 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -70,13 +70,9 @@ void pxa25x_timer_init(target_phys_addr_t base, qemu_irq *irqs);
 void pxa27x_timer_init(target_phys_addr_t base, qemu_irq *irqs, qemu_irq irq4);
 
 /* pxa2xx_gpio.c */
-typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo;
-PXA2xxGPIOInfo *pxa2xx_gpio_init(target_phys_addr_t base,
+DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
                 CPUState *env, qemu_irq *pic, int lines);
-qemu_irq *pxa2xx_gpio_in_get(PXA2xxGPIOInfo *s);
-void pxa2xx_gpio_out_set(PXA2xxGPIOInfo *s,
-                int line, qemu_irq handler);
-void pxa2xx_gpio_read_notifier(PXA2xxGPIOInfo *s, qemu_irq handler);
+void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler);
 
 /* pxa2xx_dma.c */
 typedef struct PXA2xxDMAState PXA2xxDMAState;
@@ -132,7 +128,7 @@ typedef struct {
     qemu_irq *pic;
     qemu_irq reset;
     PXA2xxDMAState *dma;
-    PXA2xxGPIOInfo *gpio;
+    DeviceState *gpio;
     PXA2xxLCDState *lcd;
     SSIBus **ssp;
     PXA2xxI2CState *i2c[2];
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 6e72a5c..d966846 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2158,7 +2158,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
 
     /* GPIO1 resets the processor */
     /* The handler can be overridden by board-specific code */
-    pxa2xx_gpio_out_set(s->gpio, 1, s->reset);
+    qdev_connect_gpio_out(s->gpio, 1, s->reset);
     return s;
 }
 
@@ -2279,7 +2279,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
 
     /* GPIO1 resets the processor */
     /* The handler can be overridden by board-specific code */
-    pxa2xx_gpio_out_set(s->gpio, 1, s->reset);
+    qdev_connect_gpio_out(s->gpio, 1, s->reset);
     return s;
 }
 
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 0d03446..789965d 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -8,15 +8,18 @@
  */
 
 #include "hw.h"
+#include "sysbus.h"
 #include "pxa.h"
 
 #define PXA2XX_GPIO_BANKS	4
 
+typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo;
 struct PXA2xxGPIOInfo {
-    qemu_irq *pic;
+    SysBusDevice busdev;
+    qemu_irq irq0, irq1, irqX;
     int lines;
+    int ncpu;
     CPUState *cpu_env;
-    qemu_irq *in;
 
     /* XXX: GNU C vectors are more suitable */
     uint32_t ilevel[PXA2XX_GPIO_BANKS];
@@ -66,19 +69,19 @@ static struct {
 static void pxa2xx_gpio_irq_update(PXA2xxGPIOInfo *s)
 {
     if (s->status[0] & (1 << 0))
-        qemu_irq_raise(s->pic[PXA2XX_PIC_GPIO_0]);
+        qemu_irq_raise(s->irq0);
     else
-        qemu_irq_lower(s->pic[PXA2XX_PIC_GPIO_0]);
+        qemu_irq_lower(s->irq0);
 
     if (s->status[0] & (1 << 1))
-        qemu_irq_raise(s->pic[PXA2XX_PIC_GPIO_1]);
+        qemu_irq_raise(s->irq1);
     else
-        qemu_irq_lower(s->pic[PXA2XX_PIC_GPIO_1]);
+        qemu_irq_lower(s->irq1);
 
     if ((s->status[0] & ~3) | s->status[1] | s->status[2] | s->status[3])
-        qemu_irq_raise(s->pic[PXA2XX_PIC_GPIO_X]);
+        qemu_irq_raise(s->irqX);
     else
-        qemu_irq_lower(s->pic[PXA2XX_PIC_GPIO_X]);
+        qemu_irq_lower(s->irqX);
 }
 
 /* Bitmap of pins used as standby and sleep wake-up sources.  */
@@ -249,96 +252,89 @@ static CPUWriteMemoryFunc * const pxa2xx_gpio_writefn[] = {
     pxa2xx_gpio_write
 };
 
-static void pxa2xx_gpio_save(QEMUFile *f, void *opaque)
-{
-    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
-    int i;
-
-    qemu_put_be32(f, s->lines);
-
-    for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
-        qemu_put_be32s(f, &s->ilevel[i]);
-        qemu_put_be32s(f, &s->olevel[i]);
-        qemu_put_be32s(f, &s->dir[i]);
-        qemu_put_be32s(f, &s->rising[i]);
-        qemu_put_be32s(f, &s->falling[i]);
-        qemu_put_be32s(f, &s->status[i]);
-        qemu_put_be32s(f, &s->gafr[i * 2 + 0]);
-        qemu_put_be32s(f, &s->gafr[i * 2 + 1]);
-
-        qemu_put_be32s(f, &s->prev_level[i]);
-    }
-}
-
-static int pxa2xx_gpio_load(QEMUFile *f, void *opaque, int version_id)
+DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
+                CPUState *env, qemu_irq *pic, int lines)
 {
-    PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
-    int i;
+    DeviceState *dev;
 
-    if (qemu_get_be32(f) != s->lines)
-        return -EINVAL;
+    dev = qdev_create(NULL, "pxa2xx-gpio");
+    qdev_prop_set_int32(dev, "lines", lines);
+    qdev_prop_set_int32(dev, "ncpu", env->cpu_index);
+    qdev_init_nofail(dev);
 
-    for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
-        qemu_get_be32s(f, &s->ilevel[i]);
-        qemu_get_be32s(f, &s->olevel[i]);
-        qemu_get_be32s(f, &s->dir[i]);
-        qemu_get_be32s(f, &s->rising[i]);
-        qemu_get_be32s(f, &s->falling[i]);
-        qemu_get_be32s(f, &s->status[i]);
-        qemu_get_be32s(f, &s->gafr[i * 2 + 0]);
-        qemu_get_be32s(f, &s->gafr[i * 2 + 1]);
-
-        qemu_get_be32s(f, &s->prev_level[i]);
-    }
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[PXA2XX_PIC_GPIO_0]);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[PXA2XX_PIC_GPIO_1]);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[PXA2XX_PIC_GPIO_X]);
 
-    return 0;
+    return dev;
 }
 
-PXA2xxGPIOInfo *pxa2xx_gpio_init(target_phys_addr_t base,
-                CPUState *env, qemu_irq *pic, int lines)
+static int pxa2xx_gpio_initfn(SysBusDevice *dev)
 {
     int iomemtype;
     PXA2xxGPIOInfo *s;
 
-    s = (PXA2xxGPIOInfo *)
-            qemu_mallocz(sizeof(PXA2xxGPIOInfo));
-    memset(s, 0, sizeof(PXA2xxGPIOInfo));
-    s->pic = pic;
-    s->lines = lines;
-    s->cpu_env = env;
-    s->in = qemu_allocate_irqs(pxa2xx_gpio_set, s, lines);
+    s = FROM_SYSBUS(PXA2xxGPIOInfo, dev);
 
-    iomemtype = cpu_register_io_memory(pxa2xx_gpio_readfn,
-                    pxa2xx_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(base, 0x00001000, iomemtype);
+    s->cpu_env = qemu_get_cpu(s->ncpu);
 
-    register_savevm(NULL, "pxa2xx_gpio", 0, 0,
-                    pxa2xx_gpio_save, pxa2xx_gpio_load, s);
-
-    return s;
-}
+    qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines);
+    qdev_init_gpio_out(&dev->qdev, s->handler, s->lines);
 
-qemu_irq *pxa2xx_gpio_in_get(PXA2xxGPIOInfo *s)
-{
-    return s->in;
-}
+    iomemtype = cpu_register_io_memory(pxa2xx_gpio_readfn,
+                    pxa2xx_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
 
-void pxa2xx_gpio_out_set(PXA2xxGPIOInfo *s,
-                int line, qemu_irq handler)
-{
-    if (line >= s->lines) {
-        printf("%s: No GPIO pin %i\n", __FUNCTION__, line);
-        return;
-    }
+    sysbus_init_mmio(dev, 0x1000, iomemtype);
+    sysbus_init_irq(dev, &s->irq0);
+    sysbus_init_irq(dev, &s->irq1);
+    sysbus_init_irq(dev, &s->irqX);
 
-    s->handler[line] = handler;
+    return 0;
 }
 
 /*
  * Registers a callback to notify on GPLR reads.  This normally
  * shouldn't be needed but it is used for the hack on Spitz machines.
  */
-void pxa2xx_gpio_read_notifier(PXA2xxGPIOInfo *s, qemu_irq handler)
+void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler)
 {
+    PXA2xxGPIOInfo *s = FROM_SYSBUS(PXA2xxGPIOInfo, sysbus_from_qdev(dev));
     s->read_notify = handler;
 }
+
+static const VMStateDescription vmstate_pxa2xx_gpio_regs = {
+    .name = "pxa2xx-gpio",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_INT32(lines, PXA2xxGPIOInfo),
+        VMSTATE_UINT32_ARRAY(ilevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(olevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(dir, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(rising, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(falling, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(status, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+        VMSTATE_UINT32_ARRAY(gafr, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS * 2),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static SysBusDeviceInfo pxa2xx_gpio_info = {
+    .init       = pxa2xx_gpio_initfn,
+    .qdev.name  = "pxa2xx-gpio",
+    .qdev.desc  = "PXA2xx GPIO controller",
+    .qdev.size  = sizeof(PXA2xxGPIOInfo),
+    .qdev.props = (Property []) {
+        DEFINE_PROP_INT32("lines", PXA2xxGPIOInfo, lines, 0),
+        DEFINE_PROP_INT32("ncpu", PXA2xxGPIOInfo, ncpu, 0),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void pxa2xx_gpio_register(void)
+{
+    sysbus_register_withprop(&pxa2xx_gpio_info);
+}
+device_init(pxa2xx_gpio_register);
diff --git a/hw/spitz.c b/hw/spitz.c
index e225931..5b1e42d 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -470,10 +470,10 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
     s = FROM_SYSBUS(SpitzKeyboardState, sysbus_from_qdev(dev));
 
     for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++)
-        qdev_connect_gpio_out(dev, i, pxa2xx_gpio_in_get(cpu->gpio)[spitz_gpio_key_sense[i]]);
+        qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(cpu->gpio, spitz_gpio_key_sense[i]));
 
     for (i = 0; i < 5; i ++)
-        s->gpiomap[i] = pxa2xx_gpio_in_get(cpu->gpio)[spitz_gpiomap[i]];
+        s->gpiomap[i] = qdev_get_gpio_in(cpu->gpio, spitz_gpiomap[i]);
 
     if (!graphic_rotate)
         s->gpiomap[4] = qemu_irq_invert(s->gpiomap[4]);
@@ -482,7 +482,7 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
         qemu_set_irq(s->gpiomap[i], 0);
 
     for (i = 0; i < SPITZ_KEY_STROBE_NUM; i ++)
-        pxa2xx_gpio_out_set(cpu->gpio, spitz_gpio_key_strobe[i],
+        qdev_connect_gpio_out(cpu->gpio, spitz_gpio_key_strobe[i],
                 qdev_get_gpio_in(dev, i));
 
     qemu_mod_timer(s->kbdtimer, qemu_get_clock(vm_clock));
@@ -685,7 +685,7 @@ static void spitz_ssp_attach(PXA2xxState *cpu)
     bus = qdev_get_child_bus(mux, "ssi1");
     dev = ssi_create_slave(bus, "ads7846");
     qdev_connect_gpio_out(dev, 0,
-                          pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_TP_INT]);
+                          qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_TP_INT));
 
     bus = qdev_get_child_bus(mux, "ssi2");
     max1111 = ssi_create_slave(bus, "max1111");
@@ -693,11 +693,11 @@ static void spitz_ssp_attach(PXA2xxState *cpu)
     max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
     max111x_set_input(max1111, MAX1111_ACIN_VOLT, SPITZ_CHARGEON_ACIN);
 
-    pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_LCDCON_CS,
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_LCDCON_CS,
                         qdev_get_gpio_in(mux, 0));
-    pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_ADS7846_CS,
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ADS7846_CS,
                         qdev_get_gpio_in(mux, 1));
-    pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_MAX1111_CS,
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_MAX1111_CS,
                         qdev_get_gpio_in(mux, 2));
 }
 
@@ -747,7 +747,7 @@ static void spitz_i2c_setup(PXA2xxState *cpu)
     wm = i2c_create_slave(bus, "wm8750", 0);
 
     spitz_wm8750_addr(wm, 0, 0);
-    pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_WM,
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_WM,
                     qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
     /* .. and to the sound interface.  */
     cpu->i2s->opaque = wm;
@@ -840,7 +840,7 @@ static int spitz_hsync;
 static void spitz_lcd_hsync_handler(void *opaque, int line, int level)
 {
     PXA2xxState *cpu = (PXA2xxState *) opaque;
-    qemu_set_irq(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_HSYNC], spitz_hsync);
+    qemu_set_irq(qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_HSYNC), spitz_hsync);
     spitz_hsync ^= 1;
 }
 
@@ -860,24 +860,24 @@ static void spitz_gpio_setup(PXA2xxState *cpu, int slots)
 
     /* MMC/SD host */
     pxa2xx_mmci_handlers(cpu->mmc,
-                    pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_SD_WP],
-                    pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_SD_DETECT]);
+                    qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_SD_WP),
+                    qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_SD_DETECT));
 
     /* Battery lock always closed */
-    qemu_irq_raise(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_BAT_COVER]);
+    qemu_irq_raise(qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_BAT_COVER));
 
     /* Handle reset */
-    pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_ON_RESET, cpu->reset);
+    qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ON_RESET, cpu->reset);
 
     /* PCMCIA signals: card's IRQ and Card-Detect */
     if (slots >= 1)
         pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
-                        pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF1_IRQ],
-                        pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF1_CD]);
+                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF1_IRQ),
+                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF1_CD));
     if (slots >= 2)
         pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
-                        pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF2_IRQ],
-                        pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF2_CD]);
+                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF2_IRQ),
+                        qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF2_CD));
 }
 
 /* Board init.  */
diff --git a/hw/tosa.c b/hw/tosa.c
index 18e3be5..0bfab16 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -95,18 +95,18 @@ static void tosa_gpio_setup(PXA2xxState *cpu,
     /* MMC/SD host */
     pxa2xx_mmci_handlers(cpu->mmc,
                     qdev_get_gpio_in(scp0, TOSA_GPIO_SD_WP),
-                    qemu_irq_invert(pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_nSD_DETECT]));
+                    qemu_irq_invert(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_nSD_DETECT)));
 
     /* Handle reset */
-    pxa2xx_gpio_out_set(cpu->gpio, TOSA_GPIO_ON_RESET, cpu->reset);
+    qdev_connect_gpio_out(cpu->gpio, TOSA_GPIO_ON_RESET, cpu->reset);
 
     /* PCMCIA signals: card's IRQ and Card-Detect */
     pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
-                        pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_CF_IRQ],
-                        pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_CF_CD]);
+                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_CF_IRQ),
+                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_CF_CD));
 
     pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
-                        pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_JC_CF_IRQ],
+                        qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_JC_CF_IRQ),
                         NULL);
 
     qdev_connect_gpio_out(scp1, TOSA_GPIO_BT_LED, outsignals[0]);
@@ -220,7 +220,7 @@ static void tosa_init(ram_addr_t ram_size,
                     qemu_ram_alloc(NULL, "tosa.rom", TOSA_ROM) | IO_MEM_ROM);
 
     tmio = tc6393xb_init(0x10000000,
-            pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_TC6393XB_INT]);
+            qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_TC6393XB_INT));
 
     scp0 = sysbus_create_simple("scoop", 0x08800000, NULL);
     scp1 = sysbus_create_simple("scoop", 0x14800040, NULL);
commit 7ef4227baae2cdd460bfe714393cb8e7e4cff354
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Fri Jan 21 19:56:10 2011 +0300

    spitz: make spitz-keyboard to use qdev infrastructure
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/spitz.c b/hw/spitz.c
index ad26049..e225931 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -219,11 +219,10 @@ static const int spitz_gpiomap[5] = {
     SPITZ_GPIO_AK_INT, SPITZ_GPIO_SYNC, SPITZ_GPIO_ON_KEY,
     SPITZ_GPIO_SWA, SPITZ_GPIO_SWB,
 };
-static int spitz_gpio_invert[5] = { 0, 0, 0, 0, 0, };
 
 typedef struct {
+    SysBusDevice busdev;
     qemu_irq sense[SPITZ_KEY_SENSE_NUM];
-    qemu_irq *strobe;
     qemu_irq gpiomap[5];
     int keymap[0x80];
     uint16_t keyrow[SPITZ_KEY_SENSE_NUM];
@@ -274,8 +273,7 @@ static void spitz_keyboard_keydown(SpitzKeyboardState *s, int keycode)
 
     /* Handle the additional keys */
     if ((spitz_keycode >> 4) == SPITZ_KEY_SENSE_NUM) {
-        qemu_set_irq(s->gpiomap[spitz_keycode & 0xf], (keycode < 0x80) ^
-                        spitz_gpio_invert[spitz_keycode & 0xf]);
+        qemu_set_irq(s->gpiomap[spitz_keycode & 0xf], (keycode < 0x80));
         return;
     }
 
@@ -293,8 +291,9 @@ static void spitz_keyboard_keydown(SpitzKeyboardState *s, int keycode)
 
 #define QUEUE_KEY(c)	s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c
 
-static void spitz_keyboard_handler(SpitzKeyboardState *s, int keycode)
+static void spitz_keyboard_handler(void *opaque, int keycode)
 {
+    SpitzKeyboardState *s = opaque;
     uint16_t code;
     int mapcode;
     switch (keycode) {
@@ -440,34 +439,15 @@ static void spitz_keyboard_pre_map(SpitzKeyboardState *s)
     s->imodifiers = 0;
     s->fifopos = 0;
     s->fifolen = 0;
-    s->kbdtimer = qemu_new_timer(vm_clock, spitz_keyboard_tick, s);
-    spitz_keyboard_tick(s);
 }
 
 #undef SHIFT
 #undef CTRL
 #undef FN
 
-static void spitz_keyboard_save(QEMUFile *f, void *opaque)
+static int spitz_keyboard_post_load(void *opaque, int version_id)
 {
     SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
-    int i;
-
-    qemu_put_be16s(f, &s->sense_state);
-    qemu_put_be16s(f, &s->strobe_state);
-    for (i = 0; i < 5; i ++)
-        qemu_put_byte(f, spitz_gpio_invert[i]);
-}
-
-static int spitz_keyboard_load(QEMUFile *f, void *opaque, int version_id)
-{
-    SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
-    int i;
-
-    qemu_get_be16s(f, &s->sense_state);
-    qemu_get_be16s(f, &s->strobe_state);
-    for (i = 0; i < 5; i ++)
-        spitz_gpio_invert[i] = qemu_get_byte(f);
 
     /* Release all pressed keys */
     memset(s->keyrow, 0, sizeof(s->keyrow));
@@ -482,36 +462,55 @@ static int spitz_keyboard_load(QEMUFile *f, void *opaque, int version_id)
 
 static void spitz_keyboard_register(PXA2xxState *cpu)
 {
-    int i, j;
+    int i;
+    DeviceState *dev;
     SpitzKeyboardState *s;
 
-    s = (SpitzKeyboardState *)
-            qemu_mallocz(sizeof(SpitzKeyboardState));
-    memset(s, 0, sizeof(SpitzKeyboardState));
-
-    for (i = 0; i < 0x80; i ++)
-        s->keymap[i] = -1;
-    for (i = 0; i < SPITZ_KEY_SENSE_NUM + 1; i ++)
-        for (j = 0; j < SPITZ_KEY_STROBE_NUM; j ++)
-            if (spitz_keymap[i][j] != -1)
-                s->keymap[spitz_keymap[i][j]] = (i << 4) | j;
+    dev = sysbus_create_simple("spitz-keyboard", -1, NULL);
+    s = FROM_SYSBUS(SpitzKeyboardState, sysbus_from_qdev(dev));
 
     for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++)
-        s->sense[i] = pxa2xx_gpio_in_get(cpu->gpio)[spitz_gpio_key_sense[i]];
+        qdev_connect_gpio_out(dev, i, pxa2xx_gpio_in_get(cpu->gpio)[spitz_gpio_key_sense[i]]);
 
     for (i = 0; i < 5; i ++)
         s->gpiomap[i] = pxa2xx_gpio_in_get(cpu->gpio)[spitz_gpiomap[i]];
 
-    s->strobe = qemu_allocate_irqs(spitz_keyboard_strobe, s,
-                    SPITZ_KEY_STROBE_NUM);
+    if (!graphic_rotate)
+        s->gpiomap[4] = qemu_irq_invert(s->gpiomap[4]);
+
+    for (i = 0; i < 5; i++)
+        qemu_set_irq(s->gpiomap[i], 0);
+
     for (i = 0; i < SPITZ_KEY_STROBE_NUM; i ++)
-        pxa2xx_gpio_out_set(cpu->gpio, spitz_gpio_key_strobe[i], s->strobe[i]);
+        pxa2xx_gpio_out_set(cpu->gpio, spitz_gpio_key_strobe[i],
+                qdev_get_gpio_in(dev, i));
+
+    qemu_mod_timer(s->kbdtimer, qemu_get_clock(vm_clock));
+
+    qemu_add_kbd_event_handler(spitz_keyboard_handler, s);
+}
+
+static int spitz_keyboard_init(SysBusDevice *dev)
+{
+    SpitzKeyboardState *s;
+    int i, j;
+
+    s = FROM_SYSBUS(SpitzKeyboardState, dev);
+
+    for (i = 0; i < 0x80; i ++)
+        s->keymap[i] = -1;
+    for (i = 0; i < SPITZ_KEY_SENSE_NUM + 1; i ++)
+        for (j = 0; j < SPITZ_KEY_STROBE_NUM; j ++)
+            if (spitz_keymap[i][j] != -1)
+                s->keymap[spitz_keymap[i][j]] = (i << 4) | j;
 
     spitz_keyboard_pre_map(s);
-    qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s);
 
-    register_savevm(NULL, "spitz_keyboard", 0, 0,
-                    spitz_keyboard_save, spitz_keyboard_load, s);
+    s->kbdtimer = qemu_new_timer(vm_clock, spitz_keyboard_tick, s);
+    qdev_init_gpio_in(&dev->qdev, spitz_keyboard_strobe, SPITZ_KEY_STROBE_NUM);
+    qdev_init_gpio_out(&dev->qdev, s->sense, SPITZ_KEY_SENSE_NUM);
+
+    return 0;
 }
 
 /* LCD backlight controller */
@@ -879,18 +878,6 @@ static void spitz_gpio_setup(PXA2xxState *cpu, int slots)
         pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
                         pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF2_IRQ],
                         pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF2_CD]);
-
-    /* Initialise the screen rotation related signals */
-    spitz_gpio_invert[3] = 0;	/* Always open */
-    if (graphic_rotate) {	/* Tablet mode */
-        spitz_gpio_invert[4] = 0;
-    } else {			/* Portrait mode */
-        spitz_gpio_invert[4] = 1;
-    }
-    qemu_set_irq(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_SWA],
-                    spitz_gpio_invert[3]);
-    qemu_set_irq(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_SWB],
-                    spitz_gpio_invert[4]);
 }
 
 /* Board init.  */
@@ -1027,6 +1014,11 @@ static void spitz_machine_init(void)
 
 machine_init(spitz_machine_init);
 
+static bool is_version_0(void *opaque, int version_id)
+{
+    return version_id == 0;
+}
+
 static VMStateDescription vmstate_sl_nand_info = {
     .name = "sl-nand",
     .version_id = 0,
@@ -1051,6 +1043,30 @@ static SysBusDeviceInfo sl_nand_info = {
     },
 };
 
+static VMStateDescription vmstate_spitz_kbd = {
+    .name = "spitz-keyboard",
+    .version_id = 1,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .post_load = spitz_keyboard_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT16(sense_state, SpitzKeyboardState),
+        VMSTATE_UINT16(strobe_state, SpitzKeyboardState),
+        VMSTATE_UNUSED_TEST(is_version_0, 5),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static SysBusDeviceInfo spitz_keyboard_info = {
+    .init = spitz_keyboard_init,
+    .qdev.name = "spitz-keyboard",
+    .qdev.size = sizeof(SpitzKeyboardState),
+    .qdev.vmsd = &vmstate_spitz_kbd,
+    .qdev.props = (Property []) {
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
 static const VMStateDescription vmstate_corgi_ssp_regs = {
     .name = "corgi-ssp",
     .version_id = 1,
@@ -1094,6 +1110,7 @@ static void spitz_register_devices(void)
 {
     ssi_register_slave(&corgi_ssp_info);
     ssi_register_slave(&spitz_lcdtg_info);
+    sysbus_register_withprop(&spitz_keyboard_info);
     sysbus_register_withprop(&sl_nand_info);
 }
 
commit 34f9f0b5802a6ff9ec0be00810f7910d3935df3e
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Fri Jan 21 13:12:11 2011 +0300

    spitz: make sl-nand emulation use qdev infrastructure
    
    Switch sl-nand emulation to use qdev and vmstate. Also drop ecc_get/_put
    functions as sl-nand was the only user of that code.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/ecc.c b/hw/ecc.c
index 2fbf167..a75408b 100644
--- a/hw/ecc.c
+++ b/hw/ecc.c
@@ -74,18 +74,15 @@ void ecc_reset(ECCState *s)
 }
 
 /* Save/restore */
-void ecc_put(QEMUFile *f, ECCState *s)
-{
-    qemu_put_8s(f, &s->cp);
-    qemu_put_be16s(f, &s->lp[0]);
-    qemu_put_be16s(f, &s->lp[1]);
-    qemu_put_be16s(f, &s->count);
-}
-
-void ecc_get(QEMUFile *f, ECCState *s)
-{
-    qemu_get_8s(f, &s->cp);
-    qemu_get_be16s(f, &s->lp[0]);
-    qemu_get_be16s(f, &s->lp[1]);
-    qemu_get_be16s(f, &s->count);
-}
+VMStateDescription vmstate_ecc_state = {
+    .name = "ecc-state",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT8(cp, ECCState),
+        VMSTATE_UINT16_ARRAY(lp, ECCState, 2),
+        VMSTATE_UINT16(count, ECCState),
+        VMSTATE_END_OF_LIST(),
+    },
+};
diff --git a/hw/flash.h b/hw/flash.h
index a80205c..d7d103e 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -51,5 +51,4 @@ typedef struct {
 
 uint8_t ecc_digest(ECCState *s, uint8_t sample);
 void ecc_reset(ECCState *s);
-void ecc_put(QEMUFile *f, ECCState *s);
-void ecc_get(QEMUFile *f, ECCState *s);
+extern VMStateDescription vmstate_ecc_state;
diff --git a/hw/onenand.c b/hw/onenand.c
index d9cdcf2..71c1ab4 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -19,6 +19,7 @@
  */
 
 #include "qemu-common.h"
+#include "hw.h"
 #include "flash.h"
 #include "irq.h"
 #include "blockdev.h"
diff --git a/hw/spitz.c b/hw/spitz.c
index c7a1c60..ad26049 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -47,8 +47,11 @@
 #define FLASHCTL_NCE		(FLASHCTL_CE0 | FLASHCTL_CE1)
 
 typedef struct {
+    SysBusDevice busdev;
     NANDFlashState *nand;
     uint8_t ctl;
+    uint8_t manf_id;
+    uint8_t chip_id;
     ECCState ecc;
 } SLNANDState;
 
@@ -131,56 +134,53 @@ static void sl_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void sl_save(QEMUFile *f, void *opaque)
-{
-    SLNANDState *s = (SLNANDState *) opaque;
-
-    qemu_put_8s(f, &s->ctl);
-    ecc_put(f, &s->ecc);
-}
-
-static int sl_load(QEMUFile *f, void *opaque, int version_id)
-{
-    SLNANDState *s = (SLNANDState *) opaque;
-
-    qemu_get_8s(f, &s->ctl);
-    ecc_get(f, &s->ecc);
-
-    return 0;
-}
-
 enum {
     FLASH_128M,
     FLASH_1024M,
 };
 
+static CPUReadMemoryFunc * const sl_readfn[] = {
+    sl_readb,
+    sl_readb,
+    sl_readl,
+};
+static CPUWriteMemoryFunc * const sl_writefn[] = {
+    sl_writeb,
+    sl_writeb,
+    sl_writeb,
+};
+
 static void sl_flash_register(PXA2xxState *cpu, int size)
 {
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "sl-nand");
+
+    qdev_prop_set_uint8(dev, "manf_id", NAND_MFR_SAMSUNG);
+    if (size == FLASH_128M)
+        qdev_prop_set_uint8(dev, "chip_id", 0x73);
+    else if (size == FLASH_1024M)
+        qdev_prop_set_uint8(dev, "chip_id", 0xf1);
+
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, FLASH_BASE);
+}
+
+static int sl_nand_init(SysBusDevice *dev) {
     int iomemtype;
     SLNANDState *s;
-    CPUReadMemoryFunc * const sl_readfn[] = {
-        sl_readb,
-        sl_readb,
-        sl_readl,
-    };
-    CPUWriteMemoryFunc * const sl_writefn[] = {
-        sl_writeb,
-        sl_writeb,
-        sl_writeb,
-    };
-
-    s = (SLNANDState *) qemu_mallocz(sizeof(SLNANDState));
+
+    s = FROM_SYSBUS(SLNANDState, dev);
+
     s->ctl = 0;
-    if (size == FLASH_128M)
-        s->nand = nand_init(NAND_MFR_SAMSUNG, 0x73);
-    else if (size == FLASH_1024M)
-        s->nand = nand_init(NAND_MFR_SAMSUNG, 0xf1);
+    s->nand = nand_init(s->manf_id, s->chip_id);
 
     iomemtype = cpu_register_io_memory(sl_readfn,
                     sl_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(FLASH_BASE, 0x40, iomemtype);
 
-    register_savevm(NULL, "sl_flash", 0, 0, sl_save, sl_load, s);
+    sysbus_init_mmio(dev, 0x40, iomemtype);
+
+    return 0;
 }
 
 /* Spitz Keyboard */
@@ -1027,6 +1027,30 @@ static void spitz_machine_init(void)
 
 machine_init(spitz_machine_init);
 
+static VMStateDescription vmstate_sl_nand_info = {
+    .name = "sl-nand",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT8(ctl, SLNANDState),
+        VMSTATE_STRUCT(ecc, SLNANDState, 0, vmstate_ecc_state, ECCState),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static SysBusDeviceInfo sl_nand_info = {
+    .init = sl_nand_init,
+    .qdev.name = "sl-nand",
+    .qdev.size = sizeof(SLNANDState),
+    .qdev.vmsd = &vmstate_sl_nand_info,
+    .qdev.props = (Property []) {
+        DEFINE_PROP_UINT8("manf_id", SLNANDState, manf_id, NAND_MFR_SAMSUNG),
+        DEFINE_PROP_UINT8("chip_id", SLNANDState, chip_id, 0xf1),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
 static const VMStateDescription vmstate_corgi_ssp_regs = {
     .name = "corgi-ssp",
     .version_id = 1,
@@ -1070,6 +1094,7 @@ static void spitz_register_devices(void)
 {
     ssi_register_slave(&corgi_ssp_info);
     ssi_register_slave(&spitz_lcdtg_info);
+    sysbus_register_withprop(&sl_nand_info);
 }
 
 device_init(spitz_register_devices)
commit 43842120f482564ea2059a78ae6b8a93bb18c91d
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Thu Jan 20 18:52:28 2011 +0300

    Use vmstate to save/load spitz-lcdtg and corgi-ssp state
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/spitz.c b/hw/spitz.c
index 1e2f16b..c7a1c60 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -527,8 +527,8 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
 
 typedef struct {
     SSISlave ssidev;
-    int bl_intensity;
-    int bl_power;
+    uint32_t bl_intensity;
+    uint32_t bl_power;
 } SpitzLCDTG;
 
 static void spitz_bl_update(SpitzLCDTG *s)
@@ -592,21 +592,6 @@ static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value)
     return 0;
 }
 
-static void spitz_lcdtg_save(QEMUFile *f, void *opaque)
-{
-    SpitzLCDTG *s = (SpitzLCDTG *)opaque;
-    qemu_put_be32(f, s->bl_intensity);
-    qemu_put_be32(f, s->bl_power);
-}
-
-static int spitz_lcdtg_load(QEMUFile *f, void *opaque, int version_id)
-{
-    SpitzLCDTG *s = (SpitzLCDTG *)opaque;
-    s->bl_intensity = qemu_get_be32(f);
-    s->bl_power = qemu_get_be32(f);
-    return 0;
-}
-
 static int spitz_lcdtg_init(SSISlave *dev)
 {
     SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
@@ -615,8 +600,6 @@ static int spitz_lcdtg_init(SSISlave *dev)
     s->bl_power = 0;
     s->bl_intensity = 0x20;
 
-    register_savevm(&dev->qdev, "spitz-lcdtg", -1, 1,
-                    spitz_lcdtg_save, spitz_lcdtg_load, s);
     return 0;
 }
 
@@ -635,7 +618,7 @@ static DeviceState *max1111;
 typedef struct {
     SSISlave ssidev;
     SSIBus *bus[3];
-    int enable[3];
+    uint32_t enable[3];
 } CorgiSSPState;
 
 static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value)
@@ -677,30 +660,6 @@ static void spitz_adc_temp_on(void *opaque, int line, int level)
         max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
 }
 
-static void spitz_ssp_save(QEMUFile *f, void *opaque)
-{
-    CorgiSSPState *s = (CorgiSSPState *)opaque;
-    int i;
-
-    for (i = 0; i < 3; i++) {
-        qemu_put_be32(f, s->enable[i]);
-    }
-}
-
-static int spitz_ssp_load(QEMUFile *f, void *opaque, int version_id)
-{
-    CorgiSSPState *s = (CorgiSSPState *)opaque;
-    int i;
-
-    if (version_id != 1) {
-        return -EINVAL;
-    }
-    for (i = 0; i < 3; i++) {
-        s->enable[i] = qemu_get_be32(f);
-    }
-    return 0;
-}
-
 static int corgi_ssp_init(SSISlave *dev)
 {
     CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev);
@@ -710,8 +669,6 @@ static int corgi_ssp_init(SSISlave *dev)
     s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
     s->bus[2] = ssi_create_bus(&dev->qdev, "ssi2");
 
-    register_savevm(&dev->qdev, "spitz_ssp", -1, 1,
-                    spitz_ssp_save, spitz_ssp_load, s);
     return 0;
 }
 
@@ -1070,16 +1027,41 @@ static void spitz_machine_init(void)
 
 machine_init(spitz_machine_init);
 
+static const VMStateDescription vmstate_corgi_ssp_regs = {
+    .name = "corgi-ssp",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT32_ARRAY(enable, CorgiSSPState, 3),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
 static SSISlaveInfo corgi_ssp_info = {
     .qdev.name = "corgi-ssp",
     .qdev.size = sizeof(CorgiSSPState),
+    .qdev.vmsd = &vmstate_corgi_ssp_regs,
     .init = corgi_ssp_init,
     .transfer = corgi_ssp_transfer
 };
 
+static const VMStateDescription vmstate_spitz_lcdtg_regs = {
+    .name = "spitz-lcdtg",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT32(bl_intensity, SpitzLCDTG),
+        VMSTATE_UINT32(bl_power, SpitzLCDTG),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
 static SSISlaveInfo spitz_lcdtg_info = {
     .qdev.name = "spitz-lcdtg",
     .qdev.size = sizeof(SpitzLCDTG),
+    .qdev.vmsd = &vmstate_spitz_lcdtg_regs,
     .init = spitz_lcdtg_init,
     .transfer = spitz_lcdtg_transfer
 };
commit 383d01c663290e09d4529bf539ee9e91b75d2fec
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Thu Jan 20 18:52:27 2011 +0300

    SharpSL scoop device - convert to qdev
    
    Convert SharpSL scoop device to qdev, remove lots of supporting code, as
    lot of init and gpio related things can now be done automagically.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>

diff --git a/hw/sharpsl.h b/hw/sharpsl.h
index c5ccf79..0b3a774 100644
--- a/hw/sharpsl.h
+++ b/hw/sharpsl.h
@@ -10,13 +10,6 @@
     fprintf(stderr, "%s: " format, __FUNCTION__, ##__VA_ARGS__)
 
 /* zaurus.c */
-typedef struct ScoopInfo ScoopInfo;
-ScoopInfo *scoop_init(PXA2xxState *cpu,
-                int instance, target_phys_addr_t target_base);
-void scoop_gpio_set(void *opaque, int line, int level);
-qemu_irq *scoop_gpio_in_get(ScoopInfo *s);
-void scoop_gpio_out_set(ScoopInfo *s, int line,
-                qemu_irq handler);
 
 #define SL_PXA_PARAM_BASE	0xa0000a00
 void sl_bootparam_write(target_phys_addr_t ptr);
diff --git a/hw/spitz.c b/hw/spitz.c
index 092bb64..1e2f16b 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -23,6 +23,7 @@
 #include "audio/audio.h"
 #include "boards.h"
 #include "blockdev.h"
+#include "sysbus.h"
 
 #undef REG_FMT
 #define REG_FMT			"0x%02lx"
@@ -851,21 +852,21 @@ static void spitz_out_switch(void *opaque, int line, int level)
 #define SPITZ_SCP2_MIC_BIAS		9
 
 static void spitz_scoop_gpio_setup(PXA2xxState *cpu,
-                ScoopInfo *scp0, ScoopInfo *scp1)
+                DeviceState *scp0, DeviceState *scp1)
 {
     qemu_irq *outsignals = qemu_allocate_irqs(spitz_out_switch, cpu, 8);
 
-    scoop_gpio_out_set(scp0, SPITZ_SCP_CHRG_ON, outsignals[0]);
-    scoop_gpio_out_set(scp0, SPITZ_SCP_JK_B, outsignals[1]);
-    scoop_gpio_out_set(scp0, SPITZ_SCP_LED_GREEN, outsignals[2]);
-    scoop_gpio_out_set(scp0, SPITZ_SCP_LED_ORANGE, outsignals[3]);
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_CHRG_ON, outsignals[0]);
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_JK_B, outsignals[1]);
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_GREEN, outsignals[2]);
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_ORANGE, outsignals[3]);
 
     if (scp1) {
-        scoop_gpio_out_set(scp1, SPITZ_SCP2_BACKLIGHT_CONT, outsignals[4]);
-        scoop_gpio_out_set(scp1, SPITZ_SCP2_BACKLIGHT_ON, outsignals[5]);
+        qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_CONT, outsignals[4]);
+        qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_ON, outsignals[5]);
     }
 
-    scoop_gpio_out_set(scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]);
+    qdev_connect_gpio_out(scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]);
 }
 
 #define SPITZ_GPIO_HSYNC		22
@@ -952,7 +953,7 @@ static void spitz_common_init(ram_addr_t ram_size,
                 const char *cpu_model, enum spitz_model_e model, int arm_id)
 {
     PXA2xxState *cpu;
-    ScoopInfo *scp0, *scp1 = NULL;
+    DeviceState *scp0, *scp1 = NULL;
 
     if (!cpu_model)
         cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
@@ -970,9 +971,9 @@ static void spitz_common_init(ram_addr_t ram_size,
 
     spitz_ssp_attach(cpu);
 
-    scp0 = scoop_init(cpu, 0, 0x10800000);
+    scp0 = sysbus_create_simple("scoop", 0x10800000, NULL);
     if (model != akita) {
-	    scp1 = scoop_init(cpu, 1, 0x08800040);
+        scp1 = sysbus_create_simple("scoop", 0x08800040, NULL);
     }
 
     spitz_scoop_gpio_setup(cpu, scp0, scp1);
diff --git a/hw/tosa.c b/hw/tosa.c
index cc8ce6d..18e3be5 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -20,6 +20,7 @@
 #include "i2c.h"
 #include "ssi.h"
 #include "blockdev.h"
+#include "sysbus.h"
 
 #define TOSA_RAM    0x04000000
 #define TOSA_ROM	0x00800000
@@ -86,14 +87,14 @@ static void tosa_out_switch(void *opaque, int line, int level)
 
 
 static void tosa_gpio_setup(PXA2xxState *cpu,
-                ScoopInfo *scp0,
-                ScoopInfo *scp1,
+                DeviceState *scp0,
+                DeviceState *scp1,
                 TC6393xbState *tmio)
 {
     qemu_irq *outsignals = qemu_allocate_irqs(tosa_out_switch, cpu, 4);
     /* MMC/SD host */
     pxa2xx_mmci_handlers(cpu->mmc,
-                    scoop_gpio_in_get(scp0)[TOSA_GPIO_SD_WP],
+                    qdev_get_gpio_in(scp0, TOSA_GPIO_SD_WP),
                     qemu_irq_invert(pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_nSD_DETECT]));
 
     /* Handle reset */
@@ -108,12 +109,12 @@ static void tosa_gpio_setup(PXA2xxState *cpu,
                         pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_JC_CF_IRQ],
                         NULL);
 
-    scoop_gpio_out_set(scp1, TOSA_GPIO_BT_LED, outsignals[0]);
-    scoop_gpio_out_set(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]);
-    scoop_gpio_out_set(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]);
-    scoop_gpio_out_set(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_BT_LED, outsignals[0]);
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]);
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]);
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
 
-    scoop_gpio_out_set(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio));
+    qdev_connect_gpio_out(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio));
 }
 
 static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value)
@@ -208,7 +209,7 @@ static void tosa_init(ram_addr_t ram_size,
 {
     PXA2xxState *cpu;
     TC6393xbState *tmio;
-    ScoopInfo *scp0, *scp1;
+    DeviceState *scp0, *scp1;
 
     if (!cpu_model)
         cpu_model = "pxa255";
@@ -221,8 +222,8 @@ static void tosa_init(ram_addr_t ram_size,
     tmio = tc6393xb_init(0x10000000,
             pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_TC6393XB_INT]);
 
-    scp0 = scoop_init(cpu, 0, 0x08800000);
-    scp1 = scoop_init(cpu, 1, 0x14800040);
+    scp0 = sysbus_create_simple("scoop", 0x08800000, NULL);
+    scp1 = sysbus_create_simple("scoop", 0x14800040, NULL);
 
     tosa_gpio_setup(cpu, scp0, scp1, tmio);
 
diff --git a/hw/zaurus.c b/hw/zaurus.c
index 36be94a..fca11a5 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -18,15 +18,17 @@
 #include "hw.h"
 #include "pxa.h"
 #include "sharpsl.h"
+#include "sysbus.h"
 
 #undef REG_FMT
 #define REG_FMT			"0x%02lx"
 
 /* SCOOP devices */
 
+typedef struct ScoopInfo ScoopInfo;
 struct ScoopInfo {
+    SysBusDevice busdev;
     qemu_irq handler[16];
-    qemu_irq *in;
     uint16_t status;
     uint16_t power;
     uint32_t gpio_level;
@@ -153,7 +155,7 @@ static CPUWriteMemoryFunc * const scoop_writefn[] = {
     scoop_writeb,
 };
 
-void scoop_gpio_set(void *opaque, int line, int level)
+static void scoop_gpio_set(void *opaque, int line, int level)
 {
     ScoopInfo *s = (ScoopInfo *) opaque;
 
@@ -163,77 +165,66 @@ void scoop_gpio_set(void *opaque, int line, int level)
         s->gpio_level &= ~(1 << line);
 }
 
-qemu_irq *scoop_gpio_in_get(ScoopInfo *s)
+static int scoop_init(SysBusDevice *dev)
 {
-    return s->in;
-}
+    ScoopInfo *s = FROM_SYSBUS(ScoopInfo, dev);
+    int iomemtype;
 
-void scoop_gpio_out_set(ScoopInfo *s, int line,
-                qemu_irq handler) {
-    if (line >= 16) {
-        fprintf(stderr, "No GPIO pin %i\n", line);
-        exit(-1);
-    }
+    s->status = 0x02;
+    qdev_init_gpio_out(&s->busdev.qdev, s->handler, 16);
+    qdev_init_gpio_in(&s->busdev.qdev, scoop_gpio_set, 16);
+    iomemtype = cpu_register_io_memory(scoop_readfn,
+                    scoop_writefn, s, DEVICE_NATIVE_ENDIAN);
 
-    s->handler[line] = handler;
-}
+    sysbus_init_mmio(dev, 0x1000, iomemtype);
 
-static void scoop_save(QEMUFile *f, void *opaque)
-{
-    ScoopInfo *s = (ScoopInfo *) opaque;
-    qemu_put_be16s(f, &s->status);
-    qemu_put_be16s(f, &s->power);
-    qemu_put_be32s(f, &s->gpio_level);
-    qemu_put_be32s(f, &s->gpio_dir);
-    qemu_put_be32s(f, &s->prev_level);
-    qemu_put_be16s(f, &s->mcr);
-    qemu_put_be16s(f, &s->cdr);
-    qemu_put_be16s(f, &s->ccr);
-    qemu_put_be16s(f, &s->irr);
-    qemu_put_be16s(f, &s->imr);
-    qemu_put_be16s(f, &s->isr);
+    return 0;
 }
 
-static int scoop_load(QEMUFile *f, void *opaque, int version_id)
+static bool is_version_0 (void *opaque, int version_id)
 {
-    uint16_t dummy;
-    ScoopInfo *s = (ScoopInfo *) opaque;
-    qemu_get_be16s(f, &s->status);
-    qemu_get_be16s(f, &s->power);
-    qemu_get_be32s(f, &s->gpio_level);
-    qemu_get_be32s(f, &s->gpio_dir);
-    qemu_get_be32s(f, &s->prev_level);
-    qemu_get_be16s(f, &s->mcr);
-    qemu_get_be16s(f, &s->cdr);
-    qemu_get_be16s(f, &s->ccr);
-    qemu_get_be16s(f, &s->irr);
-    qemu_get_be16s(f, &s->imr);
-    qemu_get_be16s(f, &s->isr);
-    if (version_id < 1)
-	    qemu_get_be16s(f, &dummy);
-
-    return 0;
+    return version_id == 0;
 }
 
-ScoopInfo *scoop_init(PXA2xxState *cpu,
-		int instance,
-		target_phys_addr_t target_base) {
-    int iomemtype;
-    ScoopInfo *s;
 
-    s = (ScoopInfo *)
-            qemu_mallocz(sizeof(ScoopInfo));
-    memset(s, 0, sizeof(ScoopInfo));
+static const VMStateDescription vmstate_scoop_regs = {
+    .name = "scoop",
+    .version_id = 1,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT16(status, ScoopInfo),
+        VMSTATE_UINT16(power, ScoopInfo),
+        VMSTATE_UINT32(gpio_level, ScoopInfo),
+        VMSTATE_UINT32(gpio_dir, ScoopInfo),
+        VMSTATE_UINT32(prev_level, ScoopInfo),
+        VMSTATE_UINT16(mcr, ScoopInfo),
+        VMSTATE_UINT16(cdr, ScoopInfo),
+        VMSTATE_UINT16(ccr, ScoopInfo),
+        VMSTATE_UINT16(irr, ScoopInfo),
+        VMSTATE_UINT16(imr, ScoopInfo),
+        VMSTATE_UINT16(isr, ScoopInfo),
+        VMSTATE_UNUSED_TEST(is_version_0, 2),
+        VMSTATE_END_OF_LIST(),
+    },
+};
 
-    s->status = 0x02;
-    s->in = qemu_allocate_irqs(scoop_gpio_set, s, 16);
-    iomemtype = cpu_register_io_memory(scoop_readfn,
-                    scoop_writefn, s, DEVICE_NATIVE_ENDIAN);
-    cpu_register_physical_memory(target_base, 0x1000, iomemtype);
-    register_savevm(NULL, "scoop", instance, 1, scoop_save, scoop_load, s);
+static SysBusDeviceInfo scoop_sysbus_info = {
+    .init           = scoop_init,
+    .qdev.name      = "scoop",
+    .qdev.desc      = "Scoop2 Sharp custom ASIC",
+    .qdev.size      = sizeof(ScoopInfo),
+    .qdev.vmsd      = &vmstate_scoop_regs,
+    .qdev.props     = (Property[]) {
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
 
-    return s;
+static void scoop_register(void)
+{
+    sysbus_register_withprop(&scoop_sysbus_info);
 }
+device_init(scoop_register);
 
 /* Write the bootloader parameters memory area.  */
 
commit 4c90051801725d5bd12979a585a8da5f1eecd497
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Thu Jan 27 12:49:04 2011 +0900

    pci: typo in pcibus_get_dev_path()
    
    This patch fixes typo in pcibus_get_dev_path().
    Without this patch, the result of pcibus_get_dev_path() isn't unique.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index 712280a..d5bbba9 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -2072,7 +2072,7 @@ static char *pcibus_get_dev_path(DeviceState *dev)
     for (t = d; t; t = t->bus->parent_dev) {
         p -= slot_len;
         s = snprintf(slot, sizeof slot, ":%02x.%x",
-                     PCI_SLOT(t->devfn), PCI_FUNC(d->devfn));
+                     PCI_SLOT(t->devfn), PCI_FUNC(t->devfn));
         assert(s == slot_len);
         memcpy(p, slot, slot_len);
     }
commit bb34007e86aa2a7902ee60e0f6fa2f0e4cccbffe
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Wed Jan 26 15:55:07 2011 +0200

    pci: bridge control fixup
    
    PCI_BRIDGE_CTL_DISCARD_STATUS (bit 10 in bridge control register)
    is W1C so we should not make it writeable, otherwise the assert(!(wmask
    & w1cmask)) in pci_default_write_config() is hit
    
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
    Reported-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Tested-by: Isaku Yamahata <yamahata at valinux.co.jp>

diff --git a/hw/pci.c b/hw/pci.c
index 044c4bd..712280a 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -641,7 +641,6 @@ static void pci_init_wmask_bridge(PCIDevice *d)
                  PCI_BRIDGE_CTL_FAST_BACK |
                  PCI_BRIDGE_CTL_DISCARD |
                  PCI_BRIDGE_CTL_SEC_DISCARD |
-                 PCI_BRIDGE_CTL_DISCARD_STATUS |
                  PCI_BRIDGE_CTL_DISCARD_SERR);
     /* Below does not do anything as we never set this bit, put here for
      * completeness. */
commit 0fad6efce5d3f18278b7239dece3c251b3e7c04d
Author: Peter Maydell <peter.maydell at linaro.org>
Date:   Wed Jan 19 19:29:53 2011 +0000

    target-arm: Fix loading of scalar value for Neon multiply-by-scalar
    
    Fix the register and part of register we get the scalar from in
    the various "multiply vector by scalar" ops (VMUL by scalar
    and friends).
    
    Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 41cbb96..d95133f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3608,14 +3608,14 @@ static inline TCGv neon_get_scalar(int size, int reg)
 {
     TCGv tmp;
     if (size == 1) {
-        tmp = neon_load_reg(reg >> 1, reg & 1);
-    } else {
-        tmp = neon_load_reg(reg >> 2, (reg >> 1) & 1);
-        if (reg & 1) {
-            gen_neon_dup_low16(tmp);
-        } else {
+        tmp = neon_load_reg(reg & 7, reg >> 4);
+        if (reg & 8) {
             gen_neon_dup_high16(tmp);
+        } else {
+            gen_neon_dup_low16(tmp);
         }
+    } else {
+        tmp = neon_load_reg(reg & 15, reg >> 4);
     }
     return tmp;
 }
commit c6067f04c5bb40547f79b5c02b1cdef043b39c5f
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Wed Jan 19 15:37:58 2011 +0100

    target-arm: Fix garbage collection of temporaries in Neon emulation.
    
    Fix garbage collection of temporaries in Neon emulation.
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index f445c87..41cbb96 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4183,6 +4183,13 @@ static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
         break;
     default: abort();
     }
+
+    /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
+       Don't forget to clean them now.  */
+    if (size < 2) {
+      dead_tmp(a);
+      dead_tmp(b);
+    }
 }
 
 /* Translate a NEON data processing instruction.  Return nonzero if the
@@ -4847,7 +4854,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                 if (size == 3) {
                     tcg_temp_free_i64(tmp64);
                 } else {
-                    dead_tmp(tmp2);
+                    tcg_temp_free_i32(tmp2);
                 }
             } else if (op == 10) {
                 /* VSHLL */
@@ -5083,8 +5090,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     case 8: case 9: case 10: case 11: case 12: case 13:
                         /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
                         gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
-                        dead_tmp(tmp2);
-                        dead_tmp(tmp);
                         break;
                     case 14: /* Polynomial VMULL */
                         cpu_abort(env, "Polynomial VMULL not implemented");
@@ -5235,6 +5240,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         return 1;
 
                     tmp2 = neon_get_scalar(size, rm);
+                    /* We need a copy of tmp2 because gen_neon_mull
+                     * deletes it during pass 0.  */
+                    tmp4 = new_tmp();
+                    tcg_gen_mov_i32(tmp4, tmp2);
                     tmp3 = neon_load_reg(rn, 1);
 
                     for (pass = 0; pass < 2; pass++) {
@@ -5242,9 +5251,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                             tmp = neon_load_reg(rn, 0);
                         } else {
                             tmp = tmp3;
+                            tmp2 = tmp4;
                         }
                         gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
-                        dead_tmp(tmp);
                         if (op == 6 || op == 7) {
                             gen_neon_negl(cpu_V0, size);
                         }
@@ -5271,7 +5280,6 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
                         neon_store_reg64(cpu_V0, rd + pass);
                     }
 
-                    dead_tmp(tmp2);
 
                     break;
                 default: /* 14 and 15 are RESERVED */
commit 40d3c433606530ee1bb46ce95a6ca1cf2ee9d9c7
Author: Christophe Lyon <christophe.lyon at st.com>
Date:   Wed Jan 19 17:10:52 2011 +0100

    Support saturation with shift=0.
    
    This patch fixes corner-case saturations, when the target range is
    zero. It merely removes the guard against (sh == 0), and makes:
    __ssat(0x87654321, 1) return 0xffffffff and set the saturation flag
    __usat(0x87654321, 0) return 0 and set the saturation flag
    
    Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
    Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-arm/translate.c b/target-arm/translate.c
index c60cd18..f445c87 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6888,27 +6888,23 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                             tcg_gen_shli_i32(tmp, tmp, shift);
                         }
                         sh = (insn >> 16) & 0x1f;
-                        if (sh != 0) {
-                            tmp2 = tcg_const_i32(sh);
-                            if (insn & (1 << 22))
-                                gen_helper_usat(tmp, tmp, tmp2);
-                            else
-                                gen_helper_ssat(tmp, tmp, tmp2);
-                            tcg_temp_free_i32(tmp2);
-                        }
+                        tmp2 = tcg_const_i32(sh);
+                        if (insn & (1 << 22))
+                          gen_helper_usat(tmp, tmp, tmp2);
+                        else
+                          gen_helper_ssat(tmp, tmp, tmp2);
+                        tcg_temp_free_i32(tmp2);
                         store_reg(s, rd, tmp);
                     } else if ((insn & 0x00300fe0) == 0x00200f20) {
                         /* [us]sat16 */
                         tmp = load_reg(s, rm);
                         sh = (insn >> 16) & 0x1f;
-                        if (sh != 0) {
-                            tmp2 = tcg_const_i32(sh);
-                            if (insn & (1 << 22))
-                                gen_helper_usat16(tmp, tmp, tmp2);
-                            else
-                                gen_helper_ssat16(tmp, tmp, tmp2);
-                            tcg_temp_free_i32(tmp2);
-                        }
+                        tmp2 = tcg_const_i32(sh);
+                        if (insn & (1 << 22))
+                          gen_helper_usat16(tmp, tmp, tmp2);
+                        else
+                          gen_helper_ssat16(tmp, tmp, tmp2);
+                        tcg_temp_free_i32(tmp2);
                         store_reg(s, rd, tmp);
                     } else if ((insn & 0x00700fe0) == 0x00000fa0) {
                         /* Select bytes.  */
commit e3f114f761fd44db3b33f5d704da48392fce4ce8
Author: Alexandre Courbot <gnurou at gmail.com>
Date:   Wed Jan 26 11:57:53 2011 +0900

    target-sh4: update PTEH upon MMU exception
    
    Update the PTEH register to contain the VPN at which an MMU
    exception occured as specified by the SH4 reference.
    
    Signed-off-by: Alexandre Courbot <gnurou at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 785e9e5..d2038bd 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -453,6 +453,10 @@ int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
 
     if (ret != MMU_OK) {
 	env->tea = address;
+	if (ret != MMU_DTLB_MULTIPLE && ret != MMU_ITLB_MULTIPLE) {
+	    env->pteh = (env->pteh & PTEH_ASID_MASK) |
+		    (address & PTEH_VPN_MASK);
+	}
 	switch (ret) {
 	case MMU_ITLB_MISS:
 	case MMU_DTLB_MISS_READ:
commit bc656a296885b8be7a27f49ae827298fd1b9d153
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Jan 26 02:16:39 2011 +0100

    sh4: implement missing mmaped TLB read functions
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/sh7750.c b/hw/sh7750.c
index f76f271..19d5bf8 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -625,6 +625,7 @@ static uint32_t invalid_read(void *opaque, target_phys_addr_t addr)
 
 static uint32_t sh7750_mmct_readl(void *opaque, target_phys_addr_t addr)
 {
+    SH7750State *s = opaque;
     uint32_t ret = 0;
 
     switch (MM_REGION_TYPE(addr)) {
@@ -633,19 +634,21 @@ static uint32_t sh7750_mmct_readl(void *opaque, target_phys_addr_t addr)
         /* do nothing */
 	break;
     case MM_ITLB_ADDR:
+        ret = cpu_sh4_read_mmaped_itlb_addr(s->cpu, addr);
+        break;
     case MM_ITLB_DATA:
-        /* XXXXX */
-        abort();
-	break;
+        ret = cpu_sh4_read_mmaped_itlb_data(s->cpu, addr);
+        break;
     case MM_OCACHE_ADDR:
     case MM_OCACHE_DATA:
         /* do nothing */
 	break;
     case MM_UTLB_ADDR:
+        ret = cpu_sh4_read_mmaped_utlb_addr(s->cpu, addr);
+        break;
     case MM_UTLB_DATA:
-        /* XXXXX */
-        abort();
-	break;
+        ret = cpu_sh4_read_mmaped_utlb_data(s->cpu, addr);
+        break;
     default:
         abort();
     }
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 9eccb0c..789d188 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -201,12 +201,20 @@ void do_interrupt(CPUSH4State * env);
 void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 #if !defined(CONFIG_USER_ONLY)
 void cpu_sh4_invalidate_tlb(CPUSH4State *s);
+uint32_t cpu_sh4_read_mmaped_itlb_addr(CPUSH4State *s,
+                                       target_phys_addr_t addr);
 void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr,
                                     uint32_t mem_value);
+uint32_t cpu_sh4_read_mmaped_itlb_data(CPUSH4State *s,
+                                       target_phys_addr_t addr);
 void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, target_phys_addr_t addr,
                                     uint32_t mem_value);
+uint32_t cpu_sh4_read_mmaped_utlb_addr(CPUSH4State *s,
+                                       target_phys_addr_t addr);
 void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
                                     uint32_t mem_value);
+uint32_t cpu_sh4_read_mmaped_utlb_data(CPUSH4State *s,
+                                       target_phys_addr_t addr);
 void cpu_sh4_write_mmaped_utlb_data(CPUSH4State *s, target_phys_addr_t addr,
                                     uint32_t mem_value);
 #endif
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 4cd42b5..785e9e5 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -567,6 +567,17 @@ void cpu_load_tlb(CPUSH4State * env)
     tlb_flush(s, 1);
 }
 
+uint32_t cpu_sh4_read_mmaped_itlb_addr(CPUSH4State *s,
+                                       target_phys_addr_t addr)
+{
+    int index = (addr & 0x00000300) >> 8;
+    tlb_t * entry = &s->itlb[index];
+
+    return (entry->vpn  << 10) |
+           (entry->v    <<  8) |
+           (entry->asid);
+}
+
 void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr,
 				    uint32_t mem_value)
 {
@@ -586,6 +597,29 @@ void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr,
     entry->v = v;
 }
 
+uint32_t cpu_sh4_read_mmaped_itlb_data(CPUSH4State *s,
+                                       target_phys_addr_t addr)
+{
+    int array = (addr & 0x00800000) >> 23;
+    int index = (addr & 0x00000300) >> 8;
+    tlb_t * entry = &s->itlb[index];
+
+    if (array == 0) {
+        /* ITLB Data Array 1 */
+        return (entry->ppn << 10) |
+               (entry->v   <<  8) |
+               (entry->pr  <<  5) |
+               ((entry->sz & 1) <<  6) |
+               ((entry->sz & 2) <<  4) |
+               (entry->c   <<  3) |
+               (entry->sh  <<  1);
+    } else {
+        /* ITLB Data Array 2 */
+        return (entry->tc << 1) |
+               (entry->sa);
+    }
+}
+
 void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, target_phys_addr_t addr,
                                     uint32_t mem_value)
 {
@@ -614,6 +648,19 @@ void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, target_phys_addr_t addr,
     }
 }
 
+uint32_t cpu_sh4_read_mmaped_utlb_addr(CPUSH4State *s,
+                                       target_phys_addr_t addr)
+{
+    int index = (addr & 0x00003f00) >> 8;
+    tlb_t * entry = &s->utlb[index];
+
+    increment_urc(s); /* per utlb access */
+
+    return (entry->vpn  << 10) |
+           (entry->v    <<  8) |
+           (entry->asid);
+}
+
 void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
 				    uint32_t mem_value)
 {
@@ -686,6 +733,33 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
     }
 }
 
+uint32_t cpu_sh4_read_mmaped_utlb_data(CPUSH4State *s,
+                                       target_phys_addr_t addr)
+{
+    int array = (addr & 0x00800000) >> 23;
+    int index = (addr & 0x00003f00) >> 8;
+    tlb_t * entry = &s->utlb[index];
+
+    increment_urc(s); /* per utlb access */
+
+    if (array == 0) {
+        /* ITLB Data Array 1 */
+        return (entry->ppn << 10) |
+               (entry->v   <<  8) |
+               (entry->pr  <<  5) |
+               ((entry->sz & 1) <<  6) |
+               ((entry->sz & 2) <<  4) |
+               (entry->c   <<  3) |
+               (entry->d   <<  2) |
+               (entry->sh  <<  1) |
+               (entry->wt);
+    } else {
+        /* ITLB Data Array 2 */
+        return (entry->tc << 1) |
+               (entry->sa);
+    }
+}
+
 void cpu_sh4_write_mmaped_utlb_data(CPUSH4State *s, target_phys_addr_t addr,
                                     uint32_t mem_value)
 {
commit 9f97309a70f12df5f9104f1fcc280bceac7ea27e
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Wed Jan 26 02:07:50 2011 +0100

    sh4: implement missing mmaped TLB write functions
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/sh7750.c b/hw/sh7750.c
index 36b702f..f76f271 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -673,7 +673,7 @@ static void sh7750_mmct_writel(void *opaque, target_phys_addr_t addr,
         cpu_sh4_write_mmaped_itlb_addr(s->cpu, addr, mem_value);
         break;
     case MM_ITLB_DATA:
-        /* XXXXX */
+        cpu_sh4_write_mmaped_itlb_data(s->cpu, addr, mem_value);
         abort();
 	break;
     case MM_OCACHE_ADDR:
@@ -684,8 +684,7 @@ static void sh7750_mmct_writel(void *opaque, target_phys_addr_t addr,
         cpu_sh4_write_mmaped_utlb_addr(s->cpu, addr, mem_value);
 	break;
     case MM_UTLB_DATA:
-        /* XXXXX */
-        abort();
+        cpu_sh4_write_mmaped_utlb_data(s->cpu, addr, mem_value);
 	break;
     default:
         abort();
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 95df6d2..9eccb0c 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -202,9 +202,13 @@ void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 #if !defined(CONFIG_USER_ONLY)
 void cpu_sh4_invalidate_tlb(CPUSH4State *s);
 void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr,
-				    uint32_t mem_value);
+                                    uint32_t mem_value);
+void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, target_phys_addr_t addr,
+                                    uint32_t mem_value);
 void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
-				    uint32_t mem_value);
+                                    uint32_t mem_value);
+void cpu_sh4_write_mmaped_utlb_data(CPUSH4State *s, target_phys_addr_t addr,
+                                    uint32_t mem_value);
 #endif
 
 int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr);
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 19b309b..4cd42b5 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -574,7 +574,7 @@ void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr,
     uint8_t v = (uint8_t)((mem_value & 0x00000100) >> 8);
     uint8_t asid = (uint8_t)(mem_value & 0x000000ff);
 
-    int index = (addr & 0x00003f00) >> 8;
+    int index = (addr & 0x00000300) >> 8;
     tlb_t * entry = &s->itlb[index];
     if (entry->v) {
         /* Overwriting valid entry in itlb. */
@@ -586,6 +586,34 @@ void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr,
     entry->v = v;
 }
 
+void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, target_phys_addr_t addr,
+                                    uint32_t mem_value)
+{
+    int array = (addr & 0x00800000) >> 23;
+    int index = (addr & 0x00000300) >> 8;
+    tlb_t * entry = &s->itlb[index];
+
+    if (array == 0) {
+        /* ITLB Data Array 1 */
+        if (entry->v) {
+            /* Overwriting valid entry in utlb. */
+            target_ulong address = entry->vpn << 10;
+            tlb_flush_page(s, address);
+        }
+        entry->ppn = (mem_value & 0x1ffffc00) >> 10;
+        entry->v   = (mem_value & 0x00000100) >> 8;
+        entry->sz  = (mem_value & 0x00000080) >> 6 |
+                     (mem_value & 0x00000010) >> 4;
+        entry->pr  = (mem_value & 0x00000040) >> 5;
+        entry->c   = (mem_value & 0x00000008) >> 3;
+        entry->sh  = (mem_value & 0x00000002) >> 1;
+    } else {
+        /* ITLB Data Array 2 */
+        entry->tc  = (mem_value & 0x00000008) >> 3;
+        entry->sa  = (mem_value & 0x00000007);
+    }
+}
+
 void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
 				    uint32_t mem_value)
 {
@@ -658,6 +686,38 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
     }
 }
 
+void cpu_sh4_write_mmaped_utlb_data(CPUSH4State *s, target_phys_addr_t addr,
+                                    uint32_t mem_value)
+{
+    int array = (addr & 0x00800000) >> 23;
+    int index = (addr & 0x00003f00) >> 8;
+    tlb_t * entry = &s->utlb[index];
+
+    increment_urc(s); /* per utlb access */
+
+    if (array == 0) {
+        /* UTLB Data Array 1 */
+        if (entry->v) {
+            /* Overwriting valid entry in utlb. */
+            target_ulong address = entry->vpn << 10;
+            tlb_flush_page(s, address);
+        }
+        entry->ppn = (mem_value & 0x1ffffc00) >> 10;
+        entry->v   = (mem_value & 0x00000100) >> 8;
+        entry->sz  = (mem_value & 0x00000080) >> 6 |
+                     (mem_value & 0x00000010) >> 4;
+        entry->pr  = (mem_value & 0x00000060) >> 5;
+        entry->c   = (mem_value & 0x00000008) >> 3;
+        entry->d   = (mem_value & 0x00000004) >> 2;
+        entry->sh  = (mem_value & 0x00000002) >> 1;
+        entry->wt  = (mem_value & 0x00000001);
+    } else {
+        /* UTLB Data Array 2 */
+        entry->tc = (mem_value & 0x00000008) >> 3;
+        entry->sa = (mem_value & 0x00000007);
+    }
+}
+
 int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
 {
     int n;
commit 7f0958161056ae4e4794dfeb30bc57e432d6e8e5
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Wed Jan 26 10:36:37 2011 +0100

    etrax: Dont decrease the granularity of timers
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c
index ba1adbe..133741b 100644
--- a/hw/etraxfs_timer.c
+++ b/hw/etraxfs_timer.c
@@ -100,7 +100,6 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
     return r;
 }
 
-#define TIMER_SLOWDOWN 1
 static void update_ctrl(struct etrax_timer *t, int tnum)
 {
     unsigned int op;
@@ -142,9 +141,6 @@ static void update_ctrl(struct etrax_timer *t, int tnum)
     }
 
     D(printf ("freq_hz=%d div=%d\n", freq_hz, div));
-    div = div * TIMER_SLOWDOWN;
-    div /= 1000;
-    freq_hz /= 1000;
     ptimer_set_freq(timer, freq_hz);
     ptimer_set_limit(timer, div, 0);
 
commit 5a30b7f6f19d65c0e204bf4cabe1fb5600f3836c
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Tue Jan 25 19:47:06 2011 +0100

    cris: Replace tcg branch sequence with setcond
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-cris/translate.c b/target-cris/translate.c
index f4cc125..b4648a0 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -947,15 +947,8 @@ static void gen_tst_cc (DisasContext *dc, TCGv cc, int cond)
 		case CC_EQ:
 			if ((arith_opt || move_opt)
 			    && dc->cc_x_uptodate != (2 | X_FLAG)) {
-				/* If cc_result is zero, T0 should be 
-				   non-zero otherwise T0 should be zero.  */
-				int l1;
-				l1 = gen_new_label();
-				tcg_gen_movi_tl(cc, 0);
-				tcg_gen_brcondi_tl(TCG_COND_NE, cc_result, 
-						   0, l1);
-				tcg_gen_movi_tl(cc, 1);
-				gen_set_label(l1);
+				tcg_gen_setcond_tl(TCG_COND_EQ, cc,
+						   cc_result, tcg_const_tl(0));
 			}
 			else {
 				cris_evaluate_flags(dc);
commit bf1064b587321b1af02e444201215141bd049c97
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Jan 24 22:07:46 2011 +0100

    pulseaudio: tweak config
    
    Zap unused divisor field.
    Raise the buffer size default.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: malc <av1474 at comtv.ru>

diff --git a/audio/paaudio.c b/audio/paaudio.c
index 75e3ea0..fb4510e 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -33,13 +33,11 @@ typedef struct {
 
 static struct {
     int samples;
-    int divisor;
     char *server;
     char *sink;
     char *source;
 } conf = {
-    .samples = 1024,
-    .divisor = 2,
+    .samples = 4096,
 };
 
 static void GCC_FMT_ATTR (2, 3) qpa_logerr (int err, const char *fmt, ...)
@@ -478,12 +476,6 @@ struct audio_option qpa_options[] = {
         .descr = "buffer size in samples"
     },
     {
-        .name  = "DIVISOR",
-        .tag   = AUD_OPT_INT,
-        .valp  = &conf.divisor,
-        .descr = "threshold divisor"
-    },
-    {
         .name  = "SERVER",
         .tag   = AUD_OPT_STR,
         .valp  = &conf.server,
commit e6d16fa439aeebd34e135edd3e29d4a2db6b1a33
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Jan 24 22:07:45 2011 +0100

    pulseaudio: setup buffer attrs
    
    Request reasonable buffer sizes from pulseaudio.  Without this
    pa_simple_write() can block quite long and lead to dropouts,
    especially with guests which use small audio ring buffers.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: malc <av1474 at comtv.ru>

diff --git a/audio/paaudio.c b/audio/paaudio.c
index 858ca81..75e3ea0 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -289,6 +289,7 @@ static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
 {
     int error;
     static pa_sample_spec ss;
+    static pa_buffer_attr ba;
     struct audsettings obt_as = *as;
     PAVoiceOut *pa = (PAVoiceOut *) hw;
 
@@ -296,6 +297,15 @@ static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
     ss.channels = as->nchannels;
     ss.rate = as->freq;
 
+    /*
+     * qemu audio tick runs at 250 Hz (by default), so processing
+     * data chunks worth 4 ms of sound should be a good fit.
+     */
+    ba.tlength = pa_usec_to_bytes (4 * 1000, &ss);
+    ba.minreq = pa_usec_to_bytes (2 * 1000, &ss);
+    ba.maxlength = -1;
+    ba.prebuf = -1;
+
     obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
 
     pa->s = pa_simple_new (
@@ -306,7 +316,7 @@ static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
         "pcm.playback",
         &ss,
         NULL,                   /* channel map */
-        NULL,                   /* buffering attributes */
+        &ba,                    /* buffering attributes */
         &error
         );
     if (!pa->s) {
commit 6315633b2535dc82dc1b3403f884b81e26b4c72c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Jan 24 22:07:44 2011 +0100

    pulseaudio: process 1/4 buffer max at once
    
    Limit the size of data pieces processed by the pulseaudio worker
    threads.  Never ever process more than 1/4 of the buffer at once.
    
    Background: The buffer area currently processed by the pulseaudio thread
    is blocked, i.e. the main thread (or iothread) can't fill in more data
    there.  The buffer processing time is roughly real-time due to the
    pa_simple_write() call blocking when the output queue to the pulse
    server is full.  Thus processing big chunks at once means blocking
    a large part of the buffer for a long time.  This brings high latency
    and can lead to dropouts.
    
    When processing the buffer in smaller chunks the rpos handling becomes a
    problem though.  The thread reads hw->rpos without knowing whenever
    qpa_run_out has already seen the last (small) chunk processed and
    updated rpos accordingly.  There is no point in reading hw->rpos though,
    pa->rpos can be used instead.  We just need to take care to initialize
    pa->rpos before kicking the thread.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
    Signed-off-by: malc <av1474 at comtv.ru>

diff --git a/audio/paaudio.c b/audio/paaudio.c
index 9cf685d..858ca81 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -57,9 +57,6 @@ static void *qpa_thread_out (void *arg)
 {
     PAVoiceOut *pa = arg;
     HWVoiceOut *hw = &pa->hw;
-    int threshold;
-
-    threshold = conf.divisor ? hw->samples / conf.divisor : 0;
 
     if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
         return NULL;
@@ -73,7 +70,7 @@ static void *qpa_thread_out (void *arg)
                 goto exit;
             }
 
-            if (pa->live > threshold) {
+            if (pa->live > 0) {
                 break;
             }
 
@@ -82,8 +79,8 @@ static void *qpa_thread_out (void *arg)
             }
         }
 
-        decr = to_mix = pa->live;
-        rpos = hw->rpos;
+        decr = to_mix = audio_MIN (pa->live, conf.samples >> 2);
+        rpos = pa->rpos;
 
         if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
             return NULL;
@@ -110,8 +107,8 @@ static void *qpa_thread_out (void *arg)
             return NULL;
         }
 
-        pa->live = 0;
         pa->rpos = rpos;
+        pa->live -= decr;
         pa->decr += decr;
     }
 
@@ -152,9 +149,6 @@ static void *qpa_thread_in (void *arg)
 {
     PAVoiceIn *pa = arg;
     HWVoiceIn *hw = &pa->hw;
-    int threshold;
-
-    threshold = conf.divisor ? hw->samples / conf.divisor : 0;
 
     if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) {
         return NULL;
@@ -168,7 +162,7 @@ static void *qpa_thread_in (void *arg)
                 goto exit;
             }
 
-            if (pa->dead > threshold) {
+            if (pa->dead > 0) {
                 break;
             }
 
@@ -177,8 +171,8 @@ static void *qpa_thread_in (void *arg)
             }
         }
 
-        incr = to_grab = pa->dead;
-        wpos = hw->wpos;
+        incr = to_grab = audio_MIN (pa->dead, conf.samples >> 2);
+        wpos = pa->wpos;
 
         if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) {
             return NULL;
@@ -323,6 +317,7 @@ static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as)
     audio_pcm_init_info (&hw->info, &obt_as);
     hw->samples = conf.samples;
     pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
+    pa->rpos = hw->rpos;
     if (!pa->pcm_buf) {
         dolog ("Could not allocate buffer (%d bytes)\n",
                hw->samples << hw->info.shift);
@@ -377,6 +372,7 @@ static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as)
     audio_pcm_init_info (&hw->info, &obt_as);
     hw->samples = conf.samples;
     pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
+    pa->wpos = hw->wpos;
     if (!pa->pcm_buf) {
         dolog ("Could not allocate buffer (%d bytes)\n",
                hw->samples << hw->info.shift);
commit d00b261816872d3e48adca584fca80ca21985f3b
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Jan 21 19:53:55 2011 +0900

    monitor: use after free in do_wav_capture()
    
    use after free in do_wav_capture() on the error path.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/monitor.c b/monitor.c
index 0cda3da..c5f54f4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2509,8 +2509,9 @@ static void do_wav_capture(Monitor *mon, const QDict *qdict)
     nchannels = has_channels ? nchannels : 2;
 
     if (wav_start_capture (s, path, freq, bits, nchannels)) {
-        monitor_printf(mon, "Faied to add wave capture\n");
+        monitor_printf(mon, "Failed to add wave capture\n");
         qemu_free (s);
+        return;
     }
     QLIST_INSERT_HEAD (&capture_head, s, entries);
 }
commit 52108a1ff02263e10b20544b7637241b0920983d
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Jan 21 19:53:51 2011 +0900

    mips_fulong: remove bogus HAS_AUDIO
    
    remove bogus HAS_AUDIO according to 738012bec4c67e697e766edadab3f522c552a04d.
    
    Cc: Blue Swirl <blauwirbel at gmail.com>
    Cc: Huacai Chen <zltjiangshi at gmail.com>
    Cc: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c
index 07eb9ee..2783ed5 100644
--- a/hw/mips_fulong2e.c
+++ b/hw/mips_fulong2e.c
@@ -218,13 +218,11 @@ uint8_t eeprom_spd[0x80] = {
 };
 
 /* Audio support */
-#ifdef HAS_AUDIO
 static void audio_init (PCIBus *pci_bus)
 {
     vt82c686b_ac97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 5));
     vt82c686b_mc97_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 6));
 }
-#endif
 
 /* Network support */
 static void network_init (void)
@@ -391,9 +389,7 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device,
     }
 
     /* Sound card */
-#ifdef HAS_AUDIO
     audio_init(pci_bus);
-#endif
     /* Network card */
     network_init();
 }
commit 0dfa5ef90d0b4eebaf810a897459a009e4b1cef2
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Fri Jan 21 19:53:45 2011 +0900

    audio: consolidate audio_init()
    
    consolidate audio_init() and remove references to shoundhw.
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Acked-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/arch_init.c b/arch_init.c
index e32e289..cc56f0f 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -461,7 +461,18 @@ void qemu_service_io(void)
 }
 
 #ifdef HAS_AUDIO
-struct soundhw soundhw[] = {
+struct soundhw {
+    const char *name;
+    const char *descr;
+    int enabled;
+    int isa;
+    union {
+        int (*init_isa) (qemu_irq *pic);
+        int (*init_pci) (PCIBus *bus);
+    } init;
+};
+
+static struct soundhw soundhw[] = {
 #ifdef HAS_AUDIO_CHOICE
 #if defined(TARGET_I386) || defined(TARGET_MIPS)
     {
@@ -610,10 +621,32 @@ void select_soundhw(const char *optarg)
         }
     }
 }
+
+void audio_init(qemu_irq *isa_pic, PCIBus *pci_bus)
+{
+    struct soundhw *c;
+
+    for (c = soundhw; c->name; ++c) {
+        if (c->enabled) {
+            if (c->isa) {
+                if (isa_pic) {
+                    c->init.init_isa(isa_pic);
+                }
+            } else {
+                if (pci_bus) {
+                    c->init.init_pci(pci_bus);
+                }
+            }
+        }
+    }
+}
 #else
 void select_soundhw(const char *optarg)
 {
 }
+void audio_init(qemu_irq *isa_pic, PCIBus *pci_bus)
+{
+}
 #endif
 
 int qemu_uuid_parse(const char *str, uint8_t *uuid)
diff --git a/arch_init.h b/arch_init.h
index 682890c..17c9164 100644
--- a/arch_init.h
+++ b/arch_init.h
@@ -27,6 +27,7 @@ void do_acpitable_option(const char *optarg);
 void do_smbios_option(const char *optarg);
 void cpudef_init(void);
 int audio_available(void);
+void audio_init(qemu_irq *isa_pic, PCIBus *pci_bus);
 int kvm_available(void);
 int xen_available(void);
 
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index a7caa3f..85eba5a 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -29,7 +29,7 @@
 #include "isa.h"
 #include "fdc.h"
 #include "sysemu.h"
-#include "audio/audio.h"
+#include "arch_init.h"
 #include "boards.h"
 #include "net.h"
 #include "esp.h"
@@ -90,26 +90,6 @@ static CPUWriteMemoryFunc * const dma_dummy_write[3] = {
     dma_dummy_writeb,
 };
 
-static void audio_init(qemu_irq *pic)
-{
-    struct soundhw *c;
-    int audio_enabled = 0;
-
-    for (c = soundhw; !audio_enabled && c->name; ++c) {
-        audio_enabled = c->enabled;
-    }
-
-    if (audio_enabled) {
-        for (c = soundhw; c->name; ++c) {
-            if (c->enabled) {
-                if (c->isa) {
-                    c->init.init_isa(pic);
-                }
-            }
-        }
-    }
-}
-
 #define MAGNUM_BIOS_SIZE_MAX 0x7e000
 #define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
 
@@ -284,7 +264,7 @@ void mips_jazz_init (ram_addr_t ram_size,
 
     /* Sound card */
     /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
-    audio_init(i8259);
+    audio_init(i8259, NULL);
 
     /* NVRAM: Unprotected at 0x9000, Protected at 0xa000, Read only at 0xb000 */
     ds1225y_init(0x80009000, "nvram");
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 8755416..2d3f242 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -37,7 +37,7 @@
 #include "vmware_vga.h"
 #include "qemu-char.h"
 #include "sysemu.h"
-#include "audio/audio.h"
+#include "arch_init.h"
 #include "boards.h"
 #include "qemu-log.h"
 #include "mips-bios.h"
@@ -457,25 +457,6 @@ static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_ir
     return s;
 }
 
-/* Audio support */
-static void audio_init (PCIBus *pci_bus)
-{
-    struct soundhw *c;
-    int audio_enabled = 0;
-
-    for (c = soundhw; !audio_enabled && c->name; ++c) {
-        audio_enabled = c->enabled;
-    }
-
-    if (audio_enabled) {
-        for (c = soundhw; c->name; ++c) {
-            if (c->enabled) {
-                c->init.init_pci(pci_bus);
-            }
-        }
-    }
-}
-
 /* Network support */
 static void network_init(void)
 {
@@ -967,7 +948,7 @@ void mips_malta_init (ram_addr_t ram_size,
     fdctrl_init_isa(fd);
 
     /* Sound card */
-    audio_init(pci_bus);
+    audio_init(NULL, pci_bus);
 
     /* Network card */
     network_init();
diff --git a/hw/pc.c b/hw/pc.c
index fface7d..4dfdc0b 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -829,23 +829,6 @@ static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
 static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
 static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
-void pc_audio_init (PCIBus *pci_bus, qemu_irq *pic)
-{
-    struct soundhw *c;
-
-    for (c = soundhw; c->name; ++c) {
-        if (c->enabled) {
-            if (c->isa) {
-                c->init.init_isa(pic);
-            } else {
-                if (pci_bus) {
-                    c->init.init_pci(pci_bus);
-                }
-            }
-        }
-    }
-}
-
 void pc_init_ne2k_isa(NICInfo *nd)
 {
     static int nb_ne2k = 0;
diff --git a/hw/pc.h b/hw/pc.h
index 6852790..a048768 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -100,9 +100,6 @@ void pc_basic_device_init(qemu_irq *isa_irq,
                           FDCtrl **floppy_controller,
                           ISADevice **rtc_state);
 void pc_init_ne2k_isa(NICInfo *nd);
-#ifdef HAS_AUDIO
-void pc_audio_init (PCIBus *pci_bus, qemu_irq *pic);
-#endif
 void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
                   const char *boot_device,
                   BusState *ide0, BusState *ide1,
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index f82508d..7b74473 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -34,6 +34,7 @@
 #include "kvm.h"
 #include "sysemu.h"
 #include "sysbus.h"
+#include "arch_init.h"
 #include "blockdev.h"
 
 #define MAX_IDE_BUS 2
@@ -148,7 +149,7 @@ static void pc_init1(ram_addr_t ram_size,
         }
     }
 
-    pc_audio_init(pci_enabled ? pci_bus : NULL, isa_irq);
+    audio_init(isa_irq, pci_enabled ? pci_bus : NULL);
 
     pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
                  idebus[0], idebus[1], floppy_controller, rtc_state);
diff --git a/sysemu.h b/sysemu.h
index 0c969f2..23ae17e 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -178,21 +178,6 @@ extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
 
 #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
 
-#ifdef HAS_AUDIO
-struct soundhw {
-    const char *name;
-    const char *descr;
-    int enabled;
-    int isa;
-    union {
-        int (*init_isa) (qemu_irq *pic);
-        int (*init_pci) (PCIBus *bus);
-    } init;
-};
-
-extern struct soundhw soundhw[];
-#endif
-
 void do_usb_add(Monitor *mon, const QDict *qdict);
 void do_usb_del(Monitor *mon, const QDict *qdict);
 void usb_info(Monitor *mon);
commit bec43cc3b61d025841d550800d3835986446061d
Author: Alexandre Courbot <gnurou at gmail.com>
Date:   Tue Jan 25 14:00:14 2011 +0900

    target-sh4: fix index of address read error exception
    
    Exception index of address read error should be 0x0e0.
    
    Signed-off-by: Alexandre Courbot <gnurou at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index bee0527..19b309b 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -479,7 +479,7 @@ int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
 	    break;
 	case MMU_IADDR_ERROR:
 	case MMU_DADDR_ERROR_READ:
-	    env->exception_index = 0x0c0;
+	    env->exception_index = 0x0e0;
 	    break;
 	case MMU_DADDR_ERROR_WRITE:
 	    env->exception_index = 0x100;
commit e40a67beeda6aa6e735546e9f08f3db41e23592a
Author: Alexandre Courbot <gnurou at gmail.com>
Date:   Tue Jan 25 15:32:01 2011 +0900

    target-sh4: fix TLB invalidation code
    
    In cpu_sh4_invalidate_tlb, the UTLB was invalidated twice and the
    ITLB left unchaged, probably because of some unfortunate copy/paste.
    
    Signed-off-by: Alexandre Courbot <gnurou at gmail.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 45449ea..bee0527 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -559,8 +559,8 @@ void cpu_load_tlb(CPUSH4State * env)
         entry->v = 0;
     }
     /* ITLB */
-    for (i = 0; i < UTLB_SIZE; i++) {
-        tlb_t * entry = &s->utlb[i];
+    for (i = 0; i < ITLB_SIZE; i++) {
+        tlb_t * entry = &s->itlb[i];
         entry->v = 0;
     }
 
commit b22b7b729d2d617c49381843362bc3ef336d66ec
Merge: 4a2ba23... a5c062e...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Mon Jan 24 15:16:56 2011 -0600

    Merge remote branch 'kwolf/for-anthony' into staging

commit 4a2ba232843ac4197c586c1f0f0adbb1eb02fe34
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Mon Jan 24 12:56:56 2011 +0100

    SPARC: Add asr17 register support
    
    This register is activated by CPU_FEATURE_ASR17 in the feature field.
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 5c50d9e..6f5990b 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -267,6 +267,7 @@ typedef struct sparc_def_t {
 #define CPU_FEATURE_CMT          (1 << 12)
 #define CPU_FEATURE_GL           (1 << 13)
 #define CPU_FEATURE_TA0_SHUTDOWN (1 << 14) /* Shutdown on "ta 0x0" */
+#define CPU_FEATURE_ASR17        (1 << 15)
 #ifndef TARGET_SPARC64
 #define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP |  \
                               CPU_FEATURE_MUL | CPU_FEATURE_DIV |     \
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index ec6ac27..2f3d1e6 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -1288,7 +1288,8 @@ static const sparc_def_t sparc_defs[] = {
         .mmu_sfsr_mask = 0xffffffff,
         .mmu_trcr_mask = 0xffffffff,
         .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
+        CPU_FEATURE_ASR17,
     },
 #endif
 };
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index dff0f19..e26462e 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2067,6 +2067,17 @@ static void disas_sparc_insn(DisasContext * dc)
                 case 0x10 ... 0x1f: /* implementation-dependent in the
                                        SPARCv8 manual, rdy on the
                                        microSPARC II */
+                    /* Read Asr17 */
+                    if (rs1 == 0x11 && dc->def->features & CPU_FEATURE_ASR17) {
+                        TCGv r_const;
+
+                        /* Read Asr17 for a Leon3 monoprocessor */
+                        r_const = tcg_const_tl((1 << 8)
+                                               | (dc->def->nwindows - 1));
+                        gen_movl_TN_reg(rd, r_const);
+                        tcg_temp_free(r_const);
+                        break;
+                    }
 #endif
                     gen_movl_TN_reg(rd, cpu_y);
                     break;
commit b04d98905400aeb7dd62ce938d7eecddf2816817
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Mon Jan 24 12:56:55 2011 +0100

    SPARC: Emulation of Leon3
    
    Leon3 is an open-source VHDL System-On-Chip, well known in space industry (more
    information on http://www.gaisler.com).
    
    Leon3 is made of multiple components available in the GrLib VHDL library.
    Three devices are implemented: uart, timers and IRQ manager.
    You can find code for these peripherals in the grlib_* files.
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/Makefile.target b/Makefile.target
index cd2abde..b0ba95f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -286,7 +286,10 @@ obj-sparc-y += cirrus_vga.o
 else
 obj-sparc-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o
 obj-sparc-y += slavio_timer.o slavio_misc.o sparc32_dma.o
-obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o
+obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o
+
+# GRLIB
+obj-sparc-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o
 endif
 
 obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
diff --git a/hw/leon3.c b/hw/leon3.c
new file mode 100644
index 0000000..69d8f3b
--- /dev/null
+++ b/hw/leon3.c
@@ -0,0 +1,218 @@
+/*
+ * QEMU Leon3 System Emulator
+ *
+ * Copyright (c) 2010-2011 AdaCore
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "hw.h"
+#include "qemu-timer.h"
+#include "qemu-char.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "loader.h"
+#include "elf.h"
+#include "trace.h"
+
+#include "grlib.h"
+
+/* Default system clock.  */
+#define CPU_CLK (40 * 1000 * 1000)
+
+#define PROM_FILENAME        "u-boot.bin"
+
+#define MAX_PILS 16
+
+typedef struct ResetData {
+    CPUState *env;
+    uint32_t  entry;            /* save kernel entry in case of reset */
+} ResetData;
+
+static void main_cpu_reset(void *opaque)
+{
+    ResetData *s   = (ResetData *)opaque;
+    CPUState  *env = s->env;
+
+    cpu_reset(env);
+
+    env->halted = 0;
+    env->pc     = s->entry;
+    env->npc    = s->entry + 4;
+}
+
+static void leon3_irq_ack(void *irq_manager, int intno)
+{
+    grlib_irqmp_ack((DeviceState *)irq_manager, intno);
+    leon3_cache_control_int();
+}
+
+static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
+{
+    CPUState *env = (CPUState *)opaque;
+
+    assert(env != NULL);
+
+    env->pil_in = pil_in;
+
+    if (env->pil_in && (env->interrupt_index == 0 ||
+                        (env->interrupt_index & ~15) == TT_EXTINT)) {
+        unsigned int i;
+
+        for (i = 15; i > 0; i--) {
+            if (env->pil_in & (1 << i)) {
+                int old_interrupt = env->interrupt_index;
+
+                env->interrupt_index = TT_EXTINT | i;
+                if (old_interrupt != env->interrupt_index) {
+                    trace_leon3_set_irq(i);
+                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
+                }
+                break;
+            }
+        }
+    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
+        trace_leon3_reset_irq(env->interrupt_index & 15);
+        env->interrupt_index = 0;
+        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+    }
+}
+
+static void leon3_generic_hw_init(ram_addr_t  ram_size,
+                                  const char *boot_device,
+                                  const char *kernel_filename,
+                                  const char *kernel_cmdline,
+                                  const char *initrd_filename,
+                                  const char *cpu_model)
+{
+    CPUState   *env;
+    ram_addr_t  ram_offset, prom_offset;
+    int         ret;
+    char       *filename;
+    qemu_irq   *cpu_irqs = NULL;
+    int         bios_size;
+    int         prom_size;
+    ResetData  *reset_info;
+
+    /* Init CPU */
+    if (!cpu_model) {
+        cpu_model = "LEON3";
+    }
+
+    env = cpu_init(cpu_model);
+    if (!env) {
+        fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n");
+        exit(1);
+    }
+
+    cpu_sparc_set_id(env, 0);
+
+    /* Reset data */
+    reset_info        = qemu_mallocz(sizeof(ResetData));
+    reset_info->env   = env;
+    qemu_register_reset(main_cpu_reset, reset_info);
+
+    /* Allocate IRQ manager */
+    grlib_irqmp_create(0x80000200, env, &cpu_irqs, MAX_PILS, &leon3_set_pil_in);
+
+    env->qemu_irq_ack = leon3_irq_ack;
+
+    /* Allocate RAM */
+    if ((uint64_t)ram_size > (1UL << 30)) {
+        fprintf(stderr,
+                "qemu: Too much memory for this machine: %d, maximum 1G\n",
+                (unsigned int)(ram_size / (1024 * 1024)));
+        exit(1);
+    }
+
+    ram_offset = qemu_ram_alloc(NULL, "leon3.ram", ram_size);
+    cpu_register_physical_memory(0x40000000, ram_size, ram_offset | IO_MEM_RAM);
+
+    /* Allocate BIOS */
+    prom_size = 8 * 1024 * 1024; /* 8Mb */
+    prom_offset = qemu_ram_alloc(NULL, "Leon3.bios", prom_size);
+    cpu_register_physical_memory(0x00000000, prom_size,
+                                 prom_offset | IO_MEM_ROM);
+
+    /* Load boot prom */
+    if (bios_name == NULL) {
+        bios_name = PROM_FILENAME;
+    }
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+
+    bios_size = get_image_size(filename);
+
+    if (bios_size > prom_size) {
+        fprintf(stderr, "qemu: could not load prom '%s': file too big\n",
+                filename);
+        exit(1);
+    }
+
+    if (bios_size > 0) {
+        ret = load_image_targphys(filename, 0x00000000, bios_size);
+        if (ret < 0 || ret > prom_size) {
+            fprintf(stderr, "qemu: could not load prom '%s'\n", filename);
+            exit(1);
+        }
+    } else if (kernel_filename == NULL) {
+        fprintf(stderr, "Can't read bios image %s\n", filename);
+        exit(1);
+    }
+
+    /* Can directly load an application. */
+    if (kernel_filename != NULL) {
+        long     kernel_size;
+        uint64_t entry;
+
+        kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL,
+                               1 /* big endian */, ELF_MACHINE, 0);
+        if (kernel_size < 0) {
+            fprintf(stderr, "qemu: could not load kernel '%s'\n",
+                    kernel_filename);
+            exit(1);
+        }
+        if (bios_size <= 0) {
+            /* If there is no bios/monitor, start the application.  */
+            env->pc = entry;
+            env->npc = entry + 4;
+            reset_info->entry = entry;
+        }
+    }
+
+    /* Allocate timers */
+    grlib_gptimer_create(0x80000300, 2, CPU_CLK, cpu_irqs, 6);
+
+    /* Allocate uart */
+    if (serial_hds[0]) {
+        grlib_apbuart_create(0x80000100, serial_hds[0], cpu_irqs[3]);
+    }
+}
+
+QEMUMachine leon3_generic_machine = {
+    .name     = "leon3_generic",
+    .desc     = "Leon-3 generic",
+    .init     = leon3_generic_hw_init,
+    .use_scsi = 0,
+};
+
+static void leon3_machine_init(void)
+{
+    qemu_register_machine(&leon3_generic_machine);
+}
+
+machine_init(leon3_machine_init);
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 7225b2e..5c50d9e 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -252,20 +252,21 @@ typedef struct sparc_def_t {
     uint32_t maxtl;
 } sparc_def_t;
 
-#define CPU_FEATURE_FLOAT    (1 << 0)
-#define CPU_FEATURE_FLOAT128 (1 << 1)
-#define CPU_FEATURE_SWAP     (1 << 2)
-#define CPU_FEATURE_MUL      (1 << 3)
-#define CPU_FEATURE_DIV      (1 << 4)
-#define CPU_FEATURE_FLUSH    (1 << 5)
-#define CPU_FEATURE_FSQRT    (1 << 6)
-#define CPU_FEATURE_FMUL     (1 << 7)
-#define CPU_FEATURE_VIS1     (1 << 8)
-#define CPU_FEATURE_VIS2     (1 << 9)
-#define CPU_FEATURE_FSMULD   (1 << 10)
-#define CPU_FEATURE_HYPV     (1 << 11)
-#define CPU_FEATURE_CMT      (1 << 12)
-#define CPU_FEATURE_GL       (1 << 13)
+#define CPU_FEATURE_FLOAT        (1 << 0)
+#define CPU_FEATURE_FLOAT128     (1 << 1)
+#define CPU_FEATURE_SWAP         (1 << 2)
+#define CPU_FEATURE_MUL          (1 << 3)
+#define CPU_FEATURE_DIV          (1 << 4)
+#define CPU_FEATURE_FLUSH        (1 << 5)
+#define CPU_FEATURE_FSQRT        (1 << 6)
+#define CPU_FEATURE_FMUL         (1 << 7)
+#define CPU_FEATURE_VIS1         (1 << 8)
+#define CPU_FEATURE_VIS2         (1 << 9)
+#define CPU_FEATURE_FSMULD       (1 << 10)
+#define CPU_FEATURE_HYPV         (1 << 11)
+#define CPU_FEATURE_CMT          (1 << 12)
+#define CPU_FEATURE_GL           (1 << 13)
+#define CPU_FEATURE_TA0_SHUTDOWN (1 << 14) /* Shutdown on "ta 0x0" */
 #ifndef TARGET_SPARC64
 #define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP |  \
                               CPU_FEATURE_MUL | CPU_FEATURE_DIV |     \
@@ -437,6 +438,12 @@ typedef struct CPUSPARCState {
 #define SOFTINT_REG_MASK (SOFTINT_STIMER|SOFTINT_INTRMASK|SOFTINT_TIMER)
 #endif
     sparc_def_t *def;
+
+    void *irq_manager;
+    void (*qemu_irq_ack) (void *irq_manager, int intno);
+
+    /* Leon3 cache control */
+    uint32_t cache_control;
 } CPUSPARCState;
 
 #ifndef NO_CPU_IO_DEFS
@@ -469,6 +476,8 @@ int cpu_cwp_inc(CPUState *env1, int cwp);
 int cpu_cwp_dec(CPUState *env1, int cwp);
 void cpu_set_cwp(CPUState *env1, int new_cwp);
 
+void leon3_cache_control_int(void);
+
 /* sun4m.c, sun4u.c */
 void cpu_check_irqs(CPUSPARCState *env);
 
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 6b337ca..ec6ac27 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -770,6 +770,7 @@ void cpu_reset(CPUSPARCState *env)
     env->pc = 0;
     env->npc = env->pc + 4;
 #endif
+    env->cache_control = 0;
 }
 
 static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
@@ -1274,20 +1275,20 @@ static const sparc_def_t sparc_defs[] = {
         .mmu_sfsr_mask = 0xffffffff,
         .mmu_trcr_mask = 0xffffffff,
         .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
     },
     {
         .name = "LEON3",
         .iu_version = 0xf3000000,
         .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
         .mmu_version = 0xf3000000,
-        .mmu_bm = 0x00004000,
+        .mmu_bm = 0x00000000,
         .mmu_ctpr_mask = 0x007ffff0,
         .mmu_cxr_mask = 0x0000003f,
         .mmu_sfsr_mask = 0xffffffff,
         .mmu_trcr_mask = 0xffffffff,
         .nwindows = 8,
-        .features = CPU_DEFAULT_FEATURES,
+        .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
     },
 #endif
 };
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index e6d82f9..12e8557 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -85,6 +85,7 @@ DEF_HELPER_0(fcmpeq_fcc2, void)
 DEF_HELPER_0(fcmpeq_fcc3, void)
 #endif
 DEF_HELPER_1(raise_exception, void, int)
+DEF_HELPER_0(shutdown, void)
 #define F_HELPER_0_0(name) DEF_HELPER_0(f ## name, void)
 #define F_HELPER_DQ_0_0(name)                   \
     F_HELPER_0_0(name ## d);                    \
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index b70970a..d3e1b63 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -1,6 +1,7 @@
 #include "exec.h"
 #include "host-utils.h"
 #include "helper.h"
+#include "sysemu.h"
 
 //#define DEBUG_MMU
 //#define DEBUG_MXCC
@@ -9,6 +10,7 @@
 //#define DEBUG_ASI
 //#define DEBUG_PCALL
 //#define DEBUG_PSTATE
+//#define DEBUG_CACHE_CONTROL
 
 #ifdef DEBUG_MMU
 #define DPRINTF_MMU(fmt, ...)                                   \
@@ -36,6 +38,13 @@
 #define DPRINTF_PSTATE(fmt, ...) do {} while (0)
 #endif
 
+#ifdef DEBUG_CACHE_CONTROL
+#define DPRINTF_CACHE_CONTROL(fmt, ...)                                   \
+    do { printf("CACHE_CONTROL: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF_CACHE_CONTROL(fmt, ...) do {} while (0)
+#endif
+
 #ifdef TARGET_SPARC64
 #ifndef TARGET_ABI32
 #define AM_CHECK(env1) ((env1)->pstate & PS_AM)
@@ -49,6 +58,27 @@
 #define QT0 (env->qt0)
 #define QT1 (env->qt1)
 
+/* Leon3 cache control */
+
+/* Cache control: emulate the behavior of cache control registers but without
+   any effect on the emulated */
+
+#define CACHE_STATE_MASK 0x3
+#define CACHE_DISABLED   0x0
+#define CACHE_FROZEN     0x1
+#define CACHE_ENABLED    0x3
+
+/* Cache Control register fields */
+
+#define CACHE_CTRL_IF (1 <<  4)  /* Instruction Cache Freeze on Interrupt */
+#define CACHE_CTRL_DF (1 <<  5)  /* Data Cache Freeze on Interrupt */
+#define CACHE_CTRL_DP (1 << 14)  /* Data cache flush pending */
+#define CACHE_CTRL_IP (1 << 15)  /* Instruction cache flush pending */
+#define CACHE_CTRL_IB (1 << 16)  /* Instruction burst fetch */
+#define CACHE_CTRL_FI (1 << 21)  /* Flush Instruction cache (Write only) */
+#define CACHE_CTRL_FD (1 << 22)  /* Flush Data cache (Write only) */
+#define CACHE_CTRL_DS (1 << 23)  /* Data cache snoop enable */
+
 #if defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
 static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
                           int is_asi, int size);
@@ -294,6 +324,13 @@ void HELPER(raise_exception)(int tt)
     raise_exception(tt);
 }
 
+void helper_shutdown(void)
+{
+#if !defined(CONFIG_USER_ONLY)
+    qemu_system_shutdown_request();
+#endif
+}
+
 void helper_check_align(target_ulong addr, uint32_t align)
 {
     if (addr & align) {
@@ -1612,6 +1649,103 @@ static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
 
 #ifndef TARGET_SPARC64
 #ifndef CONFIG_USER_ONLY
+
+
+/* Leon3 cache control */
+
+void leon3_cache_control_int(void)
+{
+    uint32_t state = 0;
+
+    if (env->cache_control & CACHE_CTRL_IF) {
+        /* Instruction cache state */
+        state = env->cache_control & CACHE_STATE_MASK;
+        if (state == CACHE_ENABLED) {
+            state = CACHE_FROZEN;
+            DPRINTF_CACHE_CONTROL("Instruction cache: freeze\n");
+        }
+
+        env->cache_control &= ~CACHE_STATE_MASK;
+        env->cache_control |= state;
+    }
+
+    if (env->cache_control & CACHE_CTRL_DF) {
+        /* Data cache state */
+        state = (env->cache_control >> 2) & CACHE_STATE_MASK;
+        if (state == CACHE_ENABLED) {
+            state = CACHE_FROZEN;
+            DPRINTF_CACHE_CONTROL("Data cache: freeze\n");
+        }
+
+        env->cache_control &= ~(CACHE_STATE_MASK << 2);
+        env->cache_control |= (state << 2);
+    }
+}
+
+static void leon3_cache_control_st(target_ulong addr, uint64_t val, int size)
+{
+    DPRINTF_CACHE_CONTROL("st addr:%08x, val:%" PRIx64 ", size:%d\n",
+                          addr, val, size);
+
+    if (size != 4) {
+        DPRINTF_CACHE_CONTROL("32bits only\n");
+        return;
+    }
+
+    switch (addr) {
+    case 0x00:              /* Cache control */
+
+        /* These values must always be read as zeros */
+        val &= ~CACHE_CTRL_FD;
+        val &= ~CACHE_CTRL_FI;
+        val &= ~CACHE_CTRL_IB;
+        val &= ~CACHE_CTRL_IP;
+        val &= ~CACHE_CTRL_DP;
+
+        env->cache_control = val;
+        break;
+    case 0x04:              /* Instruction cache configuration */
+    case 0x08:              /* Data cache configuration */
+        /* Read Only */
+        break;
+    default:
+        DPRINTF_CACHE_CONTROL("write unknown register %08x\n", addr);
+        break;
+    };
+}
+
+static uint64_t leon3_cache_control_ld(target_ulong addr, int size)
+{
+    uint64_t ret = 0;
+
+    if (size != 4) {
+        DPRINTF_CACHE_CONTROL("32bits only\n");
+        return 0;
+    }
+
+    switch (addr) {
+    case 0x00:              /* Cache control */
+        ret = env->cache_control;
+        break;
+
+        /* Configuration registers are read and only always keep those
+           predefined values */
+
+    case 0x04:              /* Instruction cache configuration */
+        ret = 0x10220000;
+        break;
+    case 0x08:              /* Data cache configuration */
+        ret = 0x18220000;
+        break;
+    default:
+        DPRINTF_CACHE_CONTROL("read unknown register %08x\n", addr);
+        break;
+    };
+    DPRINTF_CACHE_CONTROL("st addr:%08x, ret:%" PRIx64 ", size:%d\n",
+                          addr, ret, size);
+    return ret;
+}
+
 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
 {
     uint64_t ret = 0;
@@ -1621,8 +1755,13 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
 
     helper_check_align(addr, size - 1);
     switch (asi) {
-    case 2: /* SuperSparc MXCC registers */
+    case 2: /* SuperSparc MXCC registers and Leon3 cache control */
         switch (addr) {
+        case 0x00:          /* Leon3 Cache Control */
+        case 0x08:          /* Leon3 Instruction Cache config */
+        case 0x0C:          /* Leon3 Date Cache config */
+            ret = leon3_cache_control_ld(addr, size);
+            break;
         case 0x01c00a00: /* MXCC control register */
             if (size == 8)
                 ret = env->mxccregs[3];
@@ -1850,8 +1989,14 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
 {
     helper_check_align(addr, size - 1);
     switch(asi) {
-    case 2: /* SuperSparc MXCC registers */
+    case 2: /* SuperSparc MXCC registers and Leon3 cache control */
         switch (addr) {
+        case 0x00:          /* Leon3 Cache Control */
+        case 0x08:          /* Leon3 Instruction Cache config */
+        case 0x0C:          /* Leon3 Date Cache config */
+            leon3_cache_control_st(addr, val, size);
+            break;
+
         case 0x01c00000: /* MXCC stream data register 0 */
             if (size == 8)
                 env->mxccdata[0] = val;
@@ -4177,6 +4322,13 @@ void do_interrupt(CPUState *env)
     env->pc = env->tbr;
     env->npc = env->pc + 4;
     env->exception_index = -1;
+
+#if !defined(CONFIG_USER_ONLY)
+    /* IRQ acknowledgment */
+    if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
+        env->qemu_irq_ack(env->irq_manager, intno);
+    }
+#endif
 }
 #endif
 
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 21c5675..dff0f19 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1997,8 +1997,9 @@ static void disas_sparc_insn(DisasContext * dc)
                     } else
                         tcg_gen_mov_tl(cpu_dst, cpu_src1);
                 }
+
                 cond = GET_FIELD(insn, 3, 6);
-                if (cond == 0x8) {
+                if (cond == 0x8) { /* Trap Always */
                     save_state(dc, cpu_cond);
                     if ((dc->def->features & CPU_FEATURE_HYPV) &&
                         supervisor(dc))
@@ -2007,7 +2008,15 @@ static void disas_sparc_insn(DisasContext * dc)
                         tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
                     tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
                     tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
-                    gen_helper_raise_exception(cpu_tmp32);
+
+                    if (rs2 == 0 &&
+                        dc->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
+
+                        gen_helper_shutdown();
+
+                    } else {
+                        gen_helper_raise_exception(cpu_tmp32);
+                    }
                 } else if (cond != 0) {
                     TCGv r_cond = tcg_temp_new();
                     int l1;
diff --git a/trace-events b/trace-events
index 8e8573e..c75a7a9 100644
--- a/trace-events
+++ b/trace-events
@@ -244,3 +244,7 @@ disable grlib_irqmp_unknown_register(const char *op, uint64_t val) "%s unknown r
 # hw/grlib_apbuart.c
 disable grlib_apbuart_event(int event) "event:%d"
 disable grlib_apbuart_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
+
+# hw/leon3.c
+disable leon3_set_irq(int intno) "Set CPU IRQ %d"
+disable leon3_reset_irq(int intno) "Reset CPU IRQ %d"
commit 8b1e1320748f0aca2319ee272f106ca41a7580a2
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Mon Jan 24 12:56:54 2011 +0100

    SPARC: Emulation of GRLIB APB UART
    
    This device exposes one parameter:
     - chardev (ptr) : Pointer to a qemu character device
    
    Emulation of GrLib devices is base on the GRLIB IP Core User's Manual:
    http://www.gaisler.com/products/grlib/grip.pdf
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/grlib.h b/hw/grlib.h
index f92d6d3..fdf4b11 100644
--- a/hw/grlib.h
+++ b/hw/grlib.h
@@ -100,4 +100,27 @@ DeviceState *grlib_gptimer_create(target_phys_addr_t  base,
     return dev;
 }
 
+/* APB UART */
+
+static inline
+DeviceState *grlib_apbuart_create(target_phys_addr_t  base,
+                                  CharDriverState    *serial,
+                                  qemu_irq            irq)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "grlib,apbuart");
+    qdev_prop_set_chr(dev, "chrdev", serial);
+
+    if (qdev_init(dev)) {
+        return NULL;
+    }
+
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+
+    return dev;
+}
+
 #endif /* ! _GRLIB_H_ */
diff --git a/hw/grlib_apbuart.c b/hw/grlib_apbuart.c
new file mode 100644
index 0000000..101b150
--- /dev/null
+++ b/hw/grlib_apbuart.c
@@ -0,0 +1,187 @@
+/*
+ * QEMU GRLIB APB UART Emulator
+ *
+ * Copyright (c) 2010-2011 AdaCore
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+
+#include "trace.h"
+
+#define UART_REG_SIZE 20     /* Size of memory mapped registers */
+
+/* UART status register fields */
+#define UART_DATA_READY           (1 <<  0)
+#define UART_TRANSMIT_SHIFT_EMPTY (1 <<  1)
+#define UART_TRANSMIT_FIFO_EMPTY  (1 <<  2)
+#define UART_BREAK_RECEIVED       (1 <<  3)
+#define UART_OVERRUN              (1 <<  4)
+#define UART_PARITY_ERROR         (1 <<  5)
+#define UART_FRAMING_ERROR        (1 <<  6)
+#define UART_TRANSMIT_FIFO_HALF   (1 <<  7)
+#define UART_RECEIVE_FIFO_HALF    (1 <<  8)
+#define UART_TRANSMIT_FIFO_FULL   (1 <<  9)
+#define UART_RECEIVE_FIFO_FULL    (1 << 10)
+
+/* UART control register fields */
+#define UART_RECEIVE_ENABLE          (1 <<  0)
+#define UART_TRANSMIT_ENABLE         (1 <<  1)
+#define UART_RECEIVE_INTERRUPT       (1 <<  2)
+#define UART_TRANSMIT_INTERRUPT      (1 <<  3)
+#define UART_PARITY_SELECT           (1 <<  4)
+#define UART_PARITY_ENABLE           (1 <<  5)
+#define UART_FLOW_CONTROL            (1 <<  6)
+#define UART_LOOPBACK                (1 <<  7)
+#define UART_EXTERNAL_CLOCK          (1 <<  8)
+#define UART_RECEIVE_FIFO_INTERRUPT  (1 <<  9)
+#define UART_TRANSMIT_FIFO_INTERRUPT (1 << 10)
+#define UART_FIFO_DEBUG_MODE         (1 << 11)
+#define UART_OUTPUT_ENABLE           (1 << 12)
+#define UART_FIFO_AVAILABLE          (1 << 31)
+
+/* Memory mapped register offsets */
+#define DATA_OFFSET       0x00
+#define STATUS_OFFSET     0x04
+#define CONTROL_OFFSET    0x08
+#define SCALER_OFFSET     0x0C  /* not supported */
+#define FIFO_DEBUG_OFFSET 0x10  /* not supported */
+
+typedef struct UART {
+    SysBusDevice busdev;
+
+    qemu_irq irq;
+
+    CharDriverState *chr;
+
+    /* registers */
+    uint32_t receive;
+    uint32_t status;
+    uint32_t control;
+} UART;
+
+static int grlib_apbuart_can_receive(void *opaque)
+{
+    UART *uart = opaque;
+
+    return !!(uart->status & UART_DATA_READY);
+}
+
+static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size)
+{
+    UART *uart = opaque;
+
+    uart->receive  = *buf;
+    uart->status  |= UART_DATA_READY;
+
+    if (uart->control & UART_RECEIVE_INTERRUPT) {
+        qemu_irq_pulse(uart->irq);
+    }
+}
+
+static void grlib_apbuart_event(void *opaque, int event)
+{
+    trace_grlib_apbuart_event(event);
+}
+
+static void
+grlib_apbuart_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    UART          *uart = opaque;
+    unsigned char  c    = 0;
+
+    addr &= 0xff;
+
+    /* Unit registers */
+    switch (addr) {
+    case DATA_OFFSET:
+        c = value & 0xFF;
+        qemu_chr_write(uart->chr, &c, 1);
+        return;
+
+    case STATUS_OFFSET:
+        /* Read Only */
+        return;
+
+    case CONTROL_OFFSET:
+        /* Not supported */
+        return;
+
+    case SCALER_OFFSET:
+        /* Not supported */
+        return;
+
+    default:
+        break;
+    }
+
+    trace_grlib_apbuart_unknown_register("write", addr);
+}
+
+static CPUReadMemoryFunc * const grlib_apbuart_read[] = {
+    NULL, NULL, NULL,
+};
+
+static CPUWriteMemoryFunc * const grlib_apbuart_write[] = {
+    NULL, NULL, grlib_apbuart_writel,
+};
+
+static int grlib_apbuart_init(SysBusDevice *dev)
+{
+    UART *uart      = FROM_SYSBUS(typeof(*uart), dev);
+    int   uart_regs = 0;
+
+    qemu_chr_add_handlers(uart->chr,
+                          grlib_apbuart_can_receive,
+                          grlib_apbuart_receive,
+                          grlib_apbuart_event,
+                          uart);
+
+    sysbus_init_irq(dev, &uart->irq);
+
+    uart_regs = cpu_register_io_memory(grlib_apbuart_read,
+                                       grlib_apbuart_write,
+                                       uart, DEVICE_NATIVE_ENDIAN);
+    if (uart_regs < 0) {
+        return -1;
+    }
+
+    sysbus_init_mmio(dev, UART_REG_SIZE, uart_regs);
+
+    return 0;
+}
+
+static SysBusDeviceInfo grlib_gptimer_info = {
+    .init       = grlib_apbuart_init,
+    .qdev.name  = "grlib,apbuart",
+    .qdev.size  = sizeof(UART),
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_CHR("chrdev", UART, chr),
+        DEFINE_PROP_END_OF_LIST()
+    }
+};
+
+static void grlib_gptimer_register(void)
+{
+    sysbus_register_withprop(&grlib_gptimer_info);
+}
+
+device_init(grlib_gptimer_register)
diff --git a/trace-events b/trace-events
index 832b561..8e8573e 100644
--- a/trace-events
+++ b/trace-events
@@ -240,3 +240,7 @@ disable grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uin
 disable grlib_irqmp_ack(int intno) "interrupt:%d"
 disable grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d"
 disable grlib_irqmp_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
+
+# hw/grlib_apbuart.c
+disable grlib_apbuart_event(int event) "event:%d"
+disable grlib_apbuart_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
commit 3f10bcbb647372f888a9e34f428eb6f0225c38ca
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Mon Jan 24 12:56:53 2011 +0100

    SPARC: Emulation of GRLIB IRQMP
    
    This device exposes two parameters:
     - set_pil_in        (ptr) : A function to set the pil_in of the SPARC CPU
     - set_pil_in_opaque (ptr) : Opaque argument of the set_pil_in function
    
    Emulation of GrLib devices is base on the GRLIB IP Core User's Manual:
    http://www.gaisler.com/products/grlib/grip.pdf
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/grlib.h b/hw/grlib.h
index 776acf9..f92d6d3 100644
--- a/hw/grlib.h
+++ b/hw/grlib.h
@@ -32,6 +32,44 @@
  * http://www.gaisler.com/products/grlib/grip.pdf
  */
 
+/* IRQMP */
+
+typedef void (*set_pil_in_fn) (void *opaque, uint32_t pil_in);
+
+void grlib_irqmp_set_irq(void *opaque, int irq, int level);
+
+void grlib_irqmp_ack(DeviceState *dev, int intno);
+
+static inline
+DeviceState *grlib_irqmp_create(target_phys_addr_t   base,
+                                CPUState            *env,
+                                qemu_irq           **cpu_irqs,
+                                uint32_t             nr_irqs,
+                                set_pil_in_fn        set_pil_in)
+{
+    DeviceState *dev;
+
+    assert(cpu_irqs != NULL);
+
+    dev = qdev_create(NULL, "grlib,irqmp");
+    qdev_prop_set_ptr(dev, "set_pil_in", set_pil_in);
+    qdev_prop_set_ptr(dev, "set_pil_in_opaque", env);
+
+    if (qdev_init(dev)) {
+        return NULL;
+    }
+
+    env->irq_manager = dev;
+
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+
+    *cpu_irqs = qemu_allocate_irqs(grlib_irqmp_set_irq,
+                                   dev,
+                                   nr_irqs);
+
+    return dev;
+}
+
 /* GPTimer */
 
 static inline
diff --git a/hw/grlib_irqmp.c b/hw/grlib_irqmp.c
new file mode 100644
index 0000000..f47c491
--- /dev/null
+++ b/hw/grlib_irqmp.c
@@ -0,0 +1,376 @@
+/*
+ * QEMU GRLIB IRQMP Emulator
+ *
+ * (Multiprocessor and extended interrupt not supported)
+ *
+ * Copyright (c) 2010-2011 AdaCore
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "cpu.h"
+
+#include "grlib.h"
+
+#include "trace.h"
+
+#define IRQMP_MAX_CPU 16
+#define IRQMP_REG_SIZE 256      /* Size of memory mapped registers */
+
+/* Memory mapped register offsets */
+#define LEVEL_OFFSET     0x00
+#define PENDING_OFFSET   0x04
+#define FORCE0_OFFSET    0x08
+#define CLEAR_OFFSET     0x0C
+#define MP_STATUS_OFFSET 0x10
+#define BROADCAST_OFFSET 0x14
+#define MASK_OFFSET      0x40
+#define FORCE_OFFSET     0x80
+#define EXTENDED_OFFSET  0xC0
+
+typedef struct IRQMPState IRQMPState;
+
+typedef struct IRQMP {
+    SysBusDevice busdev;
+
+    void *set_pil_in;
+    void *set_pil_in_opaque;
+
+    IRQMPState *state;
+} IRQMP;
+
+struct IRQMPState {
+    uint32_t level;
+    uint32_t pending;
+    uint32_t clear;
+    uint32_t broadcast;
+
+    uint32_t mask[IRQMP_MAX_CPU];
+    uint32_t force[IRQMP_MAX_CPU];
+    uint32_t extended[IRQMP_MAX_CPU];
+
+    IRQMP    *parent;
+};
+
+static void grlib_irqmp_check_irqs(IRQMPState *state)
+{
+    uint32_t      pend   = 0;
+    uint32_t      level0 = 0;
+    uint32_t      level1 = 0;
+    set_pil_in_fn set_pil_in;
+
+    assert(state != NULL);
+    assert(state->parent != NULL);
+
+    /* IRQ for CPU 0 (no SMP support) */
+    pend = (state->pending | state->force[0])
+        & state->mask[0];
+
+    level0 = pend & ~state->level;
+    level1 = pend &  state->level;
+
+    trace_grlib_irqmp_check_irqs(state->pending, state->force[0],
+                                 state->mask[0], level1, level0);
+
+    set_pil_in = (set_pil_in_fn)state->parent->set_pil_in;
+
+    /* Trigger level1 interrupt first and level0 if there is no level1 */
+    if (level1 != 0) {
+        set_pil_in(state->parent->set_pil_in_opaque, level1);
+    } else {
+        set_pil_in(state->parent->set_pil_in_opaque, level0);
+    }
+}
+
+void grlib_irqmp_ack(DeviceState *dev, int intno)
+{
+    SysBusDevice *sdev;
+    IRQMP        *irqmp;
+    IRQMPState   *state;
+    uint32_t      mask;
+
+    assert(dev != NULL);
+
+    sdev = sysbus_from_qdev(dev);
+    assert(sdev != NULL);
+
+    irqmp = FROM_SYSBUS(typeof(*irqmp), sdev);
+    assert(irqmp != NULL);
+
+    state = irqmp->state;
+    assert(state != NULL);
+
+    intno &= 15;
+    mask = 1 << intno;
+
+    trace_grlib_irqmp_ack(intno);
+
+    /* Clear registers */
+    state->pending  &= ~mask;
+    state->force[0] &= ~mask; /* Only CPU 0 (No SMP support) */
+
+    grlib_irqmp_check_irqs(state);
+}
+
+void grlib_irqmp_set_irq(void *opaque, int irq, int level)
+{
+    IRQMP      *irqmp;
+    IRQMPState *s;
+    int         i = 0;
+
+    assert(opaque != NULL);
+
+    irqmp = FROM_SYSBUS(typeof(*irqmp), sysbus_from_qdev(opaque));
+    assert(irqmp != NULL);
+
+    s = irqmp->state;
+    assert(s         != NULL);
+    assert(s->parent != NULL);
+
+
+    if (level) {
+        trace_grlib_irqmp_set_irq(irq);
+
+        if (s->broadcast & 1 << irq) {
+            /* Broadcasted IRQ */
+            for (i = 0; i < IRQMP_MAX_CPU; i++) {
+                s->force[i] |= 1 << irq;
+            }
+        } else {
+            s->pending |= 1 << irq;
+        }
+        grlib_irqmp_check_irqs(s);
+
+    }
+}
+
+static uint32_t grlib_irqmp_readl(void *opaque, target_phys_addr_t addr)
+{
+    IRQMP      *irqmp = opaque;
+    IRQMPState *state;
+
+    assert(irqmp != NULL);
+    state = irqmp->state;
+    assert(state != NULL);
+
+    addr &= 0xff;
+
+    /* global registers */
+    switch (addr) {
+    case LEVEL_OFFSET:
+        return state->level;
+
+    case PENDING_OFFSET:
+        return state->pending;
+
+    case FORCE0_OFFSET:
+        /* This register is an "alias" for the force register of CPU 0 */
+        return state->force[0];
+
+    case CLEAR_OFFSET:
+    case MP_STATUS_OFFSET:
+        /* Always read as 0 */
+        return 0;
+
+    case BROADCAST_OFFSET:
+        return state->broadcast;
+
+    default:
+        break;
+    }
+
+    /* mask registers */
+    if (addr >= MASK_OFFSET && addr < FORCE_OFFSET) {
+        int cpu = (addr - MASK_OFFSET) / 4;
+        assert(cpu >= 0 && cpu < IRQMP_MAX_CPU);
+
+        return state->mask[cpu];
+    }
+
+    /* force registers */
+    if (addr >= FORCE_OFFSET && addr < EXTENDED_OFFSET) {
+        int cpu = (addr - FORCE_OFFSET) / 4;
+        assert(cpu >= 0 && cpu < IRQMP_MAX_CPU);
+
+        return state->force[cpu];
+    }
+
+    /* extended (not supported) */
+    if (addr >= EXTENDED_OFFSET && addr < IRQMP_REG_SIZE) {
+        int cpu = (addr - EXTENDED_OFFSET) / 4;
+        assert(cpu >= 0 && cpu < IRQMP_MAX_CPU);
+
+        return state->extended[cpu];
+    }
+
+    trace_grlib_irqmp_unknown_register("read", addr);
+    return 0;
+}
+
+static void
+grlib_irqmp_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    IRQMP      *irqmp = opaque;
+    IRQMPState *state;
+
+    assert(irqmp != NULL);
+    state = irqmp->state;
+    assert(state != NULL);
+
+    addr &= 0xff;
+
+    /* global registers */
+    switch (addr) {
+    case LEVEL_OFFSET:
+        value &= 0xFFFF << 1; /* clean up the value */
+        state->level = value;
+        return;
+
+    case PENDING_OFFSET:
+        /* Read Only */
+        return;
+
+    case FORCE0_OFFSET:
+        /* This register is an "alias" for the force register of CPU 0 */
+
+        value &= 0xFFFE; /* clean up the value */
+        state->force[0] = value;
+        grlib_irqmp_check_irqs(irqmp->state);
+        return;
+
+    case CLEAR_OFFSET:
+        value &= ~1; /* clean up the value */
+        state->pending &= ~value;
+        return;
+
+    case MP_STATUS_OFFSET:
+        /* Read Only (no SMP support) */
+        return;
+
+    case BROADCAST_OFFSET:
+        value &= 0xFFFE; /* clean up the value */
+        state->broadcast = value;
+        return;
+
+    default:
+        break;
+    }
+
+    /* mask registers */
+    if (addr >= MASK_OFFSET && addr < FORCE_OFFSET) {
+        int cpu = (addr - MASK_OFFSET) / 4;
+        assert(cpu >= 0 && cpu < IRQMP_MAX_CPU);
+
+        value &= ~1; /* clean up the value */
+        state->mask[cpu] = value;
+        grlib_irqmp_check_irqs(irqmp->state);
+        return;
+    }
+
+    /* force registers */
+    if (addr >= FORCE_OFFSET && addr < EXTENDED_OFFSET) {
+        int cpu = (addr - FORCE_OFFSET) / 4;
+        assert(cpu >= 0 && cpu < IRQMP_MAX_CPU);
+
+        uint32_t force = value & 0xFFFE;
+        uint32_t clear = (value >> 16) & 0xFFFE;
+        uint32_t old   = state->force[cpu];
+
+        state->force[cpu] = (old | force) & ~clear;
+        grlib_irqmp_check_irqs(irqmp->state);
+        return;
+    }
+
+    /* extended (not supported) */
+    if (addr >= EXTENDED_OFFSET && addr < IRQMP_REG_SIZE) {
+        int cpu = (addr - EXTENDED_OFFSET) / 4;
+        assert(cpu >= 0 && cpu < IRQMP_MAX_CPU);
+
+        value &= 0xF; /* clean up the value */
+        state->extended[cpu] = value;
+        return;
+    }
+
+    trace_grlib_irqmp_unknown_register("write", addr);
+}
+
+static CPUReadMemoryFunc * const grlib_irqmp_read[] = {
+    NULL, NULL, &grlib_irqmp_readl,
+};
+
+static CPUWriteMemoryFunc * const grlib_irqmp_write[] = {
+    NULL, NULL, &grlib_irqmp_writel,
+};
+
+static void grlib_irqmp_reset(DeviceState *d)
+{
+    IRQMP *irqmp = container_of(d, IRQMP, busdev.qdev);
+    assert(irqmp        != NULL);
+    assert(irqmp->state != NULL);
+
+    memset(irqmp->state, 0, sizeof *irqmp->state);
+    irqmp->state->parent = irqmp;
+}
+
+static int grlib_irqmp_init(SysBusDevice *dev)
+{
+    IRQMP *irqmp = FROM_SYSBUS(typeof(*irqmp), dev);
+    int    irqmp_regs;
+
+    assert(irqmp != NULL);
+
+    /* Check parameters */
+    if (irqmp->set_pil_in == NULL) {
+        return -1;
+    }
+
+    irqmp_regs = cpu_register_io_memory(grlib_irqmp_read,
+                                        grlib_irqmp_write,
+                                        irqmp, DEVICE_NATIVE_ENDIAN);
+
+    irqmp->state = qemu_mallocz(sizeof *irqmp->state);
+
+    if (irqmp_regs < 0) {
+        return -1;
+    }
+
+    sysbus_init_mmio(dev, IRQMP_REG_SIZE, irqmp_regs);
+
+    return 0;
+}
+
+static SysBusDeviceInfo grlib_irqmp_info = {
+    .init = grlib_irqmp_init,
+    .qdev.name  = "grlib,irqmp",
+    .qdev.reset = grlib_irqmp_reset,
+    .qdev.size  = sizeof(IRQMP),
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_PTR("set_pil_in", IRQMP, set_pil_in),
+        DEFINE_PROP_PTR("set_pil_in_opaque", IRQMP, set_pil_in_opaque),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void grlib_irqmp_register(void)
+{
+    sysbus_register_withprop(&grlib_irqmp_info);
+}
+
+device_init(grlib_irqmp_register)
diff --git a/trace-events b/trace-events
index 3761fd1..832b561 100644
--- a/trace-events
+++ b/trace-events
@@ -234,3 +234,9 @@ disable grlib_gptimer_hit(int id) "timer:%d HIT"
 disable grlib_gptimer_readl(int id, const char *s, uint32_t val) "timer:%d %s 0x%x"
 disable grlib_gptimer_writel(int id, const char *s, uint32_t val) "timer:%d %s 0x%x"
 disable grlib_gptimer_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
+
+# hw/grlib_irqmp.c
+disable grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uint32_t lvl1, uint32_t lvl2) "pend:0x%04x force:0x%04x mask:0x%04x lvl1:0x%04x lvl0:0x%04x\n"
+disable grlib_irqmp_ack(int intno) "interrupt:%d"
+disable grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d"
+disable grlib_irqmp_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
commit 0f3a4a01ebafe93055069418c9d65cc7b1493b41
Author: Fabien Chouteau <chouteau at adacore.com>
Date:   Mon Jan 24 12:56:52 2011 +0100

    SPARC: Emulation of GRLIB GPTimer
    
    This device exposes three parameters:
     - frequency (uint32) : The system frequency
     - irq-line  (uint32) : IRQ line number for the first timer
                            (others use irq-line + 1, irq-line + 2...)
     - nr-timers (uint32) : Number of timers
    
    Emulation of GrLib devices is base on the GRLIB IP Core User's Manual:
    http://www.gaisler.com/products/grlib/grip.pdf
    
    Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/hw/grlib.h b/hw/grlib.h
new file mode 100644
index 0000000..776acf9
--- /dev/null
+++ b/hw/grlib.h
@@ -0,0 +1,65 @@
+/*
+ * QEMU GRLIB Components
+ *
+ * Copyright (c) 2010-2011 AdaCore
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef _GRLIB_H_
+#define _GRLIB_H_
+
+#include "qdev.h"
+#include "sysbus.h"
+
+/* Emulation of GrLib device is base on the GRLIB IP Core User's Manual:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ */
+
+/* GPTimer */
+
+static inline
+DeviceState *grlib_gptimer_create(target_phys_addr_t  base,
+                                  uint32_t            nr_timers,
+                                  uint32_t            freq,
+                                  qemu_irq           *cpu_irqs,
+                                  int                 base_irq)
+{
+    DeviceState *dev;
+    int i;
+
+    dev = qdev_create(NULL, "grlib,gptimer");
+    qdev_prop_set_uint32(dev, "nr-timers", nr_timers);
+    qdev_prop_set_uint32(dev, "frequency", freq);
+    qdev_prop_set_uint32(dev, "irq-line", base_irq);
+
+    if (qdev_init(dev)) {
+        return NULL;
+    }
+
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+
+    for (i = 0; i < nr_timers; i++) {
+        sysbus_connect_irq(sysbus_from_qdev(dev), i, cpu_irqs[base_irq + i]);
+    }
+
+    return dev;
+}
+
+#endif /* ! _GRLIB_H_ */
diff --git a/hw/grlib_gptimer.c b/hw/grlib_gptimer.c
new file mode 100644
index 0000000..596a900
--- /dev/null
+++ b/hw/grlib_gptimer.c
@@ -0,0 +1,395 @@
+/*
+ * QEMU GRLIB GPTimer Emulator
+ *
+ * Copyright (c) 2010-2011 AdaCore
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-timer.h"
+
+#include "trace.h"
+
+#define UNIT_REG_SIZE    16     /* Size of memory mapped regs for the unit */
+#define GPTIMER_REG_SIZE 16     /* Size of memory mapped regs for a GPTimer */
+
+#define GPTIMER_MAX_TIMERS 8
+
+/* GPTimer Config register fields */
+#define GPTIMER_ENABLE      (1 << 0)
+#define GPTIMER_RESTART     (1 << 1)
+#define GPTIMER_LOAD        (1 << 2)
+#define GPTIMER_INT_ENABLE  (1 << 3)
+#define GPTIMER_INT_PENDING (1 << 4)
+#define GPTIMER_CHAIN       (1 << 5) /* Not supported */
+#define GPTIMER_DEBUG_HALT  (1 << 6) /* Not supported */
+
+/* Memory mapped register offsets */
+#define SCALER_OFFSET         0x00
+#define SCALER_RELOAD_OFFSET  0x04
+#define CONFIG_OFFSET         0x08
+#define COUNTER_OFFSET        0x00
+#define COUNTER_RELOAD_OFFSET 0x04
+#define TIMER_BASE            0x10
+
+typedef struct GPTimer     GPTimer;
+typedef struct GPTimerUnit GPTimerUnit;
+
+struct GPTimer {
+    QEMUBH *bh;
+    struct ptimer_state *ptimer;
+
+    qemu_irq     irq;
+    int          id;
+    GPTimerUnit *unit;
+
+    /* registers */
+    uint32_t counter;
+    uint32_t reload;
+    uint32_t config;
+};
+
+struct GPTimerUnit {
+    SysBusDevice  busdev;
+
+    uint32_t nr_timers;         /* Number of timers available */
+    uint32_t freq_hz;           /* System frequency */
+    uint32_t irq_line;          /* Base irq line */
+
+    GPTimer *timers;
+
+    /* registers */
+    uint32_t scaler;
+    uint32_t reload;
+    uint32_t config;
+};
+
+static void grlib_gptimer_enable(GPTimer *timer)
+{
+    assert(timer != NULL);
+
+
+    ptimer_stop(timer->ptimer);
+
+    if (!(timer->config & GPTIMER_ENABLE)) {
+        /* Timer disabled */
+        trace_grlib_gptimer_disabled(timer->id, timer->config);
+        return;
+    }
+
+    /* ptimer is triggered when the counter reach 0 but GPTimer is triggered at
+       underflow. Set count + 1 to simulate the GPTimer behavior. */
+
+    trace_grlib_gptimer_enable(timer->id, timer->counter + 1);
+
+    ptimer_set_count(timer->ptimer, timer->counter + 1);
+    ptimer_run(timer->ptimer, 1);
+}
+
+static void grlib_gptimer_restart(GPTimer *timer)
+{
+    assert(timer != NULL);
+
+    trace_grlib_gptimer_restart(timer->id, timer->reload);
+
+    timer->counter = timer->reload;
+    grlib_gptimer_enable(timer);
+}
+
+static void grlib_gptimer_set_scaler(GPTimerUnit *unit, uint32_t scaler)
+{
+    int i = 0;
+    uint32_t value = 0;
+
+    assert(unit != NULL);
+
+    if (scaler > 0) {
+        value = unit->freq_hz / (scaler + 1);
+    } else {
+        value = unit->freq_hz;
+    }
+
+    trace_grlib_gptimer_set_scaler(scaler, value);
+
+    for (i = 0; i < unit->nr_timers; i++) {
+        ptimer_set_freq(unit->timers[i].ptimer, value);
+    }
+}
+
+static void grlib_gptimer_hit(void *opaque)
+{
+    GPTimer *timer = opaque;
+    assert(timer != NULL);
+
+    trace_grlib_gptimer_hit(timer->id);
+
+    /* Timer expired */
+
+    if (timer->config & GPTIMER_INT_ENABLE) {
+        /* Set the pending bit (only unset by write in the config register) */
+        timer->config |= GPTIMER_INT_PENDING;
+        qemu_irq_pulse(timer->irq);
+    }
+
+    if (timer->config & GPTIMER_RESTART) {
+        grlib_gptimer_restart(timer);
+    }
+}
+
+static uint32_t grlib_gptimer_readl(void *opaque, target_phys_addr_t addr)
+{
+    GPTimerUnit        *unit  = opaque;
+    target_phys_addr_t  timer_addr;
+    int                 id;
+    uint32_t            value = 0;
+
+    addr &= 0xff;
+
+    /* Unit registers */
+    switch (addr) {
+    case SCALER_OFFSET:
+        trace_grlib_gptimer_readl(-1, "scaler:", unit->scaler);
+        return unit->scaler;
+
+    case SCALER_RELOAD_OFFSET:
+        trace_grlib_gptimer_readl(-1, "reload:", unit->reload);
+        return unit->reload;
+
+    case CONFIG_OFFSET:
+        trace_grlib_gptimer_readl(-1, "config:", unit->config);
+        return unit->config;
+
+    default:
+        break;
+    }
+
+    timer_addr = (addr % TIMER_BASE);
+    id         = (addr - TIMER_BASE) / TIMER_BASE;
+
+    if (id >= 0 && id < unit->nr_timers) {
+
+        /* GPTimer registers */
+        switch (timer_addr) {
+        case COUNTER_OFFSET:
+            value = ptimer_get_count(unit->timers[id].ptimer);
+            trace_grlib_gptimer_readl(id, "counter value:", value);
+            return value;
+
+        case COUNTER_RELOAD_OFFSET:
+            value = unit->timers[id].reload;
+            trace_grlib_gptimer_readl(id, "reload value:", value);
+            return value;
+
+        case CONFIG_OFFSET:
+            trace_grlib_gptimer_readl(id, "scaler value:",
+                                      unit->timers[id].config);
+            return unit->timers[id].config;
+
+        default:
+            break;
+        }
+
+    }
+
+    trace_grlib_gptimer_unknown_register("read", addr);
+    return 0;
+}
+
+static void
+grlib_gptimer_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+    GPTimerUnit        *unit = opaque;
+    target_phys_addr_t  timer_addr;
+    int                 id;
+
+    addr &= 0xff;
+
+    /* Unit registers */
+    switch (addr) {
+    case SCALER_OFFSET:
+        value &= 0xFFFF; /* clean up the value */
+        unit->scaler = value;
+        trace_grlib_gptimer_writel(-1, "scaler:", unit->scaler);
+        return;
+
+    case SCALER_RELOAD_OFFSET:
+        value &= 0xFFFF; /* clean up the value */
+        unit->reload = value;
+        trace_grlib_gptimer_writel(-1, "reload:", unit->reload);
+        grlib_gptimer_set_scaler(unit, value);
+        return;
+
+    case CONFIG_OFFSET:
+        /* Read Only (disable timer freeze not supported) */
+        trace_grlib_gptimer_writel(-1, "config (Read Only):", 0);
+        return;
+
+    default:
+        break;
+    }
+
+    timer_addr = (addr % TIMER_BASE);
+    id         = (addr - TIMER_BASE) / TIMER_BASE;
+
+    if (id >= 0 && id < unit->nr_timers) {
+
+        /* GPTimer registers */
+        switch (timer_addr) {
+        case COUNTER_OFFSET:
+            trace_grlib_gptimer_writel(id, "counter:", value);
+            unit->timers[id].counter = value;
+            grlib_gptimer_enable(&unit->timers[id]);
+            return;
+
+        case COUNTER_RELOAD_OFFSET:
+            trace_grlib_gptimer_writel(id, "reload:", value);
+            unit->timers[id].reload = value;
+            return;
+
+        case CONFIG_OFFSET:
+            trace_grlib_gptimer_writel(id, "config:", value);
+
+            if (value & GPTIMER_INT_PENDING) {
+                /* clear pending bit */
+                value &= ~GPTIMER_INT_PENDING;
+            } else {
+                /* keep pending bit */
+                value |= unit->timers[id].config & GPTIMER_INT_PENDING;
+            }
+
+            unit->timers[id].config = value;
+
+            /* gptimer_restart calls gptimer_enable, so if "enable" and "load"
+               bits are present, we just have to call restart. */
+
+            if (value & GPTIMER_LOAD) {
+                grlib_gptimer_restart(&unit->timers[id]);
+            } else if (value & GPTIMER_ENABLE) {
+                grlib_gptimer_enable(&unit->timers[id]);
+            }
+
+            /* These fields must always be read as 0 */
+            value &= ~(GPTIMER_LOAD & GPTIMER_DEBUG_HALT);
+
+            unit->timers[id].config = value;
+            return;
+
+        default:
+            break;
+        }
+
+    }
+
+    trace_grlib_gptimer_unknown_register("write", addr);
+}
+
+static CPUReadMemoryFunc * const grlib_gptimer_read[] = {
+    NULL, NULL, grlib_gptimer_readl,
+};
+
+static CPUWriteMemoryFunc * const grlib_gptimer_write[] = {
+    NULL, NULL, grlib_gptimer_writel,
+};
+
+static void grlib_gptimer_reset(DeviceState *d)
+{
+    GPTimerUnit *unit = container_of(d, GPTimerUnit, busdev.qdev);
+    int          i    = 0;
+
+    assert(unit != NULL);
+
+    unit->scaler = 0;
+    unit->reload = 0;
+    unit->config = 0;
+
+    unit->config  = unit->nr_timers;
+    unit->config |= unit->irq_line << 3;
+    unit->config |= 1 << 8;     /* separate interrupt */
+    unit->config |= 1 << 9;     /* Disable timer freeze */
+
+
+    for (i = 0; i < unit->nr_timers; i++) {
+        GPTimer *timer = &unit->timers[i];
+
+        timer->counter = 0;
+        timer->reload = 0;
+        timer->config = 0;
+        ptimer_stop(timer->ptimer);
+        ptimer_set_count(timer->ptimer, 0);
+        ptimer_set_freq(timer->ptimer, unit->freq_hz);
+    }
+}
+
+static int grlib_gptimer_init(SysBusDevice *dev)
+{
+    GPTimerUnit  *unit = FROM_SYSBUS(typeof(*unit), dev);
+    unsigned int  i;
+    int           timer_regs;
+
+    assert(unit->nr_timers > 0);
+    assert(unit->nr_timers <= GPTIMER_MAX_TIMERS);
+
+    unit->timers = qemu_mallocz(sizeof unit->timers[0] * unit->nr_timers);
+
+    for (i = 0; i < unit->nr_timers; i++) {
+        GPTimer *timer = &unit->timers[i];
+
+        timer->unit   = unit;
+        timer->bh     = qemu_bh_new(grlib_gptimer_hit, timer);
+        timer->ptimer = ptimer_init(timer->bh);
+        timer->id     = i;
+
+        /* One IRQ line for each timer */
+        sysbus_init_irq(dev, &timer->irq);
+
+        ptimer_set_freq(timer->ptimer, unit->freq_hz);
+    }
+
+    timer_regs = cpu_register_io_memory(grlib_gptimer_read,
+                                        grlib_gptimer_write,
+                                        unit, DEVICE_NATIVE_ENDIAN);
+    if (timer_regs < 0) {
+        return -1;
+    }
+
+    sysbus_init_mmio(dev, UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers,
+                     timer_regs);
+    return 0;
+}
+
+static SysBusDeviceInfo grlib_gptimer_info = {
+    .init       = grlib_gptimer_init,
+    .qdev.name  = "grlib,gptimer",
+    .qdev.reset = grlib_gptimer_reset,
+    .qdev.size  = sizeof(GPTimerUnit),
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("frequency", GPTimerUnit, freq_hz,   40000000),
+        DEFINE_PROP_UINT32("irq-line",  GPTimerUnit, irq_line,  8),
+        DEFINE_PROP_UINT32("nr-timers", GPTimerUnit, nr_timers, 2),
+        DEFINE_PROP_END_OF_LIST()
+    }
+};
+
+static void grlib_gptimer_register(void)
+{
+    sysbus_register_withprop(&grlib_gptimer_info);
+}
+
+device_init(grlib_gptimer_register)
diff --git a/trace-events b/trace-events
index 19cee6a..3761fd1 100644
--- a/trace-events
+++ b/trace-events
@@ -224,3 +224,13 @@ disable qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t
 disable qed_aio_write_prefill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64""
 disable qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64""
 disable qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu"
+
+# hw/grlib_gptimer.c
+disable grlib_gptimer_enable(int id, uint32_t count) "timer:%d set count 0x%x and run"
+disable grlib_gptimer_disabled(int id, uint32_t config) "timer:%d Timer disable config 0x%x"
+disable grlib_gptimer_restart(int id, uint32_t reload) "timer:%d reload val: 0x%x"
+disable grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) "scaler:0x%x freq: 0x%x"
+disable grlib_gptimer_hit(int id) "timer:%d HIT"
+disable grlib_gptimer_readl(int id, const char *s, uint32_t val) "timer:%d %s 0x%x"
+disable grlib_gptimer_writel(int id, const char *s, uint32_t val) "timer:%d %s 0x%x"
+disable grlib_gptimer_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
commit a5c062edd272a222179c2bbf54c539c992aefc93
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Jan 24 15:35:01 2011 +0000

    docs: Document scsi-disk and usb-storage removable parameter
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/docs/qdev-device-use.txt b/docs/qdev-device-use.txt
index f2f9b75..4bb2be8 100644
--- a/docs/qdev-device-use.txt
+++ b/docs/qdev-device-use.txt
@@ -80,7 +80,11 @@ The -device argument differs in detail for each kind of drive:
   This SCSI controller a single SCSI bus, named ID.0.  Put a disk on
   it:
 
-  -device scsi-disk,drive=DRIVE-ID,bus=ID.0,scsi-id=SCSI-ID
+  -device scsi-disk,drive=DRIVE-ID,bus=ID.0,scsi-id=SCSI-ID,removable=RMB
+
+  The (optional) removable parameter lets you override the SCSI INQUIRY
+  removable (RMB) bit for non CD-ROM devices.  It is ignored for CD-ROM devices
+  which are always removable.  RMB is "on" or "off".
 
 * if=floppy
 
@@ -116,7 +120,12 @@ For USB devices, the old way is actually different:
 Provides much less control than -drive's HOST-OPTS...  The new way
 fixes that:
 
-    -device usb-storage,drive=DRIVE-ID
+    -device usb-storage,drive=DRIVE-ID,removable=RMB
+
+The removable parameter gives control over the SCSI INQUIRY removable (RMB)
+bit.  USB thumbdrives usually set removable=on, while USB hard disks set
+removable=off.  See the if=scsi description above for details on the removable
+parameter, which applies only to scsi-disk devices and not to scsi-generic.
 
 === Character Devices ===
 
commit 6bb7b86722c6cc772f66cdc7923dec56e8458c29
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Jan 24 15:35:00 2011 +0000

    usb-msd: Propagate removable bit to SCSI device
    
    USB Mass Storage Devices sometimes have the RMB (removable) bit set in
    the SCSI INQUIRY response.  Thumbdrives tend to have the bit set whereas
    hard disks do not.
    
    Operating systems differentiate between removable devices and fixed
    devices.  Under Linux, the anaconda installer looks for removable
    devices.  Under Windows, only fixed devices may have more than one
    partition and AutoRun is also affected by the removable bit.
    
    For these reasons, allow USB Mass Storage Devices to override the
    removable bit:
    
    qemu -usb
         -drive if=none,file=test.img,cache=none,id=disk0
         -device usb-storage,drive=disk0,removable=on
    
    The default is off.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index ccdf8ff..11722c7 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -51,6 +51,7 @@ typedef struct {
     SCSIBus bus;
     BlockConf conf;
     SCSIDevice *scsi_dev;
+    uint32_t removable;
     int result;
     /* For async completion.  */
     USBPacket *packet;
@@ -515,7 +516,7 @@ static int usb_msd_initfn(USBDevice *dev)
 
     usb_desc_init(dev);
     scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete);
-    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, false);
+    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable);
     if (!s->scsi_dev) {
         return -1;
     }
@@ -607,6 +608,7 @@ static struct USBDeviceInfo msd_info = {
     .usbdevice_init = usb_msd_init,
     .qdev.props     = (Property[]) {
         DEFINE_BLOCK_PROPERTIES(MSDState, conf),
+        DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
commit 2d1fd2613769d99e5fad1f57ab8466434e2079fd
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Jan 24 15:34:59 2011 +0000

    scsi: Allow scsi_bus_legacy_add_drive() to set removable bit
    
    scsi-disk devices may wish to override the removable bit.  Add support
    for a qdev property on SCSI devices.  This is will be used by usb-msd.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 716133c..270a982 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -90,7 +90,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
      * specified).
      */
     dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
-    scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit);
+    scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, false);
     if (!scsidev) {
         return -1;
     }
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 7febb86..ceeb4ec 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -87,7 +87,8 @@ void scsi_qdev_register(SCSIDeviceInfo *info)
 }
 
 /* handle legacy '-drive if=scsi,...' cmd line args */
-SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int unit)
+SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
+                                      int unit, bool removable)
 {
     const char *driver;
     DeviceState *dev;
@@ -95,6 +96,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int
     driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk";
     dev = qdev_create(&bus->qbus, driver);
     qdev_prop_set_uint32(dev, "scsi-id", unit);
+    if (qdev_prop_exists(dev, "removable")) {
+        qdev_prop_set_bit(dev, "removable", removable);
+    }
     if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
         qdev_free(dev);
         return NULL;
@@ -117,7 +121,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)) {
+        if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false)) {
             res = -1;
             break;
         }
diff --git a/hw/scsi.h b/hw/scsi.h
index bf02adf..846fbba 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -94,7 +94,8 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
     return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
 }
 
-SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int unit);
+SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
+                                      int unit, bool removable);
 int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
 
 SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun);
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 729d96c..ccdf8ff 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -515,7 +515,7 @@ static int usb_msd_initfn(USBDevice *dev)
 
     usb_desc_init(dev);
     scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete);
-    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0);
+    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, false);
     if (!s->scsi_dev) {
         return -1;
     }
commit 419e691f8ef16635e73d814ef3ab825272208ba8
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Jan 24 15:34:58 2011 +0000

    scsi-disk: Allow overriding SCSI INQUIRY removable bit
    
    Provide the "removable" qdev property bit to override the SCSI INQUIRY
    removable (RMB) bit for non-CDROM devices.  This will be used by USB
    Mass Storage Devices, which sometimes have this guest-visible bit set
    and sometimes do not.  They therefore requires a means for user
    configuration.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 6cb317c..488eedd 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -72,6 +72,7 @@ struct SCSIDiskState
     /* The qemu block layer uses a fixed 512 byte sector size.
        This is the number of 512 byte blocks in a single scsi sector.  */
     int cluster_size;
+    uint32_t removable;
     uint64_t max_lba;
     QEMUBH *bh;
     char *version;
@@ -552,6 +553,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
         memcpy(&outbuf[16], "QEMU CD-ROM     ", 16);
     } else {
         outbuf[0] = 0;
+        outbuf[1] = s->removable ? 0x80 : 0;
         memcpy(&outbuf[16], "QEMU HARDDISK   ", 16);
     }
     memcpy(&outbuf[8], "QEMU    ", 8);
@@ -1295,6 +1297,7 @@ static SCSIDeviceInfo scsi_disk_info = {
         DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),
         DEFINE_PROP_STRING("ver",  SCSIDiskState, version),
         DEFINE_PROP_STRING("serial",  SCSIDiskState, serial),
+        DEFINE_PROP_BIT("removable", SCSIDiskState, removable, 0, false),
         DEFINE_PROP_END_OF_LIST(),
     },
 };
commit b835e919f022d768abdf00e8dc94f1a23fdcab15
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Mon Jan 17 19:29:34 2011 +0100

    target-mips: fix save_cpu_state() calls
    
    The rule is:
    - don't save PC if the exception is only triggered by softmmu.
    - save PC if the exception can be triggered by an helper.
    
    Fix a 64-bit kernel crash when loading modules.
    
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/target-mips/translate.c b/target-mips/translate.c
index 187930e..0f93e2a 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1066,7 +1066,7 @@ static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc,
         opn = "ld";
         break;
     case OPC_LLD:
-        save_cpu_state(ctx, 0);
+        save_cpu_state(ctx, 1);
         op_ld_lld(t0, t0, ctx);
         gen_store_gpr(t0, rt);
         opn = "lld";
@@ -1086,7 +1086,7 @@ static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc,
         opn = "ldr";
         break;
     case OPC_LDPC:
-        save_cpu_state(ctx, 1);
+        save_cpu_state(ctx, 0);
         tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
         gen_op_addr_add(ctx, t0, t0, t1);
         op_ld_ld(t0, t0, ctx);
@@ -1095,7 +1095,7 @@ static void gen_ld (CPUState *env, DisasContext *ctx, uint32_t opc,
         break;
 #endif
     case OPC_LWPC:
-        save_cpu_state(ctx, 1);
+        save_cpu_state(ctx, 0);
         tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
         gen_op_addr_add(ctx, t0, t0, t1);
         op_ld_lw(t0, t0, ctx);
@@ -1238,7 +1238,7 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
     switch (opc) {
 #if defined(TARGET_MIPS64)
     case OPC_SCD:
-        save_cpu_state(ctx, 0);
+        save_cpu_state(ctx, 1);
         op_st_scd(t1, t0, rt, ctx);
         opn = "scd";
         break;
@@ -9971,7 +9971,7 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
         opn = "lwp";
         break;
     case SWP:
-        save_cpu_state(ctx, 1);
+        save_cpu_state(ctx, 0);
         gen_load_gpr(t1, rd);
         op_st_sw(t1, t0, ctx);
         tcg_gen_movi_tl(t1, 4);
@@ -9992,7 +9992,7 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
         opn = "ldp";
         break;
     case SDP:
-        save_cpu_state(ctx, 1);
+        save_cpu_state(ctx, 0);
         gen_load_gpr(t1, rd);
         op_st_sd(t1, t0, ctx);
         tcg_gen_movi_tl(t1, 8);
commit ea87e95f8fda609fa665c2abd33c30ae65e6fae2
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Jan 23 08:48:41 2011 +0000

    usb-bus: use snprintf
    
    Avoid this warning from OpenBSD linker:
      LINK  i386-softmmu/qemu
    ../usb-bus.o(.text+0x27c): In function `usb_get_fw_dev_path':
    /src/qemu/hw/usb-bus.c:294: warning: sprintf() is often misused,
    please use snprintf()
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index ac56fbc..abc7e61 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -298,20 +298,22 @@ static char *usb_get_fw_dev_path(DeviceState *qdev)
 {
     USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
     char *fw_path, *in;
-    int pos = 0;
+    ssize_t pos = 0, fw_len;
     long nr;
 
-    fw_path = qemu_malloc(32 + strlen(dev->port->path) * 6);
+    fw_len = 32 + strlen(dev->port->path) * 6;
+    fw_path = qemu_malloc(fw_len);
     in = dev->port->path;
-    while (true) {
+    while (fw_len - pos > 0) {
         nr = strtol(in, &in, 10);
         if (in[0] == '.') {
             /* some hub between root port and device */
-            pos += sprintf(fw_path + pos, "hub@%ld/", nr);
+            pos += snprintf(fw_path + pos, fw_len - pos, "hub@%ld/", nr);
             in++;
         } else {
             /* the device itself */
-            pos += sprintf(fw_path + pos, "%s@%ld", qdev_fw_name(qdev), nr);
+            pos += snprintf(fw_path + pos, fw_len - pos, "%s@%ld",
+                            qdev_fw_name(qdev), nr);
             break;
         }
     }
commit ee59e6b3bf2074774a0626bc3d5389f2b7bd05bd
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Dec 10 14:40:30 2010 +0100

    usb hid: add migration support
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 168e67d..79b20df 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -65,7 +65,7 @@ typedef struct USBKeyboardState {
     uint16_t modifiers;
     uint8_t leds;
     uint8_t key[16];
-    int keys;
+    int32_t keys;
 } USBKeyboardState;
 
 typedef struct USBHIDState {
@@ -77,7 +77,7 @@ typedef struct USBHIDState {
     uint32_t head; /* index into circular queue */
     uint32_t n;
     int kind;
-    int protocol;
+    int32_t protocol;
     uint8_t idle;
     int64_t next_idle_clock;
     int changed;
@@ -895,12 +895,72 @@ void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
     s->datain = datain;
 }
 
+static int usb_hid_post_load(void *opaque, int version_id)
+{
+    USBHIDState *s = opaque;
+
+    if (s->idle) {
+        usb_hid_set_next_idle(s, qemu_get_clock(vm_clock));
+    }
+    return 0;
+}
+
+static const VMStateDescription vmstate_usb_ptr_queue = {
+    .name = "usb-ptr-queue",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_INT32(xdx, USBPointerEvent),
+        VMSTATE_INT32(ydy, USBPointerEvent),
+        VMSTATE_INT32(dz, USBPointerEvent),
+        VMSTATE_INT32(buttons_state, USBPointerEvent),
+        VMSTATE_END_OF_LIST()
+    }
+};
+static const VMStateDescription vmstate_usb_ptr = {
+    .name = "usb-ptr",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .post_load = usb_hid_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_USB_DEVICE(dev, USBHIDState),
+        VMSTATE_STRUCT_ARRAY(ptr.queue, USBHIDState, QUEUE_LENGTH, 0,
+                             vmstate_usb_ptr_queue, USBPointerEvent),
+        VMSTATE_UINT32(head, USBHIDState),
+        VMSTATE_UINT32(n, USBHIDState),
+        VMSTATE_INT32(protocol, USBHIDState),
+        VMSTATE_UINT8(idle, USBHIDState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_usb_kbd = {
+    .name = "usb-kbd",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .post_load = usb_hid_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_USB_DEVICE(dev, USBHIDState),
+        VMSTATE_UINT32_ARRAY(kbd.keycodes, USBHIDState, QUEUE_LENGTH),
+        VMSTATE_UINT32(head, USBHIDState),
+        VMSTATE_UINT32(n, USBHIDState),
+        VMSTATE_UINT16(kbd.modifiers, USBHIDState),
+        VMSTATE_UINT8(kbd.leds, USBHIDState),
+        VMSTATE_UINT8_ARRAY(kbd.key, USBHIDState, 16),
+        VMSTATE_INT32(kbd.keys, USBHIDState),
+        VMSTATE_INT32(protocol, USBHIDState),
+        VMSTATE_UINT8(idle, USBHIDState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static struct USBDeviceInfo hid_info[] = {
     {
         .product_desc   = "QEMU USB Tablet",
         .qdev.name      = "usb-tablet",
         .usbdevice_name = "tablet",
         .qdev.size      = sizeof(USBHIDState),
+        .qdev.vmsd      = &vmstate_usb_ptr,
         .usb_desc       = &desc_tablet,
         .init           = usb_tablet_initfn,
         .handle_packet  = usb_generic_handle_packet,
@@ -913,6 +973,7 @@ static struct USBDeviceInfo hid_info[] = {
         .qdev.name      = "usb-mouse",
         .usbdevice_name = "mouse",
         .qdev.size      = sizeof(USBHIDState),
+        .qdev.vmsd      = &vmstate_usb_ptr,
         .usb_desc       = &desc_mouse,
         .init           = usb_mouse_initfn,
         .handle_packet  = usb_generic_handle_packet,
@@ -925,6 +986,7 @@ static struct USBDeviceInfo hid_info[] = {
         .qdev.name      = "usb-kbd",
         .usbdevice_name = "keyboard",
         .qdev.size      = sizeof(USBHIDState),
+        .qdev.vmsd      = &vmstate_usb_kbd,
         .usb_desc       = &desc_keyboard,
         .init           = usb_keyboard_initfn,
         .handle_packet  = usb_generic_handle_packet,
commit d15500902adb79034ef40ee3a06bbc0a7e0d8b19
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Dec 15 12:45:24 2010 +0100

    usb hub: add migration support
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 78698ca..3dd31ba 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -544,11 +544,35 @@ static int usb_hub_initfn(USBDevice *dev)
     return 0;
 }
 
+static const VMStateDescription vmstate_usb_hub_port = {
+    .name = "usb-hub-port",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT16(wPortStatus, USBHubPort),
+        VMSTATE_UINT16(wPortChange, USBHubPort),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_usb_hub = {
+    .name = "usb-hub",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_USB_DEVICE(dev, USBHubState),
+        VMSTATE_STRUCT_ARRAY(ports, USBHubState, NUM_PORTS, 0,
+                             vmstate_usb_hub_port, USBHubPort),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static struct USBDeviceInfo hub_info = {
     .product_desc   = "QEMU USB Hub",
     .qdev.name      = "usb-hub",
     .qdev.fw_name    = "hub",
     .qdev.size      = sizeof(USBHubState),
+    .qdev.vmsd      = &vmstate_usb_hub,
     .usb_desc       = &desc_hub,
     .init           = usb_hub_initfn,
     .handle_packet  = usb_hub_handle_packet,
commit c1ecb40a6124b80f1e346e38a1975e82da6507ca
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Dec 10 14:20:46 2010 +0100

    usb core: add migration support
    
    Yes, seriously.  There is no migration support at all for usb devices.
    They loose state, especially the device address, and stop responding
    because of that.  Oops.
    
    Luckily there is so much broken usb hardware out there that the guest
    usually just kicks the device hard (via port reset and
    reinitialization), then continues without a hitch.  So we got away with
    that in a surprising high number of cases.
    
    The arrival of remote wakeup (which enables autosuspend support) changes
    that picture though.  The usb devices also forget that it they are
    supposed to wakeup, so they don't do that.  The host also doesn't notice
    the device stopped working in case it suspended the device and thus
    expects it waking up instead of polling it.  Result is that your mouse
    is dead.
    
    Lets start fixing that.  Add a vmstate struct for USBDevice.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/hw.h b/hw/hw.h
index dd993de..5e24329 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -587,6 +587,16 @@ extern const VMStateDescription vmstate_i2c_slave;
     .offset     = vmstate_offset_value(_state, _field, i2c_slave),   \
 }
 
+extern const VMStateDescription vmstate_usb_device;
+
+#define VMSTATE_USB_DEVICE(_field, _state) {                         \
+    .name       = (stringify(_field)),                               \
+    .size       = sizeof(USBDevice),                                 \
+    .vmsd       = &vmstate_usb_device,                               \
+    .flags      = VMS_STRUCT,                                        \
+    .offset     = vmstate_offset_value(_state, _field, USBDevice),   \
+}
+
 #define vmstate_offset_macaddr(_state, _field)                       \
     vmstate_offset_array(_state, _field.a, uint8_t,                \
                          sizeof(typeof_field(_state, _field)))
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 6e2e5fd..ac56fbc 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -23,6 +23,22 @@ static struct BusInfo usb_bus_info = {
 static int next_usb_bus = 0;
 static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
 
+const VMStateDescription vmstate_usb_device = {
+    .name = "USBDevice",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT8(addr, USBDevice),
+        VMSTATE_INT32(state, USBDevice),
+        VMSTATE_INT32(remote_wakeup, USBDevice),
+        VMSTATE_INT32(setup_state, USBDevice),
+        VMSTATE_INT32(setup_len, USBDevice),
+        VMSTATE_INT32(setup_index, USBDevice),
+        VMSTATE_UINT8_ARRAY(setup_buf, USBDevice, 8),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
 void usb_bus_new(USBBus *bus, DeviceState *host)
 {
     qbus_create_inplace(&bus->qbus, &usb_bus_info, host, NULL);
diff --git a/hw/usb.h b/hw/usb.h
index 5c1da3e..d3d755d 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -165,13 +165,13 @@ struct USBDevice {
     int auto_attach;
     int attached;
 
-    int state;
+    int32_t state;
     uint8_t setup_buf[8];
     uint8_t data_buf[1024];
-    int remote_wakeup;
-    int setup_state;
-    int setup_len;
-    int setup_index;
+    int32_t remote_wakeup;
+    int32_t setup_state;
+    int32_t setup_len;
+    int32_t setup_index;
 
     QLIST_HEAD(, USBDescString) strings;
     const USBDescDevice *device;
commit 9892088b52da05c3944e84982922fa984e048044
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jan 14 10:56:54 2011 +0100

    vnc: fix numlock+capslock tracking
    
    This patch makes the numlock+capslock tracking logic only look at
    keydown events.  Without this patch the vnc server will insert
    bogous capslock keypress in case it sees the following key sequence:
    
      shift down --- 'A' down --- shift up  --- 'A' up
                                             ^ here
    
    It doesn't hurt with a PS/2 keyboard, but it disturbs the USB Keyboard.
    And with the key event queue just added to the usb keyboard the guest
    will actually notice.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/ui/vnc.c b/ui/vnc.c
index 495d6d6..0820d99 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1504,7 +1504,7 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
         break;
     }
 
-    if (vs->vd->lock_key_sync &&
+    if (down && vs->vd->lock_key_sync &&
         keycode_is_keypad(vs->vd->kbd_layout, keycode)) {
         /* If the numlock state needs to change then simulate an additional
            keypress before sending this one.  This will happen if the user
@@ -1523,7 +1523,7 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
         }
     }
 
-    if (vs->vd->lock_key_sync &&
+    if (down && vs->vd->lock_key_sync &&
         ((sym >= 'A' && sym <= 'Z') || (sym >= 'a' && sym <= 'z'))) {
         /* If the capslock state needs to change then simulate an additional
            keypress before sending this one.  This will happen if the user
commit 42292d4e51ac01eb28360d53127337fe275c39c5
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jan 14 09:23:22 2011 +0100

    usb hid: move head+n to common struct
    
    This patch moves the 'head' and 'n' fields from USBMouseState and
    USBKeyboardState to the common USBHIDState struct.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 5f1451b..168e67d 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -56,16 +56,12 @@ typedef struct USBPointerEvent {
 
 typedef struct USBMouseState {
     USBPointerEvent queue[QUEUE_LENGTH];
-    uint32_t head; /* index into circular queue */
-    uint32_t n;
     int mouse_grabbed;
     QEMUPutMouseEntry *eh_entry;
 } USBMouseState;
 
 typedef struct USBKeyboardState {
     uint32_t keycodes[QUEUE_LENGTH];
-    uint32_t head; /* index into circular queue */
-    uint32_t n;
     uint16_t modifiers;
     uint8_t leds;
     uint8_t key[16];
@@ -78,6 +74,8 @@ typedef struct USBHIDState {
         USBMouseState ptr;
         USBKeyboardState kbd;
     };
+    uint32_t head; /* index into circular queue */
+    uint32_t n;
     int kind;
     int protocol;
     uint8_t idle;
@@ -468,7 +466,7 @@ static void usb_pointer_event(void *opaque,
 {
     USBHIDState *hs = opaque;
     USBMouseState *s = &hs->ptr;
-    unsigned use_slot = (s->head + s->n - 1) & QUEUE_MASK;
+    unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
     unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
 
     /* We combine events where feasible to keep the queue small.  We shouldn't
@@ -476,15 +474,15 @@ static void usb_pointer_event(void *opaque,
      * that would change the location of the button state change.  When the
      * queue is empty, a second event is needed because we don't know if
      * the first event changed the button state.  */
-    if (s->n == QUEUE_LENGTH) {
+    if (hs->n == QUEUE_LENGTH) {
         /* Queue full.  Discard old button state, combine motion normally.  */
         s->queue[use_slot].buttons_state = buttons_state;
-    } else if (s->n < 2 ||
+    } else if (hs->n < 2 ||
                s->queue[use_slot].buttons_state != buttons_state ||
                s->queue[previous_slot].buttons_state != s->queue[use_slot].buttons_state) {
         /* Cannot or should not combine, so add an empty item to the queue.  */
         QUEUE_INCR(use_slot);
-        s->n++;
+        hs->n++;
         usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
     }
     usb_pointer_event_combine(&s->queue[use_slot],
@@ -499,24 +497,25 @@ static void usb_keyboard_event(void *opaque, int keycode)
     USBKeyboardState *s = &hs->kbd;
     int slot;
 
-    if (s->n == QUEUE_LENGTH) {
+    if (hs->n == QUEUE_LENGTH) {
         fprintf(stderr, "usb-kbd: warning: key event queue full\n");
         return;
     }
-    slot = (s->head + s->n) & QUEUE_MASK; s->n++;
+    slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
     s->keycodes[slot] = keycode;
     usb_hid_changed(hs);
 }
 
-static void usb_keyboard_process_keycode(USBKeyboardState *s)
+static void usb_keyboard_process_keycode(USBHIDState *hs)
 {
+    USBKeyboardState *s = &hs->kbd;
     uint8_t hid_code, key;
     int i, keycode, slot;
 
-    if (s->n == 0) {
+    if (hs->n == 0) {
         return;
     }
-    slot = s->head & QUEUE_MASK; QUEUE_INCR(s->head); s->n--;
+    slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
     keycode = s->keycodes[slot];
 
     key = keycode & 0x7f;
@@ -590,7 +589,7 @@ static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
 
     /* When the buffer is empty, return the last event.  Relative
        movements will all be zero.  */
-    index = (s->n ? s->head : s->head - 1);
+    index = (hs->n ? hs->head : hs->head - 1);
     e = &s->queue[index & QUEUE_MASK];
 
     if (hs->kind == USB_MOUSE) {
@@ -613,12 +612,12 @@ static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
     if (e->buttons_state & MOUSE_EVENT_MBUTTON)
         b |= 0x04;
 
-    if (s->n &&
+    if (hs->n &&
         !e->dz &&
         (hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
         /* that deals with this event */
-        QUEUE_INCR(s->head);
-        s->n--;
+        QUEUE_INCR(hs->head);
+        hs->n--;
     }
 
     /* Appears we have to invert the wheel direction */
@@ -664,7 +663,7 @@ static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
     if (len < 2)
         return 0;
 
-    usb_keyboard_process_keycode(s);
+    usb_keyboard_process_keycode(hs);
 
     buf[0] = s->modifiers & 0xff;
     buf[1] = 0;
@@ -702,8 +701,8 @@ static void usb_mouse_handle_reset(USBDevice *dev)
     USBHIDState *s = (USBHIDState *)dev;
 
     memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
-    s->ptr.head = 0;
-    s->ptr.n = 0;
+    s->head = 0;
+    s->n = 0;
     s->protocol = 1;
 }
 
@@ -713,8 +712,8 @@ static void usb_keyboard_handle_reset(USBDevice *dev)
 
     qemu_add_kbd_event_handler(usb_keyboard_event, s);
     memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
-    s->kbd.head = 0;
-    s->kbd.n = 0;
+    s->head = 0;
+    s->n = 0;
     memset(s->kbd.key, 0, sizeof (s->kbd.key));
     s->kbd.keys = 0;
     s->protocol = 1;
@@ -822,12 +821,11 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
             usb_hid_set_next_idle(s, curtime);
             if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
                 ret = usb_pointer_poll(s, p->data, p->len);
-                s->changed = s->ptr.n > 0;
             }
             else if (s->kind == USB_KEYBOARD) {
                 ret = usb_keyboard_poll(s, p->data, p->len);
-                s->changed = s->kbd.n > 0;
             }
+            s->changed = s->n > 0;
         } else {
             goto fail;
         }
commit 5fae51a9c26c025b94f8d7c40f54b65049de7227
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Thu Jan 13 17:42:06 2011 +0100

    usb keyboard: add event event queue
    
    This patch adds a event queue to the usb keyboard.  This makes sure the
    guest will see all key events even if they come in bursts.  With this
    patch applied sending Ctrl-Alt-Del using vncviewer's F8 menu works.
    Also with autosuspend enabled the first keypress on a suspended keyboard
    takes a little longer to be delivered to the guest because the usb bus
    must be resumed first.  Without event queue this easily gets lost.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index ea49543..5f1451b 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -63,6 +63,9 @@ typedef struct USBMouseState {
 } USBMouseState;
 
 typedef struct USBKeyboardState {
+    uint32_t keycodes[QUEUE_LENGTH];
+    uint32_t head; /* index into circular queue */
+    uint32_t n;
     uint16_t modifiers;
     uint8_t leds;
     uint8_t key[16];
@@ -494,8 +497,27 @@ static void usb_keyboard_event(void *opaque, int keycode)
 {
     USBHIDState *hs = opaque;
     USBKeyboardState *s = &hs->kbd;
+    int slot;
+
+    if (s->n == QUEUE_LENGTH) {
+        fprintf(stderr, "usb-kbd: warning: key event queue full\n");
+        return;
+    }
+    slot = (s->head + s->n) & QUEUE_MASK; s->n++;
+    s->keycodes[slot] = keycode;
+    usb_hid_changed(hs);
+}
+
+static void usb_keyboard_process_keycode(USBKeyboardState *s)
+{
     uint8_t hid_code, key;
-    int i;
+    int i, keycode, slot;
+
+    if (s->n == 0) {
+        return;
+    }
+    slot = s->head & QUEUE_MASK; QUEUE_INCR(s->head); s->n--;
+    keycode = s->keycodes[slot];
 
     key = keycode & 0x7f;
     hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
@@ -528,7 +550,6 @@ static void usb_keyboard_event(void *opaque, int keycode)
             if (s->key[i] == hid_code) {
                 s->key[i] = s->key[-- s->keys];
                 s->key[s->keys] = 0x00;
-                usb_hid_changed(hs);
                 break;
             }
         if (i < 0)
@@ -543,8 +564,6 @@ static void usb_keyboard_event(void *opaque, int keycode)
         } else
             return;
     }
-
-    usb_hid_changed(hs);
 }
 
 static inline int int_clamp(int val, int vmin, int vmax)
@@ -645,6 +664,8 @@ static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
     if (len < 2)
         return 0;
 
+    usb_keyboard_process_keycode(s);
+
     buf[0] = s->modifiers & 0xff;
     buf[1] = 0;
     if (s->keys > 6)
@@ -680,7 +701,7 @@ static void usb_mouse_handle_reset(USBDevice *dev)
 {
     USBHIDState *s = (USBHIDState *)dev;
 
-    memset (s->ptr.queue, 0, sizeof (s->ptr.queue));
+    memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
     s->ptr.head = 0;
     s->ptr.n = 0;
     s->protocol = 1;
@@ -691,6 +712,11 @@ static void usb_keyboard_handle_reset(USBDevice *dev)
     USBHIDState *s = (USBHIDState *)dev;
 
     qemu_add_kbd_event_handler(usb_keyboard_event, s);
+    memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
+    s->kbd.head = 0;
+    s->kbd.n = 0;
+    memset(s->kbd.key, 0, sizeof (s->kbd.key));
+    s->kbd.keys = 0;
     s->protocol = 1;
 }
 
@@ -800,7 +826,7 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
             }
             else if (s->kind == USB_KEYBOARD) {
                 ret = usb_keyboard_poll(s, p->data, p->len);
-                s->changed = 0;
+                s->changed = s->kbd.n > 0;
             }
         } else {
             goto fail;
commit 13f8b97a57450534ccb7aaeb55095a668183fbee
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Jan 12 13:19:20 2011 +0100

    add event queueing to USB HID
    
    The polling nature of the USB HID device makes it very hard to double
    click or drag while on a high-latency VNC connection.  This patch,
    based on work done in the Xen qemu-dm tree by Ian Jackson, fixes this
    bug by adding an event queue to the device.  The event queue associates
    each movement with the correct button state, and remembers all button
    presses and releases as well.
    
    Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
    Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
    Signed-off-by: Gerd Hoffman <kraxel at redhat.com>

diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 90a2b49..ea49543 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -45,9 +45,19 @@
 #define USB_TABLET    2
 #define USB_KEYBOARD  3
 
+typedef struct USBPointerEvent {
+    int32_t xdx, ydy; /* relative iff it's a mouse, otherwise absolute */
+    int32_t dz, buttons_state;
+} USBPointerEvent;
+
+#define QUEUE_LENGTH    16 /* should be enough for a triple-click */
+#define QUEUE_MASK      (QUEUE_LENGTH-1u)
+#define QUEUE_INCR(v)   ((v)++, (v) &= QUEUE_MASK)
+
 typedef struct USBMouseState {
-    int dx, dy, dz, buttons_state;
-    int x, y;
+    USBPointerEvent queue[QUEUE_LENGTH];
+    uint32_t head; /* index into circular queue */
+    uint32_t n;
     int mouse_grabbed;
     QEMUPutMouseEntry *eh_entry;
 } USBMouseState;
@@ -433,31 +443,50 @@ static void usb_hid_changed(USBHIDState *hs)
     usb_wakeup(&hs->dev);
 }
 
-static void usb_mouse_event(void *opaque,
-                            int dx1, int dy1, int dz1, int buttons_state)
-{
-    USBHIDState *hs = opaque;
-    USBMouseState *s = &hs->ptr;
-
-    s->dx += dx1;
-    s->dy += dy1;
-    s->dz += dz1;
-    s->buttons_state = buttons_state;
+static void usb_pointer_event_clear(USBPointerEvent *e, int buttons) {
+    e->xdx = e->ydy = e->dz = 0;
+    e->buttons_state = buttons;
+}
 
-    usb_hid_changed(hs);
+static void usb_pointer_event_combine(USBPointerEvent *e, int xyrel,
+                                      int x1, int y1, int z1) {
+    if (xyrel) {
+        e->xdx += x1;
+        e->ydy += y1;
+    } else {
+        e->xdx = x1;
+        e->ydy = y1;
+    }
+    e->dz += z1;
 }
 
-static void usb_tablet_event(void *opaque,
-			     int x, int y, int dz, int buttons_state)
+static void usb_pointer_event(void *opaque,
+                              int x1, int y1, int z1, int buttons_state)
 {
     USBHIDState *hs = opaque;
     USBMouseState *s = &hs->ptr;
-
-    s->x = x;
-    s->y = y;
-    s->dz += dz;
-    s->buttons_state = buttons_state;
-
+    unsigned use_slot = (s->head + s->n - 1) & QUEUE_MASK;
+    unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
+
+    /* We combine events where feasible to keep the queue small.  We shouldn't
+     * combine anything with the first event of a particular button state, as
+     * that would change the location of the button state change.  When the
+     * queue is empty, a second event is needed because we don't know if
+     * the first event changed the button state.  */
+    if (s->n == QUEUE_LENGTH) {
+        /* Queue full.  Discard old button state, combine motion normally.  */
+        s->queue[use_slot].buttons_state = buttons_state;
+    } else if (s->n < 2 ||
+               s->queue[use_slot].buttons_state != buttons_state ||
+               s->queue[previous_slot].buttons_state != s->queue[use_slot].buttons_state) {
+        /* Cannot or should not combine, so add an empty item to the queue.  */
+        QUEUE_INCR(use_slot);
+        s->n++;
+        usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
+    }
+    usb_pointer_event_combine(&s->queue[use_slot],
+                              hs->kind == USB_MOUSE,
+                              x1, y1, z1);
     usb_hid_changed(hs);
 }
 
@@ -528,83 +557,91 @@ static inline int int_clamp(int val, int vmin, int vmax)
         return val;
 }
 
-static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
+static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
 {
     int dx, dy, dz, b, l;
+    int index;
     USBMouseState *s = &hs->ptr;
+    USBPointerEvent *e;
 
     if (!s->mouse_grabbed) {
         qemu_activate_mouse_event_handler(s->eh_entry);
-	s->mouse_grabbed = 1;
+        s->mouse_grabbed = 1;
     }
 
-    dx = int_clamp(s->dx, -127, 127);
-    dy = int_clamp(s->dy, -127, 127);
-    dz = int_clamp(s->dz, -127, 127);
-
-    s->dx -= dx;
-    s->dy -= dy;
-    s->dz -= dz;
+    /* When the buffer is empty, return the last event.  Relative
+       movements will all be zero.  */
+    index = (s->n ? s->head : s->head - 1);
+    e = &s->queue[index & QUEUE_MASK];
 
-    /* Appears we have to invert the wheel direction */
-    dz = 0 - dz;
+    if (hs->kind == USB_MOUSE) {
+        dx = int_clamp(e->xdx, -127, 127);
+        dy = int_clamp(e->ydy, -127, 127);
+        e->xdx -= dx;
+        e->ydy -= dy;
+    } else {
+        dx = e->xdx;
+        dy = e->ydy;
+    }
+    dz = int_clamp(e->dz, -127, 127);
+    e->dz -= dz;
 
     b = 0;
-    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
+    if (e->buttons_state & MOUSE_EVENT_LBUTTON)
         b |= 0x01;
-    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
+    if (e->buttons_state & MOUSE_EVENT_RBUTTON)
         b |= 0x02;
-    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
+    if (e->buttons_state & MOUSE_EVENT_MBUTTON)
         b |= 0x04;
 
-    l = 0;
-    if (len > l)
-        buf[l ++] = b;
-    if (len > l)
-        buf[l ++] = dx;
-    if (len > l)
-        buf[l ++] = dy;
-    if (len > l)
-        buf[l ++] = dz;
-    return l;
-}
-
-static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
-{
-    int dz, b, l;
-    USBMouseState *s = &hs->ptr;
-
-    if (!s->mouse_grabbed) {
-        qemu_activate_mouse_event_handler(s->eh_entry);
-	s->mouse_grabbed = 1;
+    if (s->n &&
+        !e->dz &&
+        (hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
+        /* that deals with this event */
+        QUEUE_INCR(s->head);
+        s->n--;
     }
 
-    dz = int_clamp(s->dz, -127, 127);
-    s->dz -= dz;
-
     /* Appears we have to invert the wheel direction */
     dz = 0 - dz;
-    b = 0;
-    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
-        b |= 0x01;
-    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
-        b |= 0x02;
-    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
-        b |= 0x04;
+    l = 0;
+    switch (hs->kind) {
+    case USB_MOUSE:
+        if (len > l)
+            buf[l++] = b;
+        if (len > l)
+            buf[l++] = dx;
+        if (len > l)
+            buf[l++] = dy;
+        if (len > l)
+            buf[l++] = dz;
+        break;
 
-    buf[0] = b;
-    buf[1] = s->x & 0xff;
-    buf[2] = s->x >> 8;
-    buf[3] = s->y & 0xff;
-    buf[4] = s->y >> 8;
-    buf[5] = dz;
-    l = 6;
+    case USB_TABLET:
+        if (len > l)
+            buf[l++] = b;
+        if (len > l)
+            buf[l++] = dx & 0xff;
+        if (len > l)
+            buf[l++] = dx >> 8;
+        if (len > l)
+            buf[l++] = dy & 0xff;
+        if (len > l)
+            buf[l++] = dy >> 8;
+        if (len > l)
+            buf[l++] = dz;
+        break;
+
+    default:
+        abort();
+    }
 
     return l;
 }
 
-static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
+static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
 {
+    USBKeyboardState *s = &hs->kbd;
     if (len < 2)
         return 0;
 
@@ -643,12 +680,9 @@ static void usb_mouse_handle_reset(USBDevice *dev)
 {
     USBHIDState *s = (USBHIDState *)dev;
 
-    s->ptr.dx = 0;
-    s->ptr.dy = 0;
-    s->ptr.dz = 0;
-    s->ptr.x = 0;
-    s->ptr.y = 0;
-    s->ptr.buttons_state = 0;
+    memset (s->ptr.queue, 0, sizeof (s->ptr.queue));
+    s->ptr.head = 0;
+    s->ptr.n = 0;
     s->protocol = 1;
 }
 
@@ -708,12 +742,10 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
         }
         break;
     case GET_REPORT:
-	if (s->kind == USB_MOUSE)
-            ret = usb_mouse_poll(s, data, length);
-	else if (s->kind == USB_TABLET)
-            ret = usb_tablet_poll(s, data, length);
+        if (s->kind == USB_MOUSE || s->kind == USB_TABLET)
+            ret = usb_pointer_poll(s, data, length);
         else if (s->kind == USB_KEYBOARD)
-            ret = usb_keyboard_poll(&s->kbd, data, length);
+            ret = usb_keyboard_poll(s, data, length);
         break;
     case SET_REPORT:
         if (s->kind == USB_KEYBOARD)
@@ -762,13 +794,14 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
             if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
                 return USB_RET_NAK;
             usb_hid_set_next_idle(s, curtime);
-            s->changed = 0;
-            if (s->kind == USB_MOUSE)
-                ret = usb_mouse_poll(s, p->data, p->len);
-            else if (s->kind == USB_TABLET)
-                ret = usb_tablet_poll(s, p->data, p->len);
-            else if (s->kind == USB_KEYBOARD)
-                ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
+            if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
+                ret = usb_pointer_poll(s, p->data, p->len);
+                s->changed = s->ptr.n > 0;
+            }
+            else if (s->kind == USB_KEYBOARD) {
+                ret = usb_keyboard_poll(s, p->data, p->len);
+                s->changed = 0;
+            }
         } else {
             goto fail;
         }
@@ -803,13 +836,13 @@ static int usb_hid_initfn(USBDevice *dev, int kind)
     s->kind = kind;
 
     if (s->kind == USB_MOUSE) {
-        s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s,
+        s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
                                                        0, "QEMU USB Mouse");
     } else if (s->kind == USB_TABLET) {
-        s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s,
+        s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
                                                        1, "QEMU USB Tablet");
     }
-        
+
     /* Force poll routine to be run and grab input the first time.  */
     s->changed = 1;
     return 0;
commit 96df67d1c3928704cd76d0b2e76372ef18658e85
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Mon Jan 24 09:32:20 2011 +0000

    block: Use backing format driver during image creation
    
    The backing format should be honored during image creation.  For some
    reason we currently use the image format to open the backing file.  This
    fails when the backing file has a different format than the image being
    created.  Keep the image and backing format drivers completely separate.
    
    Also print the backing filename if there is an error opening the backing
    file instead of the image filename.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Acked-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block.c b/block.c
index ff2795b..7ad3ddf 100644
--- a/block.c
+++ b/block.c
@@ -2778,6 +2778,7 @@ int bdrv_img_create(const char *filename, const char *fmt,
     QEMUOptionParameter *backing_fmt, *backing_file;
     BlockDriverState *bs = NULL;
     BlockDriver *drv, *proto_drv;
+    BlockDriver *backing_drv = NULL;
     int ret = 0;
 
     /* Find driver and parse its options */
@@ -2846,7 +2847,8 @@ int bdrv_img_create(const char *filename, const char *fmt,
 
     backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
     if (backing_fmt && backing_fmt->value.s) {
-        if (!bdrv_find_format(backing_fmt->value.s)) {
+        backing_drv = bdrv_find_format(backing_fmt->value.s);
+        if (!backing_drv) {
             error_report("Unknown backing file format '%s'",
                          backing_fmt->value.s);
             ret = -EINVAL;
@@ -2863,9 +2865,9 @@ int bdrv_img_create(const char *filename, const char *fmt,
 
             bs = bdrv_new("");
 
-            ret = bdrv_open(bs, backing_file->value.s, flags, drv);
+            ret = bdrv_open(bs, backing_file->value.s, flags, backing_drv);
             if (ret < 0) {
-                error_report("Could not open '%s'", filename);
+                error_report("Could not open '%s'", backing_file->value.s);
                 goto out;
             }
             bdrv_get_geometry(bs, &size);
commit 850ec1133bf0f78ff19402cfd5d77eea376599a9
Author: Markus Armbruster <armbru at redhat.com>
Date:   Mon Jan 17 19:31:29 2011 +0100

    blockdev: Fix drive_del not to crash when drive is not in use
    
    Watch this:
    
        (qemu) drive_add 0 if=none,file=tmp.img
        OK
        (qemu) info block
        none0: type=hd removable=0 file=tmp.img ro=0 drv=raw encrypted=0
        (qemu) drive_del none0
        Segmentation fault (core dumped)
    
    do_drive_del()'s code to clean up the pointer from a qdev using the
    drive back to the drive needs to check whether such a device exists.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 0621390..f7f591f 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -687,13 +687,15 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 
     /* clean up guest state from pointing to host resource by
      * finding and removing DeviceState "drive" property */
-    for (prop = bs->peer->info->props; prop && prop->name; prop++) {
-        if (prop->info->type == PROP_TYPE_DRIVE) {
-            ptr = qdev_get_prop_ptr(bs->peer, prop);
-            if ((*ptr) == bs) {
-                bdrv_detach(bs, bs->peer);
-                *ptr = NULL;
-                break;
+    if (bs->peer) {
+        for (prop = bs->peer->info->props; prop && prop->name; prop++) {
+            if (prop->info->type == PROP_TYPE_DRIVE) {
+                ptr = qdev_get_prop_ptr(bs->peer, prop);
+                if (*ptr == bs) {
+                    bdrv_detach(bs, bs->peer);
+                    *ptr = NULL;
+                    break;
+                }
             }
         }
     }
commit 807105a775323be9b45ef1e965c5aad85a5ec281
Author: Markus Armbruster <armbru at redhat.com>
Date:   Mon Jan 17 19:31:27 2011 +0100

    blockdev: Make drive_init() use error_report()
    
    This makes the errors point to the error location, and fixes drive_add
    to report errors in the monitor instead of stderr.
    
    While there, tweak a few error messages for consistency.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 28c051b..0621390 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -107,7 +107,7 @@ DriveInfo *drive_get_by_blockdev(BlockDriverState *bs)
 
 static void bdrv_format_print(void *opaque, const char *name)
 {
-    fprintf(stderr, " %s", name);
+    error_printf(" %s", name);
 }
 
 void drive_uninit(DriveInfo *dinfo)
@@ -129,8 +129,8 @@ static int parse_block_error_action(const char *buf, int is_read)
     } else if (!strcmp(buf, "report")) {
         return BLOCK_ERR_REPORT;
     } else {
-        fprintf(stderr, "qemu: '%s' invalid %s error action\n",
-            buf, is_read ? "read" : "write");
+        error_report("'%s' invalid %s error action",
+                     buf, is_read ? "read" : "write");
         return -1;
     }
 }
@@ -217,31 +217,30 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
 	    type = IF_NONE;
             max_devs = 0;
 	} else {
-            fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf);
+            error_report("unsupported bus type '%s'", buf);
             return NULL;
 	}
     }
 
     if (cyls || heads || secs) {
         if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
-            fprintf(stderr, "qemu: invalid physical cyls number\n");
+            error_report("invalid physical cyls number");
 	    return NULL;
 	}
         if (heads < 1 || (type == IF_IDE && heads > 16)) {
-            fprintf(stderr, "qemu: invalid physical heads number\n");
+            error_report("invalid physical heads number");
 	    return NULL;
 	}
         if (secs < 1 || (type == IF_IDE && secs > 63)) {
-            fprintf(stderr, "qemu: invalid physical secs number\n");
+            error_report("invalid physical secs number");
 	    return NULL;
 	}
     }
 
     if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
         if (!cyls) {
-            fprintf(stderr,
-                    "qemu: '%s' trans must be used with cyls,heads and secs\n",
-                    buf);
+            error_report("'%s' trans must be used with cyls,heads and secs",
+                         buf);
             return NULL;
         }
         if (!strcmp(buf, "none"))
@@ -251,7 +250,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
         else if (!strcmp(buf, "auto"))
             translation = BIOS_ATA_TRANSLATION_AUTO;
 	else {
-            fprintf(stderr, "qemu: '%s' invalid translation type\n", buf);
+            error_report("'%s' invalid translation type", buf);
 	    return NULL;
 	}
     }
@@ -261,13 +260,12 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
 	    media = MEDIA_DISK;
 	} else if (!strcmp(buf, "cdrom")) {
             if (cyls || secs || heads) {
-                fprintf(stderr,
-                        "qemu: '%s' invalid physical CHS format\n", buf);
+                error_report("'%s' invalid physical CHS format", buf);
 	        return NULL;
             }
 	    media = MEDIA_CDROM;
 	} else {
-	    fprintf(stderr, "qemu: '%s' invalid media\n", buf);
+	    error_report("'%s' invalid media", buf);
 	    return NULL;
 	}
     }
@@ -283,7 +281,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
         } else if (!strcmp(buf, "writethrough")) {
             /* this is the default */
         } else {
-           fprintf(stderr, "qemu: invalid cache option\n");
+           error_report("invalid cache option");
            return NULL;
         }
     }
@@ -295,7 +293,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
         } else if (!strcmp(buf, "threads")) {
             /* this is the default */
         } else {
-           fprintf(stderr, "qemu: invalid aio option\n");
+           error_report("invalid aio option");
            return NULL;
         }
     }
@@ -303,14 +301,14 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
 
     if ((buf = qemu_opt_get(opts, "format")) != NULL) {
        if (strcmp(buf, "?") == 0) {
-            fprintf(stderr, "qemu: Supported formats:");
-            bdrv_iterate_format(bdrv_format_print, NULL);
-            fprintf(stderr, "\n");
-	    return NULL;
+           error_printf("Supported formats:");
+           bdrv_iterate_format(bdrv_format_print, NULL);
+           error_printf("\n");
+           return NULL;
         }
         drv = bdrv_find_whitelisted_format(buf);
         if (!drv) {
-            fprintf(stderr, "qemu: '%s' invalid format\n", buf);
+            error_report("'%s' invalid format", buf);
             return NULL;
         }
     }
@@ -318,7 +316,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
     on_write_error = BLOCK_ERR_STOP_ENOSPC;
     if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
         if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
-            fprintf(stderr, "werror is not supported by this format\n");
+            error_report("werror is not supported by this bus type");
             return NULL;
         }
 
@@ -331,7 +329,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
     on_read_error = BLOCK_ERR_REPORT;
     if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
         if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) {
-            fprintf(stderr, "rerror is not supported by this format\n");
+            error_report("rerror is not supported by this bus type");
             return NULL;
         }
 
@@ -343,7 +341,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
 
     if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
         if (type != IF_VIRTIO) {
-            fprintf(stderr, "addr is not supported\n");
+            error_report("addr is not supported by this bus type");
             return NULL;
         }
     }
@@ -352,8 +350,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
 
     if (index != -1) {
         if (bus_id != 0 || unit_id != -1) {
-            fprintf(stderr,
-                    "qemu: index cannot be used with bus and unit\n");
+            error_report("index cannot be used with bus and unit");
             return NULL;
         }
         if (max_devs == 0)
@@ -384,8 +381,8 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
     /* check unit id */
 
     if (max_devs && unit_id >= max_devs) {
-        fprintf(stderr, "qemu: unit %d too big (max is %d)\n",
-                unit_id, max_devs - 1);
+        error_report("unit %d too big (max is %d)",
+                     unit_id, max_devs - 1);
         return NULL;
     }
 
@@ -479,7 +476,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
         ro = 1;
     } else if (ro == 1) {
         if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
-            fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
+            error_report("readonly not supported by this bus type");
             return NULL;
         }
     }
@@ -488,8 +485,8 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
 
     ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv);
     if (ret < 0) {
-        fprintf(stderr, "qemu: could not open disk image %s: %s\n",
-                        file, strerror(-ret));
+        error_report("could not open disk image %s: %s",
+                     file, strerror(-ret));
         return NULL;
     }
 
commit 483848540557aef6af08adbe3ef8201b961220d5
Author: Markus Armbruster <armbru at redhat.com>
Date:   Mon Jan 17 19:31:26 2011 +0100

    blockdev: Fix error message for invalid -drive CHS
    
    When cyls, heads or secs are out of range, the error message prints
    buf, which points to the value of option "if".  Bogus, may even be
    null.  Drop that.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index 662f7a9..28c051b 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -224,15 +224,15 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
 
     if (cyls || heads || secs) {
         if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
-            fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf);
+            fprintf(stderr, "qemu: invalid physical cyls number\n");
 	    return NULL;
 	}
         if (heads < 1 || (type == IF_IDE && heads > 16)) {
-            fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf);
+            fprintf(stderr, "qemu: invalid physical heads number\n");
 	    return NULL;
 	}
         if (secs < 1 || (type == IF_IDE && secs > 63)) {
-            fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf);
+            fprintf(stderr, "qemu: invalid physical secs number\n");
 	    return NULL;
 	}
     }
commit 77358b59f6f3ef571fb2262f5f6216e179d07ecb
Author: Pierre Riteau <Pierre.Riteau at irisa.fr>
Date:   Fri Jan 21 12:42:30 2011 +0100

    Fix block migration when the device size is not a multiple of 1 MB
    
    b02bea3a85cc939f09aa674a3f1e4f36d418c007 added a check on the return
    value of bdrv_write and aborts migration when it fails. However, if the
    size of the block device to migrate is not a multiple of BLOCK_SIZE
    (currently 1 MB), the last bdrv_write will fail with -EIO.
    
    Fixed by calling bdrv_write with the correct size of the last block.
    
    Signed-off-by: Pierre Riteau <Pierre.Riteau at irisa.fr>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index 60b9fc0..c9d3e81 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -638,8 +638,10 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
     int len, flags;
     char device_name[256];
     int64_t addr;
-    BlockDriverState *bs;
+    BlockDriverState *bs, *bs_prev = NULL;
     uint8_t *buf;
+    int64_t total_sectors = 0;
+    int nr_sectors;
 
     do {
         addr = qemu_get_be64(f);
@@ -661,10 +663,26 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
                 return -EINVAL;
             }
 
+            if (bs != bs_prev) {
+                bs_prev = bs;
+                total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
+                if (total_sectors <= 0) {
+                    error_report("Error getting length of block device %s\n",
+                                 device_name);
+                    return -EINVAL;
+                }
+            }
+
+            if (total_sectors - addr < BDRV_SECTORS_PER_DIRTY_CHUNK) {
+                nr_sectors = total_sectors - addr;
+            } else {
+                nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
+            }
+
             buf = qemu_malloc(BLOCK_SIZE);
 
             qemu_get_buffer(f, buf, BLOCK_SIZE);
-            ret = bdrv_write(bs, addr, buf, BDRV_SECTORS_PER_DIRTY_CHUNK);
+            ret = bdrv_write(bs, addr, buf, nr_sectors);
 
             qemu_free(buf);
             if (ret < 0) {
commit c743849bee7333c7ef256b7e12e34ed6f907064f
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date:   Fri Jan 14 22:44:33 2011 +0000

    qed: Refuse to create images on block devices
    
    QED relies on the underlying filesystem to extend the file and maintain
    its size.  Check that images are not created on a block device.
    
    Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qed.c b/block/qed.c
index 085c4f2..a46f9ef 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -469,6 +469,12 @@ static int qed_create(const char *filename, uint32_t cluster_size,
         return ret;
     }
 
+    /* File must start empty and grow, check truncate is supported */
+    ret = bdrv_truncate(bs, 0);
+    if (ret < 0) {
+        goto out;
+    }
+
     if (backing_file) {
         header.features |= QED_F_BACKING_FILE;
         header.backing_filename_offset = sizeof(le_header);
commit e61846908efd5ea0916d157a82adabf0674a01b0
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Jan 17 15:35:28 2011 +0100

    Documentation: Add qemu-img check/rebase
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/qemu-img.texi b/qemu-img.texi
index 1b90ddb..ced64a4 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -59,6 +59,13 @@ lists all snapshots in the given image
 Command description:
 
 @table @option
+ at item check [-f @var{fmt}] @var{filename}
+
+Perform a consistency check on the disk image @var{filename}.
+
+Only the formats @code{qcow2}, @code{qed} and @code{vdi} support
+consistency checks.
+
 @item create [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}]
 
 Create the new disk image @var{filename} of size @var{size} and format
@@ -107,6 +114,40 @@ they are displayed too.
 
 List, apply, create or delete snapshots in image @var{filename}.
 
+ at item rebase [-f @var{fmt}] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
+
+Changes the backing file of an image. Only the formats @code{qcow2} and
+ at code{qed} support changing the backing file.
+
+The backing file is changed to @var{backing_file} and (if the image format of
+ at var{filename} supports this) the backing file format is changed to
+ at var{backing_fmt}.
+
+There are two different modes in which @code{rebase} can operate:
+ at table @option
+ at item Safe mode
+This is the default mode and performs a real rebase operation. The new backing
+file may differ from the old one and qemu-img rebase will take care of keeping
+the guest-visible content of @var{filename} unchanged.
+
+In order to achieve this, any clusters that differ between @var{backing_file}
+and the old backing file of @var{filename} are merged into @var{filename}
+before actually changing the backing file.
+
+Note that the safe mode is an expensive operation, comparable to converting
+an image. It only works if the old backing file still exists.
+
+ at item Unsafe mode
+qemu-img uses the unsafe mode if @code{-u} is specified. In this mode, only the
+backing file name and format of @var{filename} is changed without any checks
+on the file contents. The user must take care of specifying the correct new
+backing file, or the guest-visible content of the image will be corrupted.
+
+This mode is useful for renaming or moving the backing file to somewhere else.
+It can be used without an accessible old backing file, i.e. you can use it to
+fix an image whose backing file has already been moved/renamed.
+ at end table
+
 @item resize @var{filename} [+ | -]@var{size}
 
 Change the disk image as if it had been created with @var{size}.
commit 1635eecc413ed680013cf77e6994901cafe15590
Author: Stefan Weil <weil at mail.berlios.de>
Date:   Sat Jan 15 19:01:03 2011 +0100

    ide: Remove unneeded null pointer check
    
    With bm == NULL, other code in the same function would crash.
    
    This bug was reported by cppcheck:
    hw/ide/pci.c:280: error: Possible null pointer dereference: bm
    
    Cc: Michael S. Tsirkin <mst at redhat.com>
    Signed-off-by: Stefan Weil <weil at mail.berlios.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 987caff..35168cb 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -267,9 +267,7 @@ static void bmdma_irq(void *opaque, int n, int level)
         return;
     }
 
-    if (bm) {
-        bm->status |= BM_STATUS_INT;
-    }
+    bm->status |= BM_STATUS_INT;
 
     /* trigger the real irq */
     qemu_set_irq(bm->irq, level);
commit 3de0a2944bdb3047dce275560631834bcb4afe22
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Fri Jan 14 15:55:38 2011 +0100

    qcow2: Batch flushes for COW
    
    qcow2 calls bdrv_flush() after performing COW in order to ensure that the
    L2 table change is never written before the copy is safe on disk. Now that the
    L2 table is cached, we can wait with flushing until we write out the next L2
    table.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index 5f1740b..8f2955b 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -38,6 +38,7 @@ struct Qcow2Cache {
     int                     size;
     Qcow2CachedTable*       entries;
     struct Qcow2Cache*      depends;
+    bool                    depends_on_flush;
     bool                    writethrough;
 };
 
@@ -85,13 +86,15 @@ static int qcow2_cache_flush_dependency(BlockDriverState *bs, Qcow2Cache *c)
     }
 
     c->depends = NULL;
+    c->depends_on_flush = false;
+
     return 0;
 }
 
 static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
 {
     BDRVQcowState *s = bs->opaque;
-    int ret;
+    int ret = 0;
 
     if (!c->entries[i].dirty || !c->entries[i].offset) {
         return 0;
@@ -99,11 +102,17 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
 
     if (c->depends) {
         ret = qcow2_cache_flush_dependency(bs, c);
-        if (ret < 0) {
-            return ret;
+    } else if (c->depends_on_flush) {
+        ret = bdrv_flush(bs->file);
+        if (ret >= 0) {
+            c->depends_on_flush = false;
         }
     }
 
+    if (ret < 0) {
+        return ret;
+    }
+
     if (c == s->refcount_block_cache) {
         BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART);
     } else if (c == s->l2_table_cache) {
@@ -167,6 +176,11 @@ int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
     return 0;
 }
 
+void qcow2_cache_depends_on_flush(Qcow2Cache *c)
+{
+    c->depends_on_flush = true;
+}
+
 static int qcow2_cache_find_entry_to_replace(Qcow2Cache *c)
 {
     int i;
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 76e7e07..1c2003a 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -637,7 +637,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
      * handled.
      */
     if (cow) {
-        bdrv_flush(bs->file);
+        qcow2_cache_depends_on_flush(s->l2_table_cache);
     }
 
     qcow2_cache_set_dependency(bs, s->l2_table_cache, s->refcount_block_cache);
diff --git a/block/qcow2.h b/block/qcow2.h
index 11cbce3..6d80120 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -229,6 +229,7 @@ void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
 int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
 int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
     Qcow2Cache *dependency);
+void qcow2_cache_depends_on_flush(Qcow2Cache *c);
 
 int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
     void **table);
commit 29c1a7301af752de6721e031d31faa48887204bd
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Jan 10 17:17:28 2011 +0100

    qcow2: Use QcowCache
    
    Use the new functions of qcow2-cache.c for everything that works on refcount
    block and L2 tables.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index f7c4e2a..5f1740b 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -104,6 +104,12 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
         }
     }
 
+    if (c == s->refcount_block_cache) {
+        BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART);
+    } else if (c == s->l2_table_cache) {
+        BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
+    }
+
     ret = bdrv_pwrite(bs->file, c->entries[i].offset, c->entries[i].table,
         s->cluster_size);
     if (ret < 0) {
@@ -218,6 +224,10 @@ static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
 
     c->entries[i].offset = 0;
     if (read_from_disk) {
+        if (c == s->l2_table_cache) {
+            BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
+        }
+
         ret = bdrv_pread(bs->file, offset, c->entries[i].table, s->cluster_size);
         if (ret < 0) {
             return ret;
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index c3ef550..76e7e07 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -67,7 +67,11 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size)
         qemu_free(new_l1_table);
         return new_l1_table_offset;
     }
-    bdrv_flush(bs->file);
+
+    ret = qcow2_cache_flush(bs, s->refcount_block_cache);
+    if (ret < 0) {
+        return ret;
+    }
 
     BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE);
     for(i = 0; i < s->l1_size; i++)
@@ -98,63 +102,6 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size)
     return ret;
 }
 
-void qcow2_l2_cache_reset(BlockDriverState *bs)
-{
-    BDRVQcowState *s = bs->opaque;
-
-    memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
-    memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));
-    memset(s->l2_cache_counts, 0, L2_CACHE_SIZE * sizeof(uint32_t));
-}
-
-static inline int l2_cache_new_entry(BlockDriverState *bs)
-{
-    BDRVQcowState *s = bs->opaque;
-    uint32_t min_count;
-    int min_index, i;
-
-    /* find a new entry in the least used one */
-    min_index = 0;
-    min_count = 0xffffffff;
-    for(i = 0; i < L2_CACHE_SIZE; i++) {
-        if (s->l2_cache_counts[i] < min_count) {
-            min_count = s->l2_cache_counts[i];
-            min_index = i;
-        }
-    }
-    return min_index;
-}
-
-/*
- * seek_l2_table
- *
- * seek l2_offset in the l2_cache table
- * if not found, return NULL,
- * if found,
- *   increments the l2 cache hit count of the entry,
- *   if counter overflow, divide by two all counters
- *   return the pointer to the l2 cache entry
- *
- */
-
-static uint64_t *seek_l2_table(BDRVQcowState *s, uint64_t l2_offset)
-{
-    int i, j;
-
-    for(i = 0; i < L2_CACHE_SIZE; i++) {
-        if (l2_offset == s->l2_cache_offsets[i]) {
-            /* increment the hit count */
-            if (++s->l2_cache_counts[i] == 0xffffffff) {
-                for(j = 0; j < L2_CACHE_SIZE; j++) {
-                    s->l2_cache_counts[j] >>= 1;
-                }
-            }
-            return s->l2_cache + (i << s->l2_bits);
-        }
-    }
-    return NULL;
-}
-
 /*
  * l2_load
  *
@@ -169,33 +116,11 @@ static int l2_load(BlockDriverState *bs, uint64_t l2_offset,
     uint64_t **l2_table)
 {
     BDRVQcowState *s = bs->opaque;
-    int min_index;
     int ret;
 
-    /* seek if the table for the given offset is in the cache */
-
-    *l2_table = seek_l2_table(s, l2_offset);
-    if (*l2_table != NULL) {
-        return 0;
-    }
-
-    /* not found: load a new entry in the least used one */
-
-    min_index = l2_cache_new_entry(bs);
-    *l2_table = s->l2_cache + (min_index << s->l2_bits);
-
-    BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
-    ret = bdrv_pread(bs->file, l2_offset, *l2_table,
-        s->l2_size * sizeof(uint64_t));
-    if (ret < 0) {
-        qcow2_l2_cache_reset(bs);
-        return ret;
-    }
-
-    s->l2_cache_offsets[min_index] = l2_offset;
-    s->l2_cache_counts[min_index] = 1;
+    ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset, (void**) l2_table);
 
-    return 0;
+    return ret;
 }
 
 /*
@@ -238,7 +163,6 @@ static int write_l1_entry(BlockDriverState *bs, int l1_index)
 static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
 {
     BDRVQcowState *s = bs->opaque;
-    int min_index;
     uint64_t old_l2_offset;
     uint64_t *l2_table;
     int64_t l2_offset;
@@ -252,29 +176,48 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
     if (l2_offset < 0) {
         return l2_offset;
     }
-    bdrv_flush(bs->file);
+
+    ret = qcow2_cache_flush(bs, s->refcount_block_cache);
+    if (ret < 0) {
+        goto fail;
+    }
 
     /* allocate a new entry in the l2 cache */
 
-    min_index = l2_cache_new_entry(bs);
-    l2_table = s->l2_cache + (min_index << s->l2_bits);
+    ret = qcow2_cache_get_empty(bs, s->l2_table_cache, l2_offset, (void**) table);
+    if (ret < 0) {
+        return ret;
+    }
+
+    l2_table = *table;
 
     if (old_l2_offset == 0) {
         /* if there was no old l2 table, clear the new table */
         memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
     } else {
+        uint64_t* old_table;
+
         /* if there was an old l2 table, read it from the disk */
         BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_COW_READ);
-        ret = bdrv_pread(bs->file, old_l2_offset, l2_table,
-            s->l2_size * sizeof(uint64_t));
+        ret = qcow2_cache_get(bs, s->l2_table_cache, old_l2_offset,
+            (void**) &old_table);
+        if (ret < 0) {
+            goto fail;
+        }
+
+        memcpy(l2_table, old_table, s->cluster_size);
+
+        ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &old_table);
         if (ret < 0) {
             goto fail;
         }
     }
+
     /* write the l2 table to the file */
     BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_WRITE);
-    ret = bdrv_pwrite_sync(bs->file, l2_offset, l2_table,
-        s->l2_size * sizeof(uint64_t));
+
+    qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
+    ret = qcow2_cache_flush(bs, s->l2_table_cache);
     if (ret < 0) {
         goto fail;
     }
@@ -286,17 +229,12 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
         goto fail;
     }
 
-    /* update the l2 cache entry */
-
-    s->l2_cache_offsets[min_index] = l2_offset;
-    s->l2_cache_counts[min_index] = 1;
-
     *table = l2_table;
     return 0;
 
 fail:
+    qcow2_cache_put(bs, s->l2_table_cache, (void**) table);
     s->l1_table[l1_index] = old_l2_offset;
-    qcow2_l2_cache_reset(bs);
     return ret;
 }
 
@@ -521,6 +459,8 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
                 &l2_table[l2_index], 0, QCOW_OFLAG_COPIED);
     }
 
+    qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+
    nb_available = (c * s->cluster_sectors);
 out:
     if (nb_available > nb_needed)
@@ -575,6 +515,7 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
             return ret;
         }
     } else {
+        /* FIXME Order */
         if (l2_offset)
             qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
         ret = l2_allocate(bs, l1_index, &l2_table);
@@ -632,6 +573,7 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
 
     cluster_offset = qcow2_alloc_bytes(bs, compressed_size);
     if (cluster_offset < 0) {
+        qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
         return 0;
     }
 
@@ -646,38 +588,14 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
     /* compressed clusters never have the copied flag */
 
     BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED);
+    qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
     l2_table[l2_index] = cpu_to_be64(cluster_offset);
-    if (bdrv_pwrite_sync(bs->file,
-                    l2_offset + l2_index * sizeof(uint64_t),
-                    l2_table + l2_index,
-                    sizeof(uint64_t)) < 0)
-        return 0;
-
-    return cluster_offset;
-}
-
-/*
- * Write L2 table updates to disk, writing whole sectors to avoid a
- * read-modify-write in bdrv_pwrite
- */
-#define L2_ENTRIES_PER_SECTOR (512 / 8)
-static int write_l2_entries(BlockDriverState *bs, uint64_t *l2_table,
-    uint64_t l2_offset, int l2_index, int num)
-{
-    int l2_start_index = l2_index & ~(L1_ENTRIES_PER_SECTOR - 1);
-    int start_offset = (8 * l2_index) & ~511;
-    int end_offset = (8 * (l2_index + num) + 511) & ~511;
-    size_t len = end_offset - start_offset;
-    int ret;
-
-    BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
-    ret = bdrv_pwrite(bs->file, l2_offset + start_offset,
-        &l2_table[l2_start_index], len);
+    ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
     if (ret < 0) {
-        return ret;
+        return 0;
     }
 
-    return 0;
+    return cluster_offset;
 }
 
 int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
@@ -686,6 +604,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
     int i, j = 0, l2_index, ret;
     uint64_t *old_cluster, start_sect, l2_offset, *l2_table;
     uint64_t cluster_offset = m->cluster_offset;
+    bool cow = false;
 
     if (m->nb_clusters == 0)
         return 0;
@@ -695,6 +614,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
     /* copy content of unmodified sectors */
     start_sect = (m->offset & ~(s->cluster_size - 1)) >> 9;
     if (m->n_start) {
+        cow = true;
         ret = copy_sectors(bs, start_sect, cluster_offset, 0, m->n_start);
         if (ret < 0)
             goto err;
@@ -702,17 +622,30 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
 
     if (m->nb_available & (s->cluster_sectors - 1)) {
         uint64_t end = m->nb_available & ~(uint64_t)(s->cluster_sectors - 1);
+        cow = true;
         ret = copy_sectors(bs, start_sect + end, cluster_offset + (end << 9),
                 m->nb_available - end, s->cluster_sectors);
         if (ret < 0)
             goto err;
     }
 
-    /* update L2 table */
+    /*
+     * Update L2 table.
+     *
+     * Before we update the L2 table to actually point to the new cluster, we
+     * need to be sure that the refcounts have been increased and COW was
+     * handled.
+     */
+    if (cow) {
+        bdrv_flush(bs->file);
+    }
+
+    qcow2_cache_set_dependency(bs, s->l2_table_cache, s->refcount_block_cache);
     ret = get_cluster_table(bs, m->offset, &l2_table, &l2_offset, &l2_index);
     if (ret < 0) {
         goto err;
     }
+    qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
 
     for (i = 0; i < m->nb_clusters; i++) {
         /* if two concurrent writes happen to the same unallocated cluster
@@ -728,16 +661,9 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
                     (i << s->cluster_bits)) | QCOW_OFLAG_COPIED);
      }
 
-    /*
-     * Before we update the L2 table to actually point to the new cluster, we
-     * need to be sure that the refcounts have been increased and COW was
-     * handled.
-     */
-    bdrv_flush(bs->file);
 
-    ret = write_l2_entries(bs, l2_table, l2_offset, l2_index, m->nb_clusters);
+    ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
     if (ret < 0) {
-        qcow2_l2_cache_reset(bs);
         goto err;
     }
 
@@ -746,7 +672,6 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
      * Also flush bs->file to get the right order for L2 and refcount update.
      */
     if (j != 0) {
-        bdrv_flush(bs->file);
         for (i = 0; i < j; i++) {
             qcow2_free_any_clusters(bs,
                 be64_to_cpu(old_cluster[i]) & ~QCOW_OFLAG_COPIED, 1);
@@ -868,7 +793,8 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
                 m->depends_on = old_alloc;
                 m->nb_clusters = 0;
                 *num = 0;
-                return 0;
+                ret = 0;
+                goto fail;
             }
         }
     }
@@ -884,7 +810,8 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
     cluster_offset = qcow2_alloc_clusters(bs, nb_clusters * s->cluster_size);
     if (cluster_offset < 0) {
         QLIST_REMOVE(m, next_in_flight);
-        return cluster_offset;
+        ret = cluster_offset;
+        goto fail;
     }
 
     /* save info needed for meta data update */
@@ -893,12 +820,21 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
     m->nb_clusters = nb_clusters;
 
 out:
+    ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+    if (ret < 0) {
+        return ret;
+    }
+
     m->nb_available = MIN(nb_clusters << (s->cluster_bits - 9), n_end);
     m->cluster_offset = cluster_offset;
 
     *num = m->nb_available - n_start;
 
     return 0;
+
+fail:
+    qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+    return ret;
 }
 
 static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index a10453c..e37e226 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -32,27 +32,6 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
                             int addend);
 
 
-static int cache_refcount_updates = 0;
-
-static int write_refcount_block(BlockDriverState *bs)
-{
-    BDRVQcowState *s = bs->opaque;
-    size_t size = s->cluster_size;
-
-    if (s->refcount_block_cache_offset == 0) {
-        return 0;
-    }
-
-    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE);
-    if (bdrv_pwrite_sync(bs->file, s->refcount_block_cache_offset,
-            s->refcount_block_cache, size) < 0)
-    {
-        return -EIO;
-    }
-
-    return 0;
-}
-
 /*********************************************************/
 /* refcount handling */
 
@@ -61,7 +40,6 @@ int qcow2_refcount_init(BlockDriverState *bs)
     BDRVQcowState *s = bs->opaque;
     int ret, refcount_table_size2, i;
 
-    s->refcount_block_cache = qemu_malloc(s->cluster_size);
     refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
     s->refcount_table = qemu_malloc(refcount_table_size2);
     if (s->refcount_table_size > 0) {
@@ -81,34 +59,22 @@ int qcow2_refcount_init(BlockDriverState *bs)
 void qcow2_refcount_close(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
-    qemu_free(s->refcount_block_cache);
     qemu_free(s->refcount_table);
 }
 
 
 static int load_refcount_block(BlockDriverState *bs,
-                               int64_t refcount_block_offset)
+                               int64_t refcount_block_offset,
+                               void **refcount_block)
 {
     BDRVQcowState *s = bs->opaque;
     int ret;
 
-    if (cache_refcount_updates) {
-        ret = write_refcount_block(bs);
-        if (ret < 0) {
-            return ret;
-        }
-    }
-
     BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_LOAD);
-    ret = bdrv_pread(bs->file, refcount_block_offset, s->refcount_block_cache,
-                     s->cluster_size);
-    if (ret < 0) {
-        s->refcount_block_cache_offset = 0;
-        return ret;
-    }
+    ret = qcow2_cache_get(bs, s->refcount_block_cache, refcount_block_offset,
+        refcount_block);
 
-    s->refcount_block_cache_offset = refcount_block_offset;
-    return 0;
+    return ret;
 }
 
 /*
@@ -122,6 +88,8 @@ static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
     int refcount_table_index, block_index;
     int64_t refcount_block_offset;
     int ret;
+    uint16_t *refcount_block;
+    uint16_t refcount;
 
     refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
     if (refcount_table_index >= s->refcount_table_size)
@@ -129,16 +97,24 @@ static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
     refcount_block_offset = s->refcount_table[refcount_table_index];
     if (!refcount_block_offset)
         return 0;
-    if (refcount_block_offset != s->refcount_block_cache_offset) {
-        /* better than nothing: return allocated if read error */
-        ret = load_refcount_block(bs, refcount_block_offset);
-        if (ret < 0) {
-            return ret;
-        }
+
+    ret = qcow2_cache_get(bs, s->refcount_block_cache, refcount_block_offset,
+        (void**) &refcount_block);
+    if (ret < 0) {
+        return ret;
     }
+
     block_index = cluster_index &
         ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
-    return be16_to_cpu(s->refcount_block_cache[block_index]);
+    refcount = be16_to_cpu(refcount_block[block_index]);
+
+    ret = qcow2_cache_put(bs, s->refcount_block_cache,
+        (void**) &refcount_block);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return refcount;
 }
 
 /*
@@ -174,9 +150,10 @@ static int in_same_refcount_block(BDRVQcowState *s, uint64_t offset_a,
  * Loads a refcount block. If it doesn't exist yet, it is allocated first
  * (including growing the refcount table if needed).
  *
- * Returns the offset of the refcount block on success or -errno in error case
+ * Returns 0 on success or -errno in error case
  */
-static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
+static int alloc_refcount_block(BlockDriverState *bs,
+    int64_t cluster_index, uint16_t **refcount_block)
 {
     BDRVQcowState *s = bs->opaque;
     unsigned int refcount_table_index;
@@ -194,13 +171,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
 
         /* If it's already there, we're done */
         if (refcount_block_offset) {
-            if (refcount_block_offset != s->refcount_block_cache_offset) {
-                ret = load_refcount_block(bs, refcount_block_offset);
-                if (ret < 0) {
-                    return ret;
-                }
-            }
-            return refcount_block_offset;
+             return load_refcount_block(bs, refcount_block_offset,
+                 (void**) refcount_block);
         }
     }
 
@@ -226,12 +198,10 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
      *   refcount block into the cache
      */
 
-    if (cache_refcount_updates) {
-        ret = write_refcount_block(bs);
-        if (ret < 0) {
-            return ret;
-        }
-    }
+    *refcount_block = NULL;
+
+    /* We write to the refcount table, so we might depend on L2 tables */
+    qcow2_cache_flush(bs, s->l2_table_cache);
 
     /* Allocate the refcount block itself and mark it as used */
     int64_t new_block = alloc_clusters_noref(bs, s->cluster_size);
@@ -247,13 +217,18 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
 
     if (in_same_refcount_block(s, new_block, cluster_index << s->cluster_bits)) {
         /* Zero the new refcount block before updating it */
-        memset(s->refcount_block_cache, 0, s->cluster_size);
-        s->refcount_block_cache_offset = new_block;
+        ret = qcow2_cache_get_empty(bs, s->refcount_block_cache, new_block,
+            (void**) refcount_block);
+        if (ret < 0) {
+            goto fail_block;
+        }
+
+        memset(*refcount_block, 0, s->cluster_size);
 
         /* The block describes itself, need to update the cache */
         int block_index = (new_block >> s->cluster_bits) &
             ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
-        s->refcount_block_cache[block_index] = cpu_to_be16(1);
+        (*refcount_block)[block_index] = cpu_to_be16(1);
     } else {
         /* Described somewhere else. This can recurse at most twice before we
          * arrive at a block that describes itself. */
@@ -266,14 +241,19 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
 
         /* Initialize the new refcount block only after updating its refcount,
          * update_refcount uses the refcount cache itself */
-        memset(s->refcount_block_cache, 0, s->cluster_size);
-        s->refcount_block_cache_offset = new_block;
+        ret = qcow2_cache_get_empty(bs, s->refcount_block_cache, new_block,
+            (void**) refcount_block);
+        if (ret < 0) {
+            goto fail_block;
+        }
+
+        memset(*refcount_block, 0, s->cluster_size);
     }
 
     /* Now the new refcount block needs to be written to disk */
     BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE);
-    ret = bdrv_pwrite_sync(bs->file, new_block, s->refcount_block_cache,
-        s->cluster_size);
+    qcow2_cache_entry_mark_dirty(s->refcount_block_cache, *refcount_block);
+    ret = qcow2_cache_flush(bs, s->refcount_block_cache);
     if (ret < 0) {
         goto fail_block;
     }
@@ -290,7 +270,12 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
         }
 
         s->refcount_table[refcount_table_index] = new_block;
-        return new_block;
+        return 0;
+    }
+
+    ret = qcow2_cache_put(bs, s->refcount_block_cache, (void**) refcount_block);
+    if (ret < 0) {
+        goto fail_block;
     }
 
     /*
@@ -410,9 +395,9 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t));
     s->free_cluster_index = old_free_cluster_index;
 
-    ret = load_refcount_block(bs, new_block);
+    ret = load_refcount_block(bs, new_block, (void**) refcount_block);
     if (ret < 0) {
-        goto fail_block;
+        return ret;
     }
 
     return new_block;
@@ -420,41 +405,10 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
 fail_table:
     qemu_free(new_table);
 fail_block:
-    s->refcount_block_cache_offset = 0;
-    return ret;
-}
-
-#define REFCOUNTS_PER_SECTOR (512 >> REFCOUNT_SHIFT)
-static int write_refcount_block_entries(BlockDriverState *bs,
-    int64_t refcount_block_offset, int first_index, int last_index)
-{
-    BDRVQcowState *s = bs->opaque;
-    size_t size;
-    int ret;
-
-    if (cache_refcount_updates) {
-        return 0;
-    }
-
-    if (first_index < 0) {
-        return 0;
-    }
-
-    first_index &= ~(REFCOUNTS_PER_SECTOR - 1);
-    last_index = (last_index + REFCOUNTS_PER_SECTOR)
-        & ~(REFCOUNTS_PER_SECTOR - 1);
-
-    size = (last_index - first_index) << REFCOUNT_SHIFT;
-
-    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART);
-    ret = bdrv_pwrite(bs->file,
-        refcount_block_offset + (first_index << REFCOUNT_SHIFT),
-        &s->refcount_block_cache[first_index], size);
-    if (ret < 0) {
-        return ret;
+    if (*refcount_block != NULL) {
+        qcow2_cache_put(bs, s->refcount_block_cache, (void**) refcount_block);
     }
-
-    return 0;
+    return ret;
 }
 
 /* XXX: cache several refcount block clusters ? */
@@ -463,9 +417,8 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
 {
     BDRVQcowState *s = bs->opaque;
     int64_t start, last, cluster_offset;
-    int64_t refcount_block_offset = 0;
-    int64_t table_index = -1, old_table_index;
-    int first_index = -1, last_index = -1;
+    uint16_t *refcount_block = NULL;
+    int64_t old_table_index = -1;
     int ret;
 
 #ifdef DEBUG_ALLOC2
@@ -478,6 +431,11 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
         return 0;
     }
 
+    if (addend < 0) {
+        qcow2_cache_set_dependency(bs, s->refcount_block_cache,
+            s->l2_table_cache);
+    }
+
     start = offset & ~(s->cluster_size - 1);
     last = (offset + length - 1) & ~(s->cluster_size - 1);
     for(cluster_offset = start; cluster_offset <= last;
@@ -485,42 +443,33 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
     {
         int block_index, refcount;
         int64_t cluster_index = cluster_offset >> s->cluster_bits;
-        int64_t new_block;
+        int64_t table_index =
+            cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
 
-        /* Only write refcount block to disk when we are done with it */
-        old_table_index = table_index;
-        table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
-        if ((old_table_index >= 0) && (table_index != old_table_index)) {
+        /* Load the refcount block and allocate it if needed */
+        if (table_index != old_table_index) {
+            if (refcount_block) {
+                ret = qcow2_cache_put(bs, s->refcount_block_cache,
+                    (void**) &refcount_block);
+                if (ret < 0) {
+                    goto fail;
+                }
+            }
 
-            ret = write_refcount_block_entries(bs, refcount_block_offset,
-                first_index, last_index);
+            ret = alloc_refcount_block(bs, cluster_index, &refcount_block);
             if (ret < 0) {
-                return ret;
+                goto fail;
             }
-
-            first_index = -1;
-            last_index = -1;
         }
+        old_table_index = table_index;
 
-        /* Load the refcount block and allocate it if needed */
-        new_block = alloc_refcount_block(bs, cluster_index);
-        if (new_block < 0) {
-            ret = new_block;
-            goto fail;
-        }
-        refcount_block_offset = new_block;
+        qcow2_cache_entry_mark_dirty(s->refcount_block_cache, refcount_block);
 
         /* we can update the count and save it */
         block_index = cluster_index &
             ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
-        if (first_index == -1 || block_index < first_index) {
-            first_index = block_index;
-        }
-        if (block_index > last_index) {
-            last_index = block_index;
-        }
 
-        refcount = be16_to_cpu(s->refcount_block_cache[block_index]);
+        refcount = be16_to_cpu(refcount_block[block_index]);
         refcount += addend;
         if (refcount < 0 || refcount > 0xffff) {
             ret = -EINVAL;
@@ -529,17 +478,16 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
         if (refcount == 0 && cluster_index < s->free_cluster_index) {
             s->free_cluster_index = cluster_index;
         }
-        s->refcount_block_cache[block_index] = cpu_to_be16(refcount);
+        refcount_block[block_index] = cpu_to_be16(refcount);
     }
 
     ret = 0;
 fail:
-
     /* Write last changed block to disk */
-    if (refcount_block_offset != 0) {
+    if (refcount_block) {
         int wret;
-        wret = write_refcount_block_entries(bs, refcount_block_offset,
-            first_index, last_index);
+        wret = qcow2_cache_put(bs, s->refcount_block_cache,
+            (void**) &refcount_block);
         if (wret < 0) {
             return ret < 0 ? ret : wret;
         }
@@ -758,9 +706,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
     uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated;
     int64_t old_offset, old_l2_offset;
     int l2_size, i, j, l1_modified, l2_modified, nb_csectors, refcount;
-
-    qcow2_l2_cache_reset(bs);
-    cache_refcount_updates = 1;
+    int ret;
 
     l2_table = NULL;
     l1_table = NULL;
@@ -784,7 +730,6 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
     }
 
     l2_size = s->l2_size * sizeof(uint64_t);
-    l2_table = qemu_malloc(l2_size);
     l1_modified = 0;
     for(i = 0; i < l1_size; i++) {
         l2_offset = l1_table[i];
@@ -792,8 +737,13 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
             old_l2_offset = l2_offset;
             l2_offset &= ~QCOW_OFLAG_COPIED;
             l2_modified = 0;
-            if (bdrv_pread(bs->file, l2_offset, l2_table, l2_size) != l2_size)
+
+            ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset,
+                (void**) &l2_table);
+            if (ret < 0) {
                 goto fail;
+            }
+
             for(j = 0; j < s->l2_size; j++) {
                 offset = be64_to_cpu(l2_table[j]);
                 if (offset != 0) {
@@ -833,17 +783,23 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                         offset |= QCOW_OFLAG_COPIED;
                     }
                     if (offset != old_offset) {
+                        if (addend > 0) {
+                            qcow2_cache_set_dependency(bs, s->l2_table_cache,
+                                s->refcount_block_cache);
+                        }
                         l2_table[j] = cpu_to_be64(offset);
                         l2_modified = 1;
+                        qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
                     }
                 }
             }
-            if (l2_modified) {
-                if (bdrv_pwrite_sync(bs->file,
-                                l2_offset, l2_table, l2_size) < 0)
-                    goto fail;
+
+            ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+            if (ret < 0) {
+                goto fail;
             }
 
+
             if (addend != 0) {
                 refcount = update_cluster_refcount(bs, l2_offset >> s->cluster_bits, addend);
             } else {
@@ -871,16 +827,14 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
     }
     if (l1_allocated)
         qemu_free(l1_table);
-    qemu_free(l2_table);
-    cache_refcount_updates = 0;
-    write_refcount_block(bs);
     return 0;
  fail:
+    if (l2_table) {
+        qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+    }
+
     if (l1_allocated)
         qemu_free(l1_table);
-    qemu_free(l2_table);
-    cache_refcount_updates = 0;
-    write_refcount_block(bs);
     return -EIO;
 }
 
diff --git a/block/qcow2.c b/block/qcow2.c
index b6b094c..49bf7b9 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -143,6 +143,7 @@ static int qcow2_open(BlockDriverState *bs, int flags)
     int len, i, ret = 0;
     QCowHeader header;
     uint64_t ext_end;
+    bool writethrough;
 
     ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
     if (ret < 0) {
@@ -217,8 +218,13 @@ static int qcow2_open(BlockDriverState *bs, int flags)
             be64_to_cpus(&s->l1_table[i]);
         }
     }
-    /* alloc L2 cache */
-    s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
+
+    /* alloc L2 table/refcount block cache */
+    writethrough = ((flags & BDRV_O_CACHE_MASK) == 0);
+    s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE, writethrough);
+    s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE,
+        writethrough);
+
     s->cluster_cache = qemu_malloc(s->cluster_size);
     /* one more sector for decompressed data alignment */
     s->cluster_data = qemu_malloc(QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size
@@ -270,7 +276,9 @@ static int qcow2_open(BlockDriverState *bs, int flags)
     qcow2_free_snapshots(bs);
     qcow2_refcount_close(bs);
     qemu_free(s->l1_table);
-    qemu_free(s->l2_cache);
+    if (s->l2_table_cache) {
+        qcow2_cache_destroy(bs, s->l2_table_cache);
+    }
     qemu_free(s->cluster_cache);
     qemu_free(s->cluster_data);
     return ret;
@@ -719,7 +727,13 @@ static void qcow2_close(BlockDriverState *bs)
 {
     BDRVQcowState *s = bs->opaque;
     qemu_free(s->l1_table);
-    qemu_free(s->l2_cache);
+
+    qcow2_cache_flush(bs, s->l2_table_cache);
+    qcow2_cache_flush(bs, s->refcount_block_cache);
+
+    qcow2_cache_destroy(bs, s->l2_table_cache);
+    qcow2_cache_destroy(bs, s->refcount_block_cache);
+
     qemu_free(s->cluster_cache);
     qemu_free(s->cluster_data);
     qcow2_refcount_close(bs);
@@ -1179,6 +1193,19 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num,
 
 static int qcow2_flush(BlockDriverState *bs)
 {
+    BDRVQcowState *s = bs->opaque;
+    int ret;
+
+    ret = qcow2_cache_flush(bs, s->l2_table_cache);
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = qcow2_cache_flush(bs, s->refcount_block_cache);
+    if (ret < 0) {
+        return ret;
+    }
+
     return bdrv_flush(bs->file);
 }
 
@@ -1186,6 +1213,19 @@ static BlockDriverAIOCB *qcow2_aio_flush(BlockDriverState *bs,
                                          BlockDriverCompletionFunc *cb,
                                          void *opaque)
 {
+    BDRVQcowState *s = bs->opaque;
+    int ret;
+
+    ret = qcow2_cache_flush(bs, s->l2_table_cache);
+    if (ret < 0) {
+        return NULL;
+    }
+
+    ret = qcow2_cache_flush(bs, s->refcount_block_cache);
+    if (ret < 0) {
+        return NULL;
+    }
+
     return bdrv_aio_flush(bs->file, cb, opaque);
 }
 
diff --git a/block/qcow2.h b/block/qcow2.h
index e5473e1..11cbce3 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -51,6 +51,9 @@
 
 #define L2_CACHE_SIZE 16
 
+/* Must be at least 4 to cover all cases of refcount table growth */
+#define REFCOUNT_CACHE_SIZE 4
+
 typedef struct QCowHeader {
     uint32_t magic;
     uint32_t version;
@@ -94,9 +97,10 @@ typedef struct BDRVQcowState {
     uint64_t cluster_offset_mask;
     uint64_t l1_table_offset;
     uint64_t *l1_table;
-    uint64_t *l2_cache;
-    uint64_t l2_cache_offsets[L2_CACHE_SIZE];
-    uint32_t l2_cache_counts[L2_CACHE_SIZE];
+
+    Qcow2Cache* l2_table_cache;
+    Qcow2Cache* refcount_block_cache;
+
     uint8_t *cluster_cache;
     uint8_t *cluster_data;
     uint64_t cluster_cache_offset;
@@ -105,8 +109,6 @@ typedef struct BDRVQcowState {
     uint64_t *refcount_table;
     uint64_t refcount_table_offset;
     uint32_t refcount_table_size;
-    uint64_t refcount_block_cache_offset;
-    uint16_t *refcount_block_cache;
     int64_t free_cluster_index;
     int64_t free_byte_offset;
 
commit cbcc6336ce9e5c048821b136649712e078c4d05f
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Jan 19 10:49:50 2011 +0200

    spice: add chardev (v5)
    
    Adding a chardev backend for spice, where spice determines what
    to do with it based on the name attribute given during chardev creation.
    For usage by spice vdagent in conjunction with a properly named
    virtio-serial device, and future smartcard channel usage.
    
    Example usage:
     qemu -device virtio-serial -chardev spicevmc,name=vdagent,id=vdagent \
     -device virtserialport,chardev=vdagent,name=com.redhat.spice.0
    
    v4->v5:
     * add tracing events
     * fix missing comma
     * fix help string to show debug is optional
    
    v3->v4:
     * updated commit message
    
    v1->v3 changes: (v2 had a wrong commit message)
     * removed spice-qemu-char.h, folded into ui/qemu-spice.h
     * removed dead IOCTL code
     * removed comment
     * removed ifdef CONFIG_SPICE from qemu-config.c and qemu-options.hx help.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index fda366d..13f6b38 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -105,7 +105,7 @@ common-obj-$(CONFIG_BRLAPI) += baum.o
 common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
 common-obj-$(CONFIG_WIN32) += version.o
 
-common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display.o
+common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display.o spice-qemu-char.o
 
 audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
 audio-obj-$(CONFIG_SDL) += sdlaudio.o
diff --git a/qemu-char.c b/qemu-char.c
index edc9ad6..acc7130 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -97,6 +97,7 @@
 #endif
 
 #include "qemu_socket.h"
+#include "ui/qemu-spice.h"
 
 #define READ_BUF_LEN 4096
 
@@ -2495,6 +2496,9 @@ static const struct {
     || defined(__FreeBSD_kernel__)
     { .name = "parport",   .open = qemu_chr_open_pp },
 #endif
+#ifdef CONFIG_SPICE
+    { .name = "spicevmc",     .open = qemu_chr_open_spice },
+#endif
 };
 
 CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
diff --git a/qemu-config.c b/qemu-config.c
index 965fa46..323d3c2 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -146,6 +146,12 @@ static QemuOptsList qemu_chardev_opts = {
         },{
             .name = "signal",
             .type = QEMU_OPT_BOOL,
+        },{
+            .name = "name",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "debug",
+            .type = QEMU_OPT_NUMBER,
         },
         { /* end of list */ }
     },
diff --git a/qemu-options.hx b/qemu-options.hx
index 898561d..939297a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1368,6 +1368,9 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
 #if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
     "-chardev parport,id=id,path=path[,mux=on|off]\n"
 #endif
+#if defined(CONFIG_SPICE)
+    "-chardev spicevmc,id=id,name=name[,debug=debug]\n"
+#endif
     , QEMU_ARCH_ALL
 )
 
@@ -1392,7 +1395,8 @@ Backend is one of:
 @option{stdio},
 @option{braille},
 @option{tty},
- at option{parport}.
+ at option{parport},
+ at option{spicevmc}.
 The specific backend will determine the applicable options.
 
 All devices must have an id, which can be any string up to 127 characters long.
@@ -1568,6 +1572,16 @@ Connect to a local parallel port.
 @option{path} specifies the path to the parallel port device. @option{path} is
 required.
 
+#if defined(CONFIG_SPICE)
+ at item -chardev spicevmc ,id=@var{id} ,debug=@var{debug}, name=@var{name}
+
+ at option{debug} debug level for spicevmc
+
+ at option{name} name of spice channel to connect to
+
+Connect to a spice virtual machine channel, such as vdiport.
+#endif
+
 @end table
 ETEXI
 
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
new file mode 100644
index 0000000..517f337
--- /dev/null
+++ b/spice-qemu-char.c
@@ -0,0 +1,190 @@
+#include "config-host.h"
+#include "trace.h"
+#include "ui/qemu-spice.h"
+#include <spice.h>
+#include <spice-experimental.h>
+
+#include "osdep.h"
+
+#define dprintf(_scd, _level, _fmt, ...)                                \
+    do {                                                                \
+        static unsigned __dprintf_counter = 0;                          \
+        if (_scd->debug >= _level) {                                    \
+            fprintf(stderr, "scd: %3d: " _fmt, ++__dprintf_counter, ## __VA_ARGS__);\
+        }                                                               \
+    } while (0)
+
+#define VMC_MAX_HOST_WRITE    2048
+
+typedef struct SpiceCharDriver {
+    CharDriverState*      chr;
+    SpiceCharDeviceInstance     sin;
+    char                  *subtype;
+    bool                  active;
+    uint8_t               *buffer;
+    uint8_t               *datapos;
+    ssize_t               bufsize, datalen;
+    uint32_t              debug;
+} SpiceCharDriver;
+
+static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
+{
+    SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
+    ssize_t out = 0;
+    ssize_t last_out;
+    uint8_t* p = (uint8_t*)buf;
+
+    while (len > 0) {
+        last_out = MIN(len, VMC_MAX_HOST_WRITE);
+        qemu_chr_read(scd->chr, p, last_out);
+        if (last_out > 0) {
+            out += last_out;
+            len -= last_out;
+            p += last_out;
+        } else {
+            break;
+        }
+    }
+
+    dprintf(scd, 3, "%s: %lu/%zd\n", __func__, out, len + out);
+    trace_spice_vmc_write(out, len + out);
+    return out;
+}
+
+static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
+{
+    SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
+    int bytes = MIN(len, scd->datalen);
+
+    dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
+    if (bytes > 0) {
+        memcpy(buf, scd->datapos, bytes);
+        scd->datapos += bytes;
+        scd->datalen -= bytes;
+        assert(scd->datalen >= 0);
+        if (scd->datalen == 0) {
+            scd->datapos = 0;
+        }
+    }
+    trace_spice_vmc_read(bytes, len);
+    return bytes;
+}
+
+static SpiceCharDeviceInterface vmc_interface = {
+    .base.type          = SPICE_INTERFACE_CHAR_DEVICE,
+    .base.description   = "spice virtual channel char device",
+    .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
+    .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
+    .write              = vmc_write,
+    .read               = vmc_read,
+};
+
+
+static void vmc_register_interface(SpiceCharDriver *scd)
+{
+    if (scd->active) {
+        return;
+    }
+    dprintf(scd, 1, "%s\n", __func__);
+    scd->sin.base.sif = &vmc_interface.base;
+    qemu_spice_add_interface(&scd->sin.base);
+    scd->active = true;
+    trace_spice_vmc_register_interface(scd);
+}
+
+static void vmc_unregister_interface(SpiceCharDriver *scd)
+{
+    if (!scd->active) {
+        return;
+    }
+    dprintf(scd, 1, "%s\n", __func__);
+    spice_server_remove_interface(&scd->sin.base);
+    scd->active = false;
+    trace_spice_vmc_unregister_interface(scd);
+}
+
+
+static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    SpiceCharDriver *s = chr->opaque;
+
+    dprintf(s, 2, "%s: %d\n", __func__, len);
+    vmc_register_interface(s);
+    assert(s->datalen == 0);
+    if (s->bufsize < len) {
+        s->bufsize = len;
+        s->buffer = qemu_realloc(s->buffer, s->bufsize);
+    }
+    memcpy(s->buffer, buf, len);
+    s->datapos = s->buffer;
+    s->datalen = len;
+    spice_server_char_device_wakeup(&s->sin);
+    return len;
+}
+
+static void spice_chr_close(struct CharDriverState *chr)
+{
+    SpiceCharDriver *s = chr->opaque;
+
+    printf("%s\n", __func__);
+    vmc_unregister_interface(s);
+    qemu_free(s);
+}
+
+static void print_allowed_subtypes(void)
+{
+    const char** psubtype;
+    int i;
+
+    fprintf(stderr, "allowed names: ");
+    for(i=0, psubtype = spice_server_char_device_recognized_subtypes();
+        *psubtype != NULL; ++psubtype, ++i) {
+        if (i == 0) {
+            fprintf(stderr, "%s", *psubtype);
+        } else {
+            fprintf(stderr, ", %s", *psubtype);
+        }
+    }
+    fprintf(stderr, "\n");
+}
+
+CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
+{
+    CharDriverState *chr;
+    SpiceCharDriver *s;
+    const char* name = qemu_opt_get(opts, "name");
+    uint32_t debug = qemu_opt_get_number(opts, "debug", 0);
+    const char** psubtype = spice_server_char_device_recognized_subtypes();
+    const char *subtype = NULL;
+
+    if (name == NULL) {
+        fprintf(stderr, "spice-qemu-char: missing name parameter\n");
+        print_allowed_subtypes();
+        return NULL;
+    }
+    for(;*psubtype != NULL; ++psubtype) {
+        if (strcmp(name, *psubtype) == 0) {
+            subtype = *psubtype;
+            break;
+        }
+    }
+    if (subtype == NULL) {
+        fprintf(stderr, "spice-qemu-char: unsupported name\n");
+        print_allowed_subtypes();
+        return NULL;
+    }
+
+    chr = qemu_mallocz(sizeof(CharDriverState));
+    s = qemu_mallocz(sizeof(SpiceCharDriver));
+    s->chr = chr;
+    s->debug = debug;
+    s->active = false;
+    s->sin.subtype = subtype;
+    chr->opaque = s;
+    chr->chr_write = spice_chr_write;
+    chr->chr_close = spice_chr_close;
+
+    qemu_chr_generic_open(chr);
+
+    return chr;
+}
diff --git a/trace-events b/trace-events
index 19cee6a..ed754f5 100644
--- a/trace-events
+++ b/trace-events
@@ -224,3 +224,9 @@ disable qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t
 disable qed_aio_write_prefill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64""
 disable qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64""
 disable qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu"
+
+# spice-qemu-char.c
+disable spice_vmc_write(ssize_t out, int len) "spice wrottn %lu of requested %zd"
+disable spice_vmc_read(int bytes, int len) "spice read %lu of requested %zd"
+disable spice_vmc_register_interface(void *scd) "spice vmc registered interface %p"
+disable spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p"
diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h
index 05dc50a..916e5dc 100644
--- a/ui/qemu-spice.h
+++ b/ui/qemu-spice.h
@@ -24,6 +24,7 @@
 
 #include "qemu-option.h"
 #include "qemu-config.h"
+#include "qemu-char.h"
 
 extern int using_spice;
 
@@ -41,6 +42,8 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
 void do_info_spice_print(Monitor *mon, const QObject *data);
 void do_info_spice(Monitor *mon, QObject **ret_data);
 
+CharDriverState *qemu_chr_open_spice(QemuOpts *opts);
+
 #else  /* CONFIG_SPICE */
 
 #define using_spice 0
commit 710fc4f5f1cbb6d2cebdc575def9f9dba4b0263f
Author: Jiri Denemark <Jiri.Denemark at gmail.com>
Date:   Mon Jan 24 13:20:29 2011 +0100

    configure: Fix spice probe
    
    Non-existent $pkgconfig instead of $pkg_config was used when configure
    probes for spice availability.
    
    Signed-off-by: Jiri Denemark <jdenemar at redhat.com>

diff --git a/configure b/configure
index 210670c..dc469b2 100755
--- a/configure
+++ b/configure
@@ -2207,9 +2207,9 @@ if test "$spice" != "no" ; then
 #include <spice.h>
 int main(void) { spice_server_new(); return 0; }
 EOF
-  spice_cflags=$($pkgconfig --cflags spice-protocol spice-server 2>/dev/null)
-  spice_libs=$($pkgconfig --libs spice-protocol spice-server 2>/dev/null)
-  if $pkgconfig --atleast-version=0.5.3 spice-server >/dev/null 2>&1 && \
+  spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null)
+  spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null)
+  if $pkg_config --atleast-version=0.5.3 spice-server >/dev/null 2>&1 && \
      compile_prog "$spice_cflags" "$spice_libs" ; then
     spice="yes"
     libs_softmmu="$libs_softmmu $spice_libs"
commit 17268d54be2e15b0d8ccfc4102bc48c84299b027
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Jan 21 10:32:03 2011 +0100

    qxl: locking fix
    
    One spice worker call lacks the unlock/relock calls,
    which may lead to deadlocks, add them.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index dcea65d..fe4212b 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -866,7 +866,9 @@ static void qxl_destroy_primary(PCIQXLDevice *d)
     dprint(d, 1, "%s\n", __FUNCTION__);
 
     d->mode = QXL_MODE_UNDEFINED;
+    qemu_mutex_unlock_iothread();
     d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0);
+    qemu_mutex_lock_iothread();
 }
 
 static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
commit b67737a6cf71d1f029a692e5dc2dc26579299b97
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Wed Jan 5 18:05:52 2011 +0100

    spice/qxl: zap spice 0.4 migration compatibility bits
    
    Live migration from and to spice 0.4 qxl devices isn't going to work.
    Rip out the bits which attempt to support that.  Zap the subsection
    logic which is obsolete now.  Bumb the version to make a clean cut.
    This should obviously go in before 0.14 is released.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hw/qxl.c b/hw/qxl.c
index bd71e58..dcea65d 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1418,43 +1418,10 @@ static int qxl_post_load(void *opaque, int version)
     }
     dprint(d, 1, "%s: done\n", __FUNCTION__);
 
-    /* spice 0.4 compatibility -- accept but ignore */
-    qemu_free(d->worker_data);
-    d->worker_data = NULL;
-    d->worker_data_size = 0;
-
     return 0;
 }
 
-#define QXL_SAVE_VERSION 20
-
-static bool qxl_test_worker_data(void *opaque, int version_id)
-{
-    PCIQXLDevice* d = opaque;
-
-    if (d->revision != 1) {
-        return false;
-    }
-    if (!d->worker_data_size) {
-        return false;
-    }
-    if (!d->worker_data) {
-        d->worker_data = qemu_malloc(d->worker_data_size);
-    }
-    return true;
-}
-
-static bool qxl_test_spice04(void *opaque, int version_id)
-{
-    PCIQXLDevice* d = opaque;
-    return d->revision == 1;
-}
-
-static bool qxl_test_spice06(void *opaque)
-{
-    PCIQXLDevice* d = opaque;
-    return d->revision > 1;
-}
+#define QXL_SAVE_VERSION 21
 
 static VMStateDescription qxl_memslot = {
     .name               = "qxl-memslot",
@@ -1486,24 +1453,6 @@ static VMStateDescription qxl_surface = {
     }
 };
 
-static VMStateDescription qxl_vmstate_spice06 = {
-    .name               = "qxl/spice06",
-    .version_id         = QXL_SAVE_VERSION,
-    .minimum_version_id = QXL_SAVE_VERSION,
-    .fields = (VMStateField []) {
-        VMSTATE_INT32_EQUAL(num_memslots, PCIQXLDevice),
-        VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, 0,
-                             qxl_memslot, struct guest_slots),
-        VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0,
-                       qxl_surface, QXLSurfaceCreate),
-        VMSTATE_INT32_EQUAL(num_surfaces, PCIQXLDevice),
-        VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, 0,
-                      vmstate_info_uint64, uint64_t),
-        VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
-        VMSTATE_END_OF_LIST()
-    },
-};
-
 static VMStateDescription qxl_vmstate = {
     .name               = "qxl",
     .version_id         = QXL_SAVE_VERSION,
@@ -1519,25 +1468,17 @@ static VMStateDescription qxl_vmstate = {
         VMSTATE_UINT32(last_release_offset, PCIQXLDevice),
         VMSTATE_UINT32(mode, PCIQXLDevice),
         VMSTATE_UINT32(ssd.unique, PCIQXLDevice),
-
-        /* spice 0.4 sends/expects them */
-        VMSTATE_VBUFFER_UINT32(vga.vram_ptr, PCIQXLDevice, 0, qxl_test_spice04, 0,
-                               vga.vram_size),
-        VMSTATE_UINT32_TEST(worker_data_size, PCIQXLDevice, qxl_test_spice04),
-        VMSTATE_VBUFFER_UINT32(worker_data, PCIQXLDevice, 0, qxl_test_worker_data, 0,
-                               worker_data_size),
-
+        VMSTATE_INT32_EQUAL(num_memslots, PCIQXLDevice),
+        VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, 0,
+                             qxl_memslot, struct guest_slots),
+        VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0,
+                       qxl_surface, QXLSurfaceCreate),
+        VMSTATE_INT32_EQUAL(num_surfaces, PCIQXLDevice),
+        VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, 0,
+                      vmstate_info_uint64, uint64_t),
+        VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
         VMSTATE_END_OF_LIST()
     },
-    .subsections = (VMStateSubsection[]) {
-        {
-            /* additional spice 0.6 state */
-            .vmsd   = &qxl_vmstate_spice06,
-            .needed = qxl_test_spice06,
-        },{
-            /* end of list */
-        },
-    },
 };
 
 static PCIDeviceInfo qxl_info_primary = {
diff --git a/hw/qxl.h b/hw/qxl.h
index 98e11ce..f6c450d 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -80,10 +80,6 @@ typedef struct PCIQXLDevice {
 
     /* io bar */
     uint32_t           io_base;
-
-    /* spice 0.4 loadvm compatibility */
-    void               *worker_data;
-    uint32_t           worker_data_size;
 } PCIQXLDevice;
 
 #define PANIC_ON(x) if ((x)) {                         \
commit 8d86e2bfe36ae8e03bf2ba0c8206b91e29ad292f
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Thu Jan 6 11:43:17 2011 +0100

    vnc/spice: fix "never" and "now" expire_time

diff --git a/monitor.c b/monitor.c
index 4c92d38..6aa1bb9 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1136,9 +1136,9 @@ static int expire_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
     time_t when;
     int rc;
 
-    if (strcmp(whenstr, "now")) {
+    if (strcmp(whenstr, "now") == 0) {
         when = 0;
-    } else if (strcmp(whenstr, "never")) {
+    } else if (strcmp(whenstr, "never") == 0) {
         when = TIME_MAX;
     } else if (whenstr[0] == '+') {
         when = time(NULL) + strtoull(whenstr+1, NULL, 10);
commit 7ee3bf03984ada1ac7c7a4f27d8583a5718adadb
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Dec 13 21:30:37 2010 +0100

    spice: MAINTAINERS update

diff --git a/MAINTAINERS b/MAINTAINERS
index f20d390..ab48380 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -383,6 +383,14 @@ S: Odd Fixes
 F: gdbstub*
 F: gdb-xml/
 
+SPICE
+M: Gerd Hoffmann <kraxel at redhat.com>
+S: Supported
+F: ui/qemu-spice.h
+F: ui/spice-*.c
+F: audio/spiceaudio.c
+F: hw/qxl*
+
 Graphics
 M: Anthony Liguori <aliguori at us.ibm.com>
 S: Maintained
commit e866e23959b45325414ac84a21f31dea79867ee6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Fri Apr 23 13:28:21 2010 +0200

    spice/vnc: client migration.
    
    Handle spice client migration, i.e. inform a spice client connected
    about the new host and connection parameters, so it can move over the
    connection automatically.
    
    The monitor command has a not-yet used protocol argument simliar to
    set_password and expire_password commands.  This allows to add a simliar
    feature to vnc in the future.  Daniel Berrange plans to work on this.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 1cea572..4906d89 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -815,6 +815,23 @@ ETEXI
     },
 
 STEXI
+ at item client_migrate_info @var{protocol} @var{hostname} @var{port} @var{tls-port} @var{cert-subject}
+ at findex client_migrate_info
+Set the spice/vnc connection info for the migration target.  The spice/vnc
+server will ask the spice/vnc client to automatically reconnect using the
+new parameters (if specified) once the vm migration finished successfully.
+ETEXI
+
+    {
+        .name       = "client_migrate_info",
+        .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
+        .params     = "protocol hostname port tls-port cert-subject",
+        .help       = "send migration info to spice/vnc client",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = client_migrate_info,
+    },
+
+STEXI
 @item snapshot_blkdev
 @findex snapshot_blkdev
 Snapshot device, using snapshot file as target if provided
diff --git a/monitor.c b/monitor.c
index d291158..4c92d38 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1173,6 +1173,33 @@ static int expire_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
     return -1;
 }
 
+static int client_migrate_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+    const char *protocol = qdict_get_str(qdict, "protocol");
+    const char *hostname = qdict_get_str(qdict, "hostname");
+    const char *subject  = qdict_get_try_str(qdict, "cert-subject");
+    int port             = qdict_get_try_int(qdict, "port", -1);
+    int tls_port         = qdict_get_try_int(qdict, "tls-port", -1);
+    int ret;
+
+    if (strcmp(protocol, "spice") == 0) {
+        if (!using_spice) {
+            qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
+            return -1;
+        }
+
+        ret = qemu_spice_migrate_info(hostname, port, tls_port, subject);
+        if (ret != 0) {
+            qerror_report(QERR_UNDEFINED_ERROR);
+            return -1;
+        }
+        return 0;
+    }
+
+    qerror_report(QERR_INVALID_PARAMETER, "protocol");
+    return -1;
+}
+
 static int do_screen_dump(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     vga_hw_screen_dump(qdict_get_str(qdict, "filename"));
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 56c4d8b..2ed8f44 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -503,6 +503,41 @@ EQMP
     },
 
 SQMP
+client_migrate_info
+------------------
+
+Set the spice/vnc connection info for the migration target.  The spice/vnc
+server will ask the spice/vnc client to automatically reconnect using the
+new parameters (if specified) once the vm migration finished successfully.
+
+Arguments:
+
+- "protocol":     protocol: "spice" or "vnc" (json-string)
+- "hostname":     migration target hostname (json-string)
+- "port":         spice/vnc tcp port for plaintext channels (json-int, optional)
+- "tls-port":     spice tcp port for tls-secured channels (json-int, optional)
+- "cert-subject": server certificate subject (json-string, optional)
+
+Example:
+
+-> { "execute": "client_migrate_info",
+     "arguments": { "protocol": "spice",
+                    "hostname": "virt42.lab.kraxel.org",
+                    "port": 1234 } }
+<- { "return": {} }
+
+EQMP
+
+    {
+        .name       = "client_migrate_info",
+        .args_type  = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
+        .params     = "protocol hostname port tls-port cert-subject",
+        .help       = "send migration info to spice/vnc client",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = client_migrate_info,
+    },
+
+SQMP
 migrate_set_speed
 -----------------
 
diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h
index 48239c3..05dc50a 100644
--- a/ui/qemu-spice.h
+++ b/ui/qemu-spice.h
@@ -35,6 +35,8 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin);
 int qemu_spice_set_passwd(const char *passwd,
                           bool fail_if_connected, bool disconnect_if_connected);
 int qemu_spice_set_pw_expire(time_t expires);
+int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
+                            const char *subject);
 
 void do_info_spice_print(Monitor *mon, const QObject *data);
 void do_info_spice(Monitor *mon, QObject **ret_data);
@@ -44,6 +46,8 @@ void do_info_spice(Monitor *mon, QObject **ret_data);
 #define using_spice 0
 #define qemu_spice_set_passwd(_p, _f1, _f2) (-1)
 #define qemu_spice_set_pw_expire(_e) (-1)
+static inline int qemu_spice_migrate_info(const char *h, int p, int t, const char *s)
+{ return -1; }
 
 #endif /* CONFIG_SPICE */
 
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 27a1ced..1aa1a5e 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -30,11 +30,15 @@
 #include "qbool.h"
 #include "qstring.h"
 #include "qjson.h"
+#include "notify.h"
+#include "migration.h"
 #include "monitor.h"
+#include "hw/hw.h"
 
 /* core bits */
 
 static SpiceServer *spice_server;
+static Notifier migration_state;
 static const char *auth = "spice";
 static char *auth_passwd;
 static time_t auth_expires = TIME_MAX;
@@ -416,6 +420,24 @@ void do_info_spice(Monitor *mon, QObject **ret_data)
     *ret_data = QOBJECT(server);
 }
 
+static void migration_state_notifier(Notifier *notifier)
+{
+    int state = get_migration_state();
+
+    if (state == MIG_STATE_COMPLETED) {
+#if SPICE_SERVER_VERSION >= 0x000701 /* 0.7.1 */
+        spice_server_migrate_switch(spice_server);
+#endif
+    }
+}
+
+int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
+                            const char *subject)
+{
+    return spice_server_migrate_info(spice_server, hostname,
+                                     port, tls_port, subject);
+}
+
 static int add_channel(const char *name, const char *value, void *opaque)
 {
     int security = 0;
@@ -573,6 +595,9 @@ void qemu_spice_init(void)
     spice_server_init(spice_server, &core_interface);
     using_spice = 1;
 
+    migration_state.notify = migration_state_notifier;
+    add_migration_state_change_notifier(&migration_state);
+
     qemu_spice_input_init();
     qemu_spice_audio_init();
 
commit 99a0db9b8dd72ea20a2d4cd99fe91b08903ae857
Author: Gerd Hoffmann <kraxel at redhat.com>
Date:   Mon Dec 13 17:30:12 2010 +0100

    add migration state change notifiers
    
    This patch adds functions to register and unregister notifiers for
    migration state changes and a function to query the migration state.
    The notifier is called on every state change.  Once after establishing a
    new migration object (which is in active state then) and once when the
    state changes from active to completed, canceled or error.
    
    Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>

diff --git a/migration.c b/migration.c
index d593b1d..3612572 100644
--- a/migration.c
+++ b/migration.c
@@ -36,6 +36,9 @@ static int64_t max_throttle = (32 << 20);
 
 static MigrationState *current_migration;
 
+static NotifierList migration_state_notifiers =
+    NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
+
 int qemu_start_incoming_migration(const char *uri)
 {
     const char *p;
@@ -121,6 +124,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
     }
 
     current_migration = s;
+    notifier_list_notify(&migration_state_notifiers);
     return 0;
 }
 
@@ -272,6 +276,7 @@ void migrate_fd_error(FdMigrationState *s)
 {
     DPRINTF("setting error state\n");
     s->state = MIG_STATE_ERROR;
+    notifier_list_notify(&migration_state_notifiers);
     migrate_fd_cleanup(s);
 }
 
@@ -329,6 +334,7 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
             monitor_resume(s->mon);
         }
         s->state = MIG_STATE_ERROR;
+        notifier_list_notify(&migration_state_notifiers);
     }
 
     return ret;
@@ -389,6 +395,7 @@ void migrate_fd_put_ready(void *opaque)
             state = MIG_STATE_ERROR;
         }
         s->state = state;
+        notifier_list_notify(&migration_state_notifiers);
     }
 }
 
@@ -408,6 +415,7 @@ void migrate_fd_cancel(MigrationState *mig_state)
     DPRINTF("cancelling migration\n");
 
     s->state = MIG_STATE_CANCELLED;
+    notifier_list_notify(&migration_state_notifiers);
     qemu_savevm_state_cancel(s->mon, s->file);
 
     migrate_fd_cleanup(s);
@@ -421,6 +429,7 @@ void migrate_fd_release(MigrationState *mig_state)
    
     if (s->state == MIG_STATE_ACTIVE) {
         s->state = MIG_STATE_CANCELLED;
+        notifier_list_notify(&migration_state_notifiers);
         migrate_fd_cleanup(s);
     }
     qemu_free(s);
@@ -452,3 +461,22 @@ int migrate_fd_close(void *opaque)
     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
     return s->close(s);
 }
+
+void add_migration_state_change_notifier(Notifier *notify)
+{
+    notifier_list_add(&migration_state_notifiers, notify);
+}
+
+void remove_migration_state_change_notifier(Notifier *notify)
+{
+    notifier_list_remove(&migration_state_notifiers, notify);
+}
+
+int get_migration_state(void)
+{
+    if (current_migration) {
+        return migrate_fd_get_status(current_migration);
+    } else {
+        return MIG_STATE_ERROR;
+    }
+}
diff --git a/migration.h b/migration.h
index d13ed4f..2170792 100644
--- a/migration.h
+++ b/migration.h
@@ -16,6 +16,7 @@
 
 #include "qdict.h"
 #include "qemu-common.h"
+#include "notify.h"
 
 #define MIG_STATE_ERROR		-1
 #define MIG_STATE_COMPLETED	0
@@ -134,4 +135,8 @@ static inline FdMigrationState *migrate_to_fms(MigrationState *mig_state)
     return container_of(mig_state, FdMigrationState, mig_state);
 }
 
+void add_migration_state_change_notifier(Notifier *notify);
+void remove_migration_state_change_notifier(Notifier *notify);
+int get_migration_state(void);
+
 #endif
commit be7052c2a8f667f1dc42b06afcebb964ee0b03ff
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date:   Mon Jan 24 19:00:47 2011 +0900

    pci: memory leak of PCIDevice::rom_file
    
    PCIDevice::rom_file is leaked.
    PCIDevice::rom_file is allocated in pci_qdev_init(), but not freed anywhere.
    free it in qemu_unregister_device().
    
    Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
    Signed-off-by: Michael S. Tsirkin <mst at redhat.com>

diff --git a/hw/pci.c b/hw/pci.c
index b8f5385..044c4bd 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -833,6 +833,7 @@ static int pci_unregister_device(DeviceState *dev)
 
     pci_unregister_io_regions(pci_dev);
     pci_del_option_rom(pci_dev);
+    qemu_free(pci_dev->romfile);
     do_pci_unregister_device(pci_dev);
     return 0;
 }
commit 493810940bfaad0fd5dd9bfb79cdc89519f89588
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Jan 10 17:15:10 2011 +0100

    qcow2: Add QcowCache
    
    This adds some new cache functions to qcow2 which can be used for caching
    refcount blocks and L2 tables. When used with cache=writethrough they work
    like the old caching code which is spread all over qcow2, so for this case we
    have merely a cleanup.
    
    The interesting case is with writeback caching (this includes cache=none) where
    data isn't written to disk immediately but only kept in cache initially. This
    leads to some form of metadata write batching which avoids the current "write
    to refcount block, flush, write to L2 table" pattern for each single request
    when a lot of cluster allocations happen. Instead, cache entries are only
    written out if its required to maintain the right order. In the pure cluster
    allocation case this means that all metadata updates for requests are done in
    memory initially and on sync, first the refcount blocks are written to disk,
    then fsync, then L2 tables.
    
    This improves performance of scenarios with lots of cluster allocations
    noticably (e.g. installation or after taking a snapshot).
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/Makefile.objs b/Makefile.objs
index fda366d..93406ff 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -19,7 +19,7 @@ block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 
 block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
-block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o
+block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
 block-nested-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
 block-nested-y += qed-check.o
 block-nested-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
new file mode 100644
index 0000000..f7c4e2a
--- /dev/null
+++ b/block/qcow2-cache.c
@@ -0,0 +1,290 @@
+/*
+ * L2/refcount table cache for the QCOW2 format
+ *
+ * Copyright (c) 2010 Kevin Wolf <kwolf at redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "block_int.h"
+#include "qemu-common.h"
+#include "qcow2.h"
+
+typedef struct Qcow2CachedTable {
+    void*   table;
+    int64_t offset;
+    bool    dirty;
+    int     cache_hits;
+    int     ref;
+} Qcow2CachedTable;
+
+struct Qcow2Cache {
+    int                     size;
+    Qcow2CachedTable*       entries;
+    struct Qcow2Cache*      depends;
+    bool                    writethrough;
+};
+
+Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
+    bool writethrough)
+{
+    BDRVQcowState *s = bs->opaque;
+    Qcow2Cache *c;
+    int i;
+
+    c = qemu_mallocz(sizeof(*c));
+    c->size = num_tables;
+    c->entries = qemu_mallocz(sizeof(*c->entries) * num_tables);
+    c->writethrough = writethrough;
+
+    for (i = 0; i < c->size; i++) {
+        c->entries[i].table = qemu_blockalign(bs, s->cluster_size);
+    }
+
+    return c;
+}
+
+int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c)
+{
+    int i;
+
+    for (i = 0; i < c->size; i++) {
+        assert(c->entries[i].ref == 0);
+        qemu_vfree(c->entries[i].table);
+    }
+
+    qemu_free(c->entries);
+    qemu_free(c);
+
+    return 0;
+}
+
+static int qcow2_cache_flush_dependency(BlockDriverState *bs, Qcow2Cache *c)
+{
+    int ret;
+
+    ret = qcow2_cache_flush(bs, c->depends);
+    if (ret < 0) {
+        return ret;
+    }
+
+    c->depends = NULL;
+    return 0;
+}
+
+static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
+{
+    BDRVQcowState *s = bs->opaque;
+    int ret;
+
+    if (!c->entries[i].dirty || !c->entries[i].offset) {
+        return 0;
+    }
+
+    if (c->depends) {
+        ret = qcow2_cache_flush_dependency(bs, c);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    ret = bdrv_pwrite(bs->file, c->entries[i].offset, c->entries[i].table,
+        s->cluster_size);
+    if (ret < 0) {
+        return ret;
+    }
+
+    c->entries[i].dirty = false;
+
+    return 0;
+}
+
+int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c)
+{
+    int result = 0;
+    int ret;
+    int i;
+
+    for (i = 0; i < c->size; i++) {
+        ret = qcow2_cache_entry_flush(bs, c, i);
+        if (ret < 0 && result != -ENOSPC) {
+            result = ret;
+        }
+    }
+
+    if (result == 0) {
+        ret = bdrv_flush(bs->file);
+        if (ret < 0) {
+            result = ret;
+        }
+    }
+
+    return result;
+}
+
+int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
+    Qcow2Cache *dependency)
+{
+    int ret;
+
+    if (dependency->depends) {
+        ret = qcow2_cache_flush_dependency(bs, dependency);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    if (c->depends && (c->depends != dependency)) {
+        ret = qcow2_cache_flush_dependency(bs, c);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    c->depends = dependency;
+    return 0;
+}
+
+static int qcow2_cache_find_entry_to_replace(Qcow2Cache *c)
+{
+    int i;
+    int min_count = INT_MAX;
+    int min_index = -1;
+
+
+    for (i = 0; i < c->size; i++) {
+        if (c->entries[i].ref) {
+            continue;
+        }
+
+        if (c->entries[i].cache_hits < min_count) {
+            min_index = i;
+            min_count = c->entries[i].cache_hits;
+        }
+
+        /* Give newer hits priority */
+        /* TODO Check how to optimize the replacement strategy */
+        c->entries[i].cache_hits /= 2;
+    }
+
+    if (min_index == -1) {
+        /* This can't happen in current synchronous code, but leave the check
+         * here as a reminder for whoever starts using AIO with the cache */
+        abort();
+    }
+    return min_index;
+}
+
+static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
+    uint64_t offset, void **table, bool read_from_disk)
+{
+    BDRVQcowState *s = bs->opaque;
+    int i;
+    int ret;
+
+    /* Check if the table is already cached */
+    for (i = 0; i < c->size; i++) {
+        if (c->entries[i].offset == offset) {
+            goto found;
+        }
+    }
+
+    /* If not, write a table back and replace it */
+    i = qcow2_cache_find_entry_to_replace(c);
+    if (i < 0) {
+        return i;
+    }
+
+    ret = qcow2_cache_entry_flush(bs, c, i);
+    if (ret < 0) {
+        return ret;
+    }
+
+    c->entries[i].offset = 0;
+    if (read_from_disk) {
+        ret = bdrv_pread(bs->file, offset, c->entries[i].table, s->cluster_size);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    /* Give the table some hits for the start so that it won't be replaced
+     * immediately. The number 32 is completely arbitrary. */
+    c->entries[i].cache_hits = 32;
+    c->entries[i].offset = offset;
+
+    /* And return the right table */
+found:
+    c->entries[i].cache_hits++;
+    c->entries[i].ref++;
+    *table = c->entries[i].table;
+    return 0;
+}
+
+int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
+    void **table)
+{
+    return qcow2_cache_do_get(bs, c, offset, table, true);
+}
+
+int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
+    void **table)
+{
+    return qcow2_cache_do_get(bs, c, offset, table, false);
+}
+
+int qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table)
+{
+    int i;
+
+    for (i = 0; i < c->size; i++) {
+        if (c->entries[i].table == *table) {
+            goto found;
+        }
+    }
+    return -ENOENT;
+
+found:
+    c->entries[i].ref--;
+    *table = NULL;
+
+    assert(c->entries[i].ref >= 0);
+
+    if (c->writethrough) {
+        return qcow2_cache_entry_flush(bs, c, i);
+    } else {
+        return 0;
+    }
+}
+
+void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table)
+{
+    int i;
+
+    for (i = 0; i < c->size; i++) {
+        if (c->entries[i].table == table) {
+            goto found;
+        }
+    }
+    abort();
+
+found:
+    c->entries[i].dirty = true;
+}
+
diff --git a/block/qcow2.h b/block/qcow2.h
index 5217bea..e5473e1 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -78,6 +78,9 @@ typedef struct QCowSnapshot {
     uint64_t vm_clock_nsec;
 } QCowSnapshot;
 
+struct Qcow2Cache;
+typedef struct Qcow2Cache Qcow2Cache;
+
 typedef struct BDRVQcowState {
     int cluster_bits;
     int cluster_size;
@@ -215,4 +218,20 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs, const char *snapshot_name);
 void qcow2_free_snapshots(BlockDriverState *bs);
 int qcow2_read_snapshots(BlockDriverState *bs);
 
+/* qcow2-cache.c functions */
+Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
+    bool writethrough);
+int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c);
+
+void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
+int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
+int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
+    Qcow2Cache *dependency);
+
+int qcow2_cache_get(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
+    void **table);
+int qcow2_cache_get_empty(BlockDriverState *bs, Qcow2Cache *c, uint64_t offset,
+    void **table);
+int qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c, void **table);
+
 #endif
commit c641483fbe0aa08cd7c0580d019dc2d5a7e71138
Author: Christoph Hellwig <hch at lst.de>
Date:   Mon Dec 20 13:46:09 2010 +0100

    ide: kill ide_dma_submit_check
    
    Merge ide_dma_submit_check into it's only caller.  Also use tail recursion
    using a goto instead of a real recursion - this avoid overflowing the
    stack in the pathological situation of an recurring error that is ignored.
    We'll still be busy looping in ide_dma_cb, but at least won't eat up
    all stack space after this.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 12b9c53..e698c13 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -321,14 +321,6 @@ static inline void ide_abort_command(IDEState *s)
     s->error = ABRT_ERR;
 }
 
-static inline void ide_dma_submit_check(IDEState *s,
-          BlockDriverCompletionFunc *dma_cb)
-{
-    if (s->bus->dma->aiocb)
-	return;
-    dma_cb(s, -1);
-}
-
 /* prepare data transfer and tell what to do after */
 static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
                                EndTransferFunc *end_transfer_func)
@@ -493,6 +485,7 @@ void ide_dma_cb(void *opaque, int ret)
     int n;
     int64_t sector_num;
 
+handle_rw_error:
     if (ret < 0) {
         int op = BM_STATUS_DMA_RETRY;
 
@@ -538,7 +531,11 @@ void ide_dma_cb(void *opaque, int ret)
         s->bus->dma->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
                                             ide_dma_cb, s);
     }
-    ide_dma_submit_check(s, ide_dma_cb);
+
+    if (!s->bus->dma->aiocb) {
+        ret = -1;
+        goto handle_rw_error;
+    }
     return;
 
 eot:
commit 596bb44dead047249c11df24b0e1ffaa514f4909
Author: Christoph Hellwig <hch at lst.de>
Date:   Mon Dec 20 13:45:58 2010 +0100

    ide: also reset io_buffer_index for writes
    
    Currenly the code only resets the io_buffer_index field for reads,
    but the code seems to expect this for all types of I/O.  I guess
    we simply don't hit large enough transfers that would require this
    often enough.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index e93dd46..12b9c53 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -521,8 +521,7 @@ void ide_dma_cb(void *opaque, int ret)
 
     /* launch next transfer */
     n = s->nsector;
-    if (s->is_read)
-        s->io_buffer_index = 0;
+    s->io_buffer_index = 0;
     s->io_buffer_size = n * 512;
     if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->is_read) == 0)
         goto eot;
commit cd369c4634e58a99fb82f076e6117bfdf0012b8e
Author: Christoph Hellwig <hch at lst.de>
Date:   Mon Dec 20 13:45:48 2010 +0100

    ide: factor dma handling helpers
    
    Factor the DMA I/O path that is duplicated between read and write
    commands, into common helpers using the s->is_read flag added for
    the macio ATA controller.
    
    Signed-off-by: Christoph Hellwig <hch at lst.de>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 9496e99..e93dd46 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -487,16 +487,18 @@ static int ide_handle_rw_error(IDEState *s, int error, int op)
     return 1;
 }
 
-void ide_read_dma_cb(void *opaque, int ret)
+void ide_dma_cb(void *opaque, int ret)
 {
     IDEState *s = opaque;
     int n;
     int64_t sector_num;
 
     if (ret < 0) {
-        if (ide_handle_rw_error(s, -ret,
-            BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ))
-        {
+        int op = BM_STATUS_DMA_RETRY;
+
+        if (s->is_read)
+            op |= BM_STATUS_RETRY_READ;
+        if (ide_handle_rw_error(s, -ret, op)) {
             return;
         }
     }
@@ -504,7 +506,7 @@ void ide_read_dma_cb(void *opaque, int ret)
     n = s->io_buffer_size >> 9;
     sector_num = ide_get_sector(s);
     if (n > 0) {
-        dma_buf_commit(s, 1);
+        dma_buf_commit(s, s->is_read);
         sector_num += n;
         ide_set_sector(s, sector_num);
         s->nsector -= n;
@@ -514,32 +516,44 @@ void ide_read_dma_cb(void *opaque, int ret)
     if (s->nsector == 0) {
         s->status = READY_STAT | SEEK_STAT;
         ide_set_irq(s->bus);
-    eot:
-        s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT);
-        ide_set_inactive(s);
-        return;
+        goto eot;
     }
 
     /* launch next transfer */
     n = s->nsector;
-    s->io_buffer_index = 0;
+    if (s->is_read)
+        s->io_buffer_index = 0;
     s->io_buffer_size = n * 512;
-    if (s->bus->dma->ops->prepare_buf(s->bus->dma, 1) == 0)
+    if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->is_read) == 0)
         goto eot;
+
 #ifdef DEBUG_AIO
-    printf("aio_read: sector_num=%" PRId64 " n=%d\n", sector_num, n);
+    printf("ide_dma_cb: sector_num=%" PRId64 " n=%d, is_read=%d\n",
+           sector_num, n, s->is_read);
 #endif
-    s->bus->dma->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num, ide_read_dma_cb, s);
-    ide_dma_submit_check(s, ide_read_dma_cb);
+
+    if (s->is_read) {
+        s->bus->dma->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
+                                           ide_dma_cb, s);
+    } else {
+        s->bus->dma->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
+                                            ide_dma_cb, s);
+    }
+    ide_dma_submit_check(s, ide_dma_cb);
+    return;
+
+eot:
+   s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT);
+   ide_set_inactive(s);
 }
 
-static void ide_sector_read_dma(IDEState *s)
+static void ide_sector_start_dma(IDEState *s, int is_read)
 {
     s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
     s->io_buffer_index = 0;
     s->io_buffer_size = 0;
-    s->is_read = 1;
-    s->bus->dma->ops->start_dma(s->bus->dma, s, ide_read_dma_cb);
+    s->is_read = is_read;
+    s->bus->dma->ops->start_dma(s->bus->dma, s, ide_dma_cb);
 }
 
 static void ide_sector_write_timer_cb(void *opaque)
@@ -594,57 +608,6 @@ void ide_sector_write(IDEState *s)
     }
 }
 
-void ide_write_dma_cb(void *opaque, int ret)
-{
-    IDEState *s = opaque;
-    int n;
-    int64_t sector_num;
-
-    if (ret < 0) {
-        if (ide_handle_rw_error(s, -ret,  BM_STATUS_DMA_RETRY))
-            return;
-    }
-
-    n = s->io_buffer_size >> 9;
-    sector_num = ide_get_sector(s);
-    if (n > 0) {
-        dma_buf_commit(s, 0);
-        sector_num += n;
-        ide_set_sector(s, sector_num);
-        s->nsector -= n;
-    }
-
-    /* end of transfer ? */
-    if (s->nsector == 0) {
-        s->status = READY_STAT | SEEK_STAT;
-        ide_set_irq(s->bus);
-    eot:
-        s->bus->dma->ops->add_status(s->bus->dma, BM_STATUS_INT);
-        ide_set_inactive(s);
-        return;
-    }
-
-    n = s->nsector;
-    s->io_buffer_size = n * 512;
-    /* launch next transfer */
-    if (s->bus->dma->ops->prepare_buf(s->bus->dma, 0) == 0)
-        goto eot;
-#ifdef DEBUG_AIO
-    printf("aio_write: sector_num=%" PRId64 " n=%d\n", sector_num, n);
-#endif
-    s->bus->dma->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num, ide_write_dma_cb, s);
-    ide_dma_submit_check(s, ide_write_dma_cb);
-}
-
-static void ide_sector_write_dma(IDEState *s)
-{
-    s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
-    s->io_buffer_index = 0;
-    s->io_buffer_size = 0;
-    s->is_read = 0;
-    s->bus->dma->ops->start_dma(s->bus->dma, s, ide_write_dma_cb);
-}
-
 void ide_atapi_cmd_ok(IDEState *s)
 {
     s->error = 0;
@@ -1858,7 +1821,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
         if (!s->bs)
             goto abort_cmd;
 	ide_cmd_lba48_transform(s, lba48);
-        ide_sector_read_dma(s);
+        ide_sector_start_dma(s, 1);
         break;
 	case WIN_WRITEDMA_EXT:
 	lba48 = 1;
@@ -1867,7 +1830,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
         if (!s->bs)
             goto abort_cmd;
 	ide_cmd_lba48_transform(s, lba48);
-        ide_sector_write_dma(s);
+        ide_sector_start_dma(s, 0);
         s->media_changed = 1;
         break;
     case WIN_READ_NATIVE_MAX_EXT:
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 697c3b4..d533fb6 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -439,7 +439,6 @@ struct IDEState {
     uint32_t mdata_size;
     uint8_t *mdata_storage;
     int media_changed;
-    /* for pmac */
     int is_read;
     /* SMART */
     uint8_t smart_enabled;
@@ -560,8 +559,7 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
 void ide_init_ioport(IDEBus *bus, int iobase, int iobase2);
 
 void ide_exec_cmd(IDEBus *bus, uint32_t val);
-void ide_read_dma_cb(void *opaque, int ret);
-void ide_write_dma_cb(void *opaque, int ret);
+void ide_dma_cb(void *opaque, int ret);
 void ide_sector_write(IDEState *s);
 void ide_sector_read(IDEState *s);
 void ide_flush_cache(IDEState *s);
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 510b2de..987caff 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -178,14 +178,9 @@ static void bmdma_restart_dma(BMDMAState *bm, int is_read)
     s->io_buffer_index = 0;
     s->io_buffer_size = 0;
     s->nsector = bm->nsector;
+    s->is_read = is_read;
     bm->cur_addr = bm->addr;
-
-    if (is_read) {
-        bm->dma_cb = ide_read_dma_cb;
-    } else {
-        bm->dma_cb = ide_write_dma_cb;
-    }
-
+    bm->dma_cb = ide_dma_cb;
     bmdma_start_dma(&bm->dma, s, bm->dma_cb);
 }
 
commit 8b6b2afcf85dd5ff33075e93a2e30fbea34c5a55
Author: Pierre Riteau <Pierre.Riteau at irisa.fr>
Date:   Wed Jan 12 14:41:00 2011 +0100

    Avoid divide by zero when there is no block device to migrate
    
    When block migration is requested and no read-write block device is
    present, a divide by zero exception is triggered because
    total_sector_sum equals zero.
    
    Signed-off-by: Pierre Riteau <Pierre.Riteau at irisa.fr>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block-migration.c b/block-migration.c
index 1475325..60b9fc0 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -350,7 +350,12 @@ static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f)
         }
     }
 
-    progress = completed_sector_sum * 100 / block_mig_state.total_sector_sum;
+    if (block_mig_state.total_sector_sum != 0) {
+        progress = completed_sector_sum * 100 /
+                   block_mig_state.total_sector_sum;
+    } else {
+        progress = 100;
+    }
     if (progress != block_mig_state.prev_progress) {
         block_mig_state.prev_progress = progress;
         qemu_put_be64(f, (progress << BDRV_SECTOR_BITS)
commit 70b4f4bb05ff5e6812c6593eeefbd19bd61b517d
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Wed Jan 5 11:41:02 2011 +0100

    Make strtosz() return int64_t instead of ssize_t
    
    strtosz() needs to return a 64 bit type even on 32 bit
    architectures. Otherwise qemu-img will fail to create disk
    images >= 2GB
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/cutils.c b/cutils.c
index 7984bc1..4d2e27c 100644
--- a/cutils.c
+++ b/cutils.c
@@ -291,9 +291,9 @@ int fcntl_setfl(int fd, int flag)
  * value must be terminated by whitespace, ',' or '\0'. Return -1 on
  * error.
  */
-ssize_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
+int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
 {
-    ssize_t retval = -1;
+    int64_t retval = -1;
     char *endptr, c, d;
     int mul_required = 0;
     double val, mul, integral, fraction;
@@ -365,7 +365,7 @@ ssize_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
             goto fail;
         }
     }
-    if ((val * mul >= ~(size_t)0) || val < 0) {
+    if ((val * mul >= INT64_MAX) || val < 0) {
         goto fail;
     }
     retval = val * mul;
@@ -378,7 +378,7 @@ fail:
     return retval;
 }
 
-ssize_t strtosz(const char *nptr, char **end)
+int64_t strtosz(const char *nptr, char **end)
 {
     return strtosz_suffix(nptr, end, STRTOSZ_DEFSUFFIX_MB);
 }
diff --git a/monitor.c b/monitor.c
index d291158..0cda3da 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4162,7 +4162,7 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
             break;
         case 'o':
             {
-                ssize_t val;
+                int64_t val;
                 char *end;
 
                 while (qemu_isspace(*p)) {
diff --git a/qemu-common.h b/qemu-common.h
index c766b99..c351131 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -158,8 +158,8 @@ int fcntl_setfl(int fd, int flag);
 #define STRTOSZ_DEFSUFFIX_MB	'M'
 #define STRTOSZ_DEFSUFFIX_KB	'K'
 #define STRTOSZ_DEFSUFFIX_B	'B'
-ssize_t strtosz(const char *nptr, char **end);
-ssize_t strtosz_suffix(const char *nptr, char **end, const char default_suffix);
+int64_t strtosz(const char *nptr, char **end);
+int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix);
 
 /* path.c */
 void init_paths(const char *prefix);
diff --git a/qemu-img.c b/qemu-img.c
index 1e65ea8..4a37358 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -320,7 +320,7 @@ static int img_create(int argc, char **argv)
 
     /* Get image size, if specified */
     if (optind < argc) {
-        ssize_t sval;
+        int64_t sval;
         sval = strtosz_suffix(argv[optind++], NULL, STRTOSZ_DEFSUFFIX_B);
         if (sval < 0) {
             error_report("Invalid image size specified! You may use k, M, G or "
diff --git a/vl.c b/vl.c
index 0292184..14255c4 100644
--- a/vl.c
+++ b/vl.c
@@ -804,7 +804,7 @@ static void numa_add(const char *optarg)
         if (get_param_value(option, 128, "mem", optarg) == 0) {
             node_mem[nodenr] = 0;
         } else {
-            ssize_t sval;
+            int64_t sval;
             sval = strtosz(option, NULL);
             if (sval < 0) {
                 fprintf(stderr, "qemu: invalid numa mem size: %s\n", optarg);
@@ -2245,7 +2245,7 @@ int main(int argc, char **argv, char **envp)
                 exit(0);
                 break;
             case QEMU_OPTION_m: {
-                ssize_t value;
+                int64_t value;
 
                 value = strtosz(optarg, NULL);
                 if (value < 0) {
commit c90f1b3297943f2f142d8114bef1092f9ac9acef
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date:   Thu Jan 6 17:02:23 2011 +0100

    do_snapshot_blkdev() error on missing snapshot_file argument
    
    Current code does not support snapshot internally to the running
    image. Error in case no snapshot_file is specified.
    
    Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/blockdev.c b/blockdev.c
index d7add36..662f7a9 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -526,6 +526,12 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
     int ret = 0;
     int flags;
 
+    if (!filename) {
+        qerror_report(QERR_MISSING_PARAMETER, "snapshot_file");
+        ret = -1;
+        goto out;
+    }
+
     bs = bdrv_find(device);
     if (!bs) {
         qerror_report(QERR_DEVICE_NOT_FOUND, device);
commit 710da702beb0dc4aeeab1b9e712cd9473b083a89
Author: Kevin Wolf <kwolf at redhat.com>
Date:   Mon Jan 10 12:33:02 2011 +0100

    qemu-img snapshot: Use writeback caching
    
    None of the other qemu-img subcommands uses writethrough, and there's no reason
    why snapshot should be special.
    
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>
    Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>

diff --git a/qemu-img.c b/qemu-img.c
index afd9ed2..1e65ea8 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1068,7 +1068,7 @@ static int img_snapshot(int argc, char **argv)
     int action = 0;
     qemu_timeval tv;
 
-    bdrv_oflags = BDRV_O_RDWR;
+    bdrv_oflags = BDRV_O_FLAGS | BDRV_O_RDWR;
     /* Parse commandline parameters */
     for(;;) {
         c = getopt(argc, argv, "la:c:d:h");
commit 653df36bbe58e20258610bc74c5940c456b31084
Author: Aurelien Jarno <aurelien at aurel32.net>
Date:   Sat Jan 1 21:50:34 2011 +0100

    qcow2: fix unaligned access
    
    cpu_to_be64w() is called with an obviously non-aligned pointer. Use
    cpu_to_be64wu() instead. It fixes unaligned accesses errors on IA64
    hosts.
    
    Cc: Kevin Wolf <kwolf at redhat.com>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
    Signed-off-by: Kevin Wolf <kwolf at redhat.com>

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 6928c63..c3ef550 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -81,7 +81,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size)
     /* set new table */
     BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ACTIVATE_TABLE);
     cpu_to_be32w((uint32_t*)data, new_l1_size);
-    cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset);
+    cpu_to_be64wu((uint64_t*)(data + 4), new_l1_table_offset);
     ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, l1_size), data,sizeof(data));
     if (ret < 0) {
         goto fail;
commit 0bfe006c5380c5f8a485a55ded3329fbbc224396
Author: Kevin Wolf <mail at kevin-wolf.de>
Date:   Tue Jan 4 14:03:30 2011 +0100

    multiboot: Fix upper memory size in multiboot info
    
    The upper memory size field should exclude the first MB of RAM.
    
    Signed-off-by: Kevin Wolf <mail at kevin-wolf.de>
    Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>

diff --git a/hw/multiboot.c b/hw/multiboot.c
index 7cc3055..0d2bfb4 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -306,7 +306,7 @@ int load_multiboot(void *fw_cfg,
                                 | MULTIBOOT_FLAGS_MODULES
                                 | MULTIBOOT_FLAGS_MMAP);
     stl_p(bootinfo + MBI_MEM_LOWER,   640);
-    stl_p(bootinfo + MBI_MEM_UPPER,   ram_size / 1024);
+    stl_p(bootinfo + MBI_MEM_UPPER,   (ram_size / 1024) - 1024);
     stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8001ffff); /* XXX: use the -boot switch? */
     stl_p(bootinfo + MBI_MMAP_ADDR,   ADDR_E820_MAP);
 
commit 64b85a8f2359ca3a995499afaf3c87d8e036e030
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Jan 23 16:21:20 2011 +0000

    Delete useless 'extern' qualifiers for functions
    
    'extern' qualifier is useless for function declarations. Delete
    them.
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/cache-utils.h b/cache-utils.h
index b45fde4..0b65907 100644
--- a/cache-utils.h
+++ b/cache-utils.h
@@ -9,7 +9,7 @@ struct qemu_cache_conf {
 
 extern struct qemu_cache_conf qemu_cache_conf;
 
-extern void qemu_cache_utils_init(char **envp);
+void qemu_cache_utils_init(char **envp);
 
 /* mildly adjusted code from tcg-dyngen.c */
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
diff --git a/cmd.h b/cmd.h
index cbe9549..b763b19 100644
--- a/cmd.h
+++ b/cmd.h
@@ -38,33 +38,33 @@ typedef struct cmdinfo {
 extern cmdinfo_t	*cmdtab;
 extern int		ncmds;
 
-extern void		help_init(void);
-extern void		quit_init(void);
+void help_init(void);
+void quit_init(void);
 
 typedef int (*argsfunc_t)(int index);
 typedef int (*checkfunc_t)(const cmdinfo_t *ci);
 
-extern void		add_command(const cmdinfo_t *ci);
-extern void		add_user_command(char *optarg);
-extern void		add_args_command(argsfunc_t af);
-extern void		add_check_command(checkfunc_t cf);
+void add_command(const cmdinfo_t *ci);
+void add_user_command(char *optarg);
+void add_args_command(argsfunc_t af);
+void add_check_command(checkfunc_t cf);
 
-extern const cmdinfo_t	*find_command(const char *cmd);
+const cmdinfo_t *find_command(const char *cmd);
 
-extern void		command_loop(void);
-extern int		command_usage(const cmdinfo_t *ci);
-extern int		command(const cmdinfo_t *ci, int argc, char **argv);
+void command_loop(void);
+int command_usage(const cmdinfo_t *ci);
+int command(const cmdinfo_t *ci, int argc, char **argv);
 
 /* from input.h */
-extern char	**breakline(char *input, int *count);
-extern void	doneline(char *input, char **vec);
-extern char	*fetchline(void);
+char **breakline(char *input, int *count);
+void doneline(char *input, char **vec);
+char *fetchline(void);
 
-extern long long cvtnum(char *s);
-extern void	cvtstr(double value, char *str, size_t sz);
+long long cvtnum(char *s);
+void cvtstr(double value, char *str, size_t sz);
 
-extern struct timeval tsub(struct timeval t1, struct timeval t2);
-extern double	tdiv(double value, struct timeval tv);
+struct timeval tsub(struct timeval t1, struct timeval t2);
+double tdiv(double value, struct timeval tv);
 
 enum {
 	DEFAULT_TIME		= 0x0,
@@ -72,7 +72,7 @@ enum {
 	VERBOSE_FIXED_TIME	= 0x2
 };
 
-extern void	timestr(struct timeval *tv, char *str, size_t sz, int flags);
+void timestr(struct timeval *tv, char *str, size_t sz, int flags);
 
 extern char *progname;
 
diff --git a/dis-asm.h b/dis-asm.h
index 356459c..296537a 100644
--- a/dis-asm.h
+++ b/dis-asm.h
@@ -362,48 +362,48 @@ typedef struct disassemble_info {
    target address.  Return number of bytes processed.  */
 typedef int (*disassembler_ftype) (bfd_vma, disassemble_info *);
 
-extern int print_insn_big_mips		(bfd_vma, disassemble_info*);
-extern int print_insn_little_mips	(bfd_vma, disassemble_info*);
-extern int print_insn_i386		(bfd_vma, disassemble_info*);
-extern int print_insn_m68k		(bfd_vma, disassemble_info*);
-extern int print_insn_z8001		(bfd_vma, disassemble_info*);
-extern int print_insn_z8002		(bfd_vma, disassemble_info*);
-extern int print_insn_h8300		(bfd_vma, disassemble_info*);
-extern int print_insn_h8300h		(bfd_vma, disassemble_info*);
-extern int print_insn_h8300s		(bfd_vma, disassemble_info*);
-extern int print_insn_h8500		(bfd_vma, disassemble_info*);
-extern int print_insn_alpha		(bfd_vma, disassemble_info*);
-extern disassembler_ftype arc_get_disassembler (int, int);
-extern int print_insn_arm		(bfd_vma, disassemble_info*);
-extern int print_insn_sparc		(bfd_vma, disassemble_info*);
-extern int print_insn_big_a29k		(bfd_vma, disassemble_info*);
-extern int print_insn_little_a29k	(bfd_vma, disassemble_info*);
-extern int print_insn_i960		(bfd_vma, disassemble_info*);
-extern int print_insn_sh		(bfd_vma, disassemble_info*);
-extern int print_insn_shl		(bfd_vma, disassemble_info*);
-extern int print_insn_hppa		(bfd_vma, disassemble_info*);
-extern int print_insn_m32r		(bfd_vma, disassemble_info*);
-extern int print_insn_m88k		(bfd_vma, disassemble_info*);
-extern int print_insn_mn10200		(bfd_vma, disassemble_info*);
-extern int print_insn_mn10300		(bfd_vma, disassemble_info*);
-extern int print_insn_ns32k		(bfd_vma, disassemble_info*);
-extern int print_insn_big_powerpc	(bfd_vma, disassemble_info*);
-extern int print_insn_little_powerpc	(bfd_vma, disassemble_info*);
-extern int print_insn_rs6000		(bfd_vma, disassemble_info*);
-extern int print_insn_w65		(bfd_vma, disassemble_info*);
-extern int print_insn_d10v		(bfd_vma, disassemble_info*);
-extern int print_insn_v850		(bfd_vma, disassemble_info*);
-extern int print_insn_tic30		(bfd_vma, disassemble_info*);
-extern int print_insn_ppc		(bfd_vma, disassemble_info*);
-extern int print_insn_s390		(bfd_vma, disassemble_info*);
-extern int print_insn_crisv32           (bfd_vma, disassemble_info*);
-extern int print_insn_crisv10           (bfd_vma, disassemble_info*);
-extern int print_insn_microblaze        (bfd_vma, disassemble_info*);
-extern int print_insn_ia64              (bfd_vma, disassemble_info*);
+int print_insn_big_mips         (bfd_vma, disassemble_info*);
+int print_insn_little_mips      (bfd_vma, disassemble_info*);
+int print_insn_i386             (bfd_vma, disassemble_info*);
+int print_insn_m68k             (bfd_vma, disassemble_info*);
+int print_insn_z8001            (bfd_vma, disassemble_info*);
+int print_insn_z8002            (bfd_vma, disassemble_info*);
+int print_insn_h8300            (bfd_vma, disassemble_info*);
+int print_insn_h8300h           (bfd_vma, disassemble_info*);
+int print_insn_h8300s           (bfd_vma, disassemble_info*);
+int print_insn_h8500            (bfd_vma, disassemble_info*);
+int print_insn_alpha            (bfd_vma, disassemble_info*);
+disassembler_ftype arc_get_disassembler (int, int);
+int print_insn_arm              (bfd_vma, disassemble_info*);
+int print_insn_sparc            (bfd_vma, disassemble_info*);
+int print_insn_big_a29k         (bfd_vma, disassemble_info*);
+int print_insn_little_a29k      (bfd_vma, disassemble_info*);
+int print_insn_i960             (bfd_vma, disassemble_info*);
+int print_insn_sh               (bfd_vma, disassemble_info*);
+int print_insn_shl              (bfd_vma, disassemble_info*);
+int print_insn_hppa             (bfd_vma, disassemble_info*);
+int print_insn_m32r             (bfd_vma, disassemble_info*);
+int print_insn_m88k             (bfd_vma, disassemble_info*);
+int print_insn_mn10200          (bfd_vma, disassemble_info*);
+int print_insn_mn10300          (bfd_vma, disassemble_info*);
+int print_insn_ns32k            (bfd_vma, disassemble_info*);
+int print_insn_big_powerpc      (bfd_vma, disassemble_info*);
+int print_insn_little_powerpc   (bfd_vma, disassemble_info*);
+int print_insn_rs6000           (bfd_vma, disassemble_info*);
+int print_insn_w65              (bfd_vma, disassemble_info*);
+int print_insn_d10v             (bfd_vma, disassemble_info*);
+int print_insn_v850             (bfd_vma, disassemble_info*);
+int print_insn_tic30            (bfd_vma, disassemble_info*);
+int print_insn_ppc              (bfd_vma, disassemble_info*);
+int print_insn_s390             (bfd_vma, disassemble_info*);
+int print_insn_crisv32          (bfd_vma, disassemble_info*);
+int print_insn_crisv10          (bfd_vma, disassemble_info*);
+int print_insn_microblaze       (bfd_vma, disassemble_info*);
+int print_insn_ia64             (bfd_vma, disassemble_info*);
 
 #if 0
 /* Fetch the disassembler for a given BFD, if that support is available.  */
-extern disassembler_ftype disassembler	(bfd *);
+disassembler_ftype disassembler(bfd *);
 #endif
 
 
@@ -412,21 +412,20 @@ extern disassembler_ftype disassembler	(bfd *);
 
 /* Here is a function which callers may wish to use for read_memory_func.
    It gets bytes from a buffer.  */
-extern int buffer_read_memory
-  (bfd_vma, bfd_byte *, int, struct disassemble_info *);
+int buffer_read_memory(bfd_vma, bfd_byte *, int, struct disassemble_info *);
 
 /* This function goes with buffer_read_memory.
    It prints a message using info->fprintf_func and info->stream.  */
-extern void perror_memory (int, bfd_vma, struct disassemble_info *);
+void perror_memory(int, bfd_vma, struct disassemble_info *);
 
 
 /* Just print the address in hex.  This is included for completeness even
    though both GDB and objdump provide their own (to print symbolic
    addresses).  */
-extern void generic_print_address (bfd_vma, struct disassemble_info *);
+void generic_print_address(bfd_vma, struct disassemble_info *);
 
 /* Always true.  */
-extern int generic_symbol_at_address (bfd_vma, struct disassemble_info *);
+int generic_symbol_at_address(bfd_vma, struct disassemble_info *);
 
 /* Macro to initialize a disassemble_info struct.  This should be called
    by all applications creating such a struct.  */
diff --git a/envlist.h b/envlist.h
index e76d4a1..b9addcc 100644
--- a/envlist.h
+++ b/envlist.h
@@ -7,13 +7,13 @@ extern "C" {
 
 typedef struct envlist envlist_t;
 
-extern	envlist_t *envlist_create(void);
-extern	void envlist_free(envlist_t *);
-extern	int envlist_setenv(envlist_t *, const char *);
-extern	int envlist_unsetenv(envlist_t *, const char *);
-extern	int envlist_parse_set(envlist_t *, const char *);
-extern	int envlist_parse_unset(envlist_t *, const char *);
-extern	char **envlist_to_environ(const envlist_t *, size_t *);
+envlist_t *envlist_create(void);
+void envlist_free(envlist_t *);
+int envlist_setenv(envlist_t *, const char *);
+int envlist_unsetenv(envlist_t *, const char *);
+int envlist_parse_set(envlist_t *, const char *);
+int envlist_parse_unset(envlist_t *, const char *);
+char **envlist_to_environ(const envlist_t *, size_t *);
 
 #ifdef __cplusplus
 }
diff --git a/exec-all.h b/exec-all.h
index a4b75bd..e3a82bc 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -192,7 +192,7 @@ extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
 #if defined(USE_DIRECT_JUMP)
 
 #if defined(_ARCH_PPC)
-extern void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr);
+void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr);
 #define tb_set_jmp_target1 ppc_tb_set_jmp_target
 #elif defined(__i386__) || defined(__x86_64__)
 static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
index 6c27881..a704043 100644
--- a/fsdev/qemu-fsdev.h
+++ b/fsdev/qemu-fsdev.h
@@ -49,7 +49,7 @@ typedef struct FsTypeListEntry {
     QTAILQ_ENTRY(FsTypeListEntry) next;
 } FsTypeListEntry;
 
-extern int qemu_fsdev_add(QemuOpts *opts);
-extern FsTypeEntry *get_fsdev_fsentry(char *id);
+int qemu_fsdev_add(QemuOpts *opts);
+FsTypeEntry *get_fsdev_fsentry(char *id);
 extern FileOperations local_ops;
 #endif
diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index c7731c2..126e60e 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -57,7 +57,7 @@ typedef struct FsContext
     struct xattr_operations **xops;
 } FsContext;
 
-extern void cred_init(FsCred *);
+void cred_init(FsCred *);
 
 typedef struct FileOperations
 {
diff --git a/hw/hw.h b/hw/hw.h
index 163a683..dd993de 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -799,17 +799,16 @@ extern const VMStateDescription vmstate_i2c_slave;
 #define VMSTATE_END_OF_LIST()                                         \
     {}
 
-extern int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
-                              void *opaque, int version_id);
-extern void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
-                               void *opaque);
-extern int vmstate_register(DeviceState *dev, int instance_id,
-                            const VMStateDescription *vmsd, void *base);
-extern int vmstate_register_with_alias_id(DeviceState *dev,
-                                          int instance_id,
-                                          const VMStateDescription *vmsd,
-                                          void *base, int alias_id,
-                                          int required_for_version);
+int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
+                       void *opaque, int version_id);
+void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
+                        void *opaque);
+int vmstate_register(DeviceState *dev, int instance_id,
+                     const VMStateDescription *vmsd, void *base);
+int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
+                                   const VMStateDescription *vmsd,
+                                   void *base, int alias_id,
+                                   int required_for_version);
 void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
                         void *opaque);
 #endif
diff --git a/hw/mips.h b/hw/mips.h
index 757e8f9..73aa8f8 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -21,7 +21,7 @@ int g364fb_mm_init(target_phys_addr_t vram_base,
 void mipsnet_init(int base, qemu_irq irq, NICInfo *nd);
 
 /* jazz_led.c */
-extern void jazz_led_init(target_phys_addr_t base);
+void jazz_led_init(target_phys_addr_t base);
 
 /* rc4030.c */
 typedef struct rc4030DMAState *rc4030_dma;
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index 669b610..33379a3 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -58,14 +58,12 @@ typedef struct VirtIOS390Bus {
 } VirtIOS390Bus;
 
 
-extern void s390_virtio_device_update_status(VirtIOS390Device *dev);
+void s390_virtio_device_update_status(VirtIOS390Device *dev);
 
-extern VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus);
-extern VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size);
+VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus);
+VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size);
 
-extern VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
-                                                    ram_addr_t mem,
-                                                    int *vq_num);
-extern VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus,
-                                                  ram_addr_t mem);
-extern void s390_virtio_device_sync(VirtIOS390Device *dev);
+VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
+                                             ram_addr_t mem, int *vq_num);
+VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem);
+void s390_virtio_device_sync(VirtIOS390Device *dev);
diff --git a/hw/virtio-9p-xattr.h b/hw/virtio-9p-xattr.h
index a6e31a1..2bbae2d 100644
--- a/hw/virtio-9p-xattr.h
+++ b/hw/virtio-9p-xattr.h
@@ -41,16 +41,15 @@ extern XattrOperations *mapped_xattr_ops[];
 extern XattrOperations *passthrough_xattr_ops[];
 extern XattrOperations *none_xattr_ops[];
 
-extern ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
-                              const char *name, void *value, size_t size);
-extern ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
-                               void *value, size_t vsize);
-extern int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
+ssize_t v9fs_get_xattr(FsContext *ctx, const char *path, const char *name,
+                       void *value, size_t size);
+ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, void *value,
+                        size_t vsize);
+int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
                           void *value, size_t size, int flags);
-extern int v9fs_remove_xattr(FsContext *ctx,
-                             const char *path, const char *name);
-extern ssize_t pt_listxattr(FsContext *ctx, const char *path,
-                            char *name, void *value, size_t size);
+int v9fs_remove_xattr(FsContext *ctx, const char *path, const char *name);
+ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value,
+                     size_t size);
 
 static inline ssize_t pt_getxattr(FsContext *ctx, const char *path,
                                   const char *name, void *value, size_t size)
diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
index 6c23319..2ae4ce7 100644
--- a/hw/virtio-9p.h
+++ b/hw/virtio-9p.h
@@ -495,8 +495,8 @@ typedef struct V9fsReadLinkState
     V9fsString target;
 } V9fsReadLinkState;
 
-extern size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
-                            size_t offset, size_t size, int pack);
+size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
+                      size_t offset, size_t size, int pack);
 
 static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
                         size_t offset, size_t size)
diff --git a/hw/watchdog.h b/hw/watchdog.h
index 8fd32c3..c12a293 100644
--- a/hw/watchdog.h
+++ b/hw/watchdog.h
@@ -35,9 +35,9 @@ struct WatchdogTimerModel {
 typedef struct WatchdogTimerModel WatchdogTimerModel;
 
 /* in hw/watchdog.c */
-extern int select_watchdog(const char *p);
-extern int select_watchdog_action(const char *action);
-extern void watchdog_add_model(WatchdogTimerModel *model);
-extern void watchdog_perform_action(void);
+int select_watchdog(const char *p);
+int select_watchdog_action(const char *action);
+void watchdog_add_model(WatchdogTimerModel *model);
+void watchdog_perform_action(void);
 
 #endif /* QEMU_WATCHDOG_H */
diff --git a/linux-user/arm/nwfpe/fpa11.h b/linux-user/arm/nwfpe/fpa11.h
index 07419e2..f17647b 100644
--- a/linux-user/arm/nwfpe/fpa11.h
+++ b/linux-user/arm/nwfpe/fpa11.h
@@ -89,9 +89,9 @@ typedef struct tagFPA11 {
 
 extern FPA11* qemufpa;
 
-extern void resetFPA11(void);
-extern void SetRoundingMode(const unsigned int);
-extern void SetRoundingPrecision(const unsigned int);
+void resetFPA11(void);
+void SetRoundingMode(const unsigned int);
+void SetRoundingPrecision(const unsigned int);
 
 static inline unsigned int readRegister(unsigned int reg)
 {
diff --git a/linux-user/arm/nwfpe/fpopcode.h b/linux-user/arm/nwfpe/fpopcode.h
index 16fa34a..e7d1009 100644
--- a/linux-user/arm/nwfpe/fpopcode.h
+++ b/linux-user/arm/nwfpe/fpopcode.h
@@ -384,7 +384,7 @@ static inline float32 getSingleConstant(const unsigned int nIndex)
    return float32Constant[nIndex];
 }
 
-extern unsigned int getRegisterCount(const unsigned int opcode);
-extern unsigned int getDestinationSize(const unsigned int opcode);
+unsigned int getRegisterCount(const unsigned int opcode);
+unsigned int getDestinationSize(const unsigned int opcode);
 
 #endif
diff --git a/qemu-common.h b/qemu-common.h
index 63d9943..c766b99 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -90,7 +90,7 @@ typedef int (*fprintf_function)(FILE *f, const char *fmt, ...)
 #ifdef _WIN32
 #define fsync _commit
 #define lseek _lseeki64
-extern int qemu_ftruncate64(int, int64_t);
+int qemu_ftruncate64(int, int64_t);
 #define ftruncate qemu_ftruncate64
 
 static inline char *realpath(const char *path, char *resolved_path)
diff --git a/slirp/slirp.h b/slirp/slirp.h
index dfd977a..954289a 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -238,7 +238,7 @@ void if_start(struct ttys *);
 #endif
 
 #ifndef HAVE_STRERROR
- extern char *strerror(int error);
+ char *strerror(int error);
 #endif
 
 #ifndef HAVE_INDEX
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 8d73fad..e47c372 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -105,9 +105,9 @@ int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw
 #define TARGET_VIRT_ADDR_SPACE_BITS 32
 
 #ifndef CONFIG_USER_ONLY
-extern int s390_virtio_hypercall(CPUState *env);
-extern void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token);
-extern CPUState *s390_cpu_addr2state(uint16_t cpu_addr);
+int s390_virtio_hypercall(CPUState *env);
+void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token);
+CPUState *s390_cpu_addr2state(uint16_t cpu_addr);
 #endif
 
 
diff --git a/tests/cris/sys.h b/tests/cris/sys.h
index d2ed4ce..c5f88e1 100644
--- a/tests/cris/sys.h
+++ b/tests/cris/sys.h
@@ -12,5 +12,5 @@
 
 #define mb() asm volatile ("" : : : "memory")
 
-extern void pass(void);
-extern void _fail(char *reason);
+void pass(void);
+void _fail(char *reason);
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 56c789a..20f91bc 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -852,9 +852,9 @@ typedef struct CPSProcessSerNum
         UInt32                hi;
 } CPSProcessSerNum;
 
-extern OSErr    CPSGetCurrentProcess( CPSProcessSerNum *psn);
-extern OSErr    CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
-extern OSErr    CPSSetFrontProcess( CPSProcessSerNum *psn);
+OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
+OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
+OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
 
 int main (int argc, const char * argv[]) {
 
diff --git a/ui/d3des.h b/ui/d3des.h
index ea3da44..78d546f 100644
--- a/ui/d3des.h
+++ b/ui/d3des.h
@@ -22,25 +22,25 @@
 #define EN0	0	/* MODE == encrypt */
 #define DE1	1	/* MODE == decrypt */
 
-extern void deskey(unsigned char *, int);
+void deskey(unsigned char *, int);
 /*		      hexkey[8]     MODE
  * Sets the internal key register according to the hexadecimal
  * key contained in the 8 bytes of hexkey, according to the DES,
  * for encryption or decryption according to MODE.
  */
 
-extern void usekey(unsigned long *);
+void usekey(unsigned long *);
 /*		    cookedkey[32]
  * Loads the internal key register with the data in cookedkey.
  */
 
-extern void cpkey(unsigned long *);
+void cpkey(unsigned long *);
 /*		   cookedkey[32]
  * Copies the contents of the internal key register into the storage
  * located at &cookedkey[0].
  */
 
-extern void des(unsigned char *, unsigned char *);
+void des(unsigned char *, unsigned char *);
 /*		    from[8]	      to[8]
  * Encrypts/Decrypts (according to the key currently loaded in the
  * internal key register) one block of eight bytes at address 'from'
diff --git a/ui/x_keymap.h b/ui/x_keymap.h
index 2042ce0..afde2e9 100644
--- a/ui/x_keymap.h
+++ b/ui/x_keymap.h
@@ -25,8 +25,8 @@
 #ifndef QEMU_X_KEYMAP_H
 #define QEMU_X_KEYMAP_H
 
-extern uint8_t translate_xfree86_keycode(const int key);
+uint8_t translate_xfree86_keycode(const int key);
 
-extern uint8_t translate_evdev_keycode(const int key);
+uint8_t translate_evdev_keycode(const int key);
 
 #endif
commit ba76a84d2d420ccab7383bb60c61b96491f50b33
Author: Blue Swirl <blauwirbel at gmail.com>
Date:   Sun Jan 23 11:43:25 2011 +0000

    gdbstub-xml: avoid a warning from sparse
    
    Include a header to get the declaration for xml_builtin. This
    avoids a warning from sparse:
      CC    m68k-softmmu/gdbstub-xml.o
    gdbstub-xml.c:244:12: warning: symbol 'xml_builtin' was not declared. Should it be static?
    
    Signed-off-by: Blue Swirl <blauwirbel at gmail.com>

diff --git a/scripts/feature_to_c.sh b/scripts/feature_to_c.sh
index 0994d95..b62da8a 100644
--- a/scripts/feature_to_c.sh
+++ b/scripts/feature_to_c.sh
@@ -36,6 +36,9 @@ for input; do
   arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'`
 
   ${AWK:-awk} 'BEGIN { n = 0
+      printf "#include \"config.h\"\n"
+      printf "#include \"qemu-common.h\"\n"
+      printf "#include \"gdbstub.h\"\n"
       print "static const char '$arrayname'[] = {"
       for (i = 0; i < 255; i++)
         _ord_[sprintf("%c", i)] = i
commit 94a8d39afd8ccfdbf578af04c3385fdb5f545af1
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:17 2011 +0100

    kvm: Consolidate must-have capability checks
    
    Instead of splattering the code with #ifdefs and runtime checks for
    capabilities we cannot work without anyway, provide central test
    infrastructure for verifying their availability both at build and
    runtime.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/configure b/configure
index 9a02d1f..4673bf0 100755
--- a/configure
+++ b/configure
@@ -1662,18 +1662,31 @@ if test "$kvm" != "no" ; then
 #if !defined(KVM_API_VERSION) || KVM_API_VERSION < 12 || KVM_API_VERSION > 12
 #error Invalid KVM version
 #endif
-#if !defined(KVM_CAP_USER_MEMORY)
-#error Missing KVM capability KVM_CAP_USER_MEMORY
-#endif
-#if !defined(KVM_CAP_SET_TSS_ADDR)
-#error Missing KVM capability KVM_CAP_SET_TSS_ADDR
-#endif
-#if !defined(KVM_CAP_DESTROY_MEMORY_REGION_WORKS)
-#error Missing KVM capability KVM_CAP_DESTROY_MEMORY_REGION_WORKS
-#endif
-#if !defined(KVM_CAP_USER_NMI)
-#error Missing KVM capability KVM_CAP_USER_NMI
+EOF
+    must_have_caps="KVM_CAP_USER_MEMORY \
+                    KVM_CAP_DESTROY_MEMORY_REGION_WORKS \
+                    KVM_CAP_COALESCED_MMIO \
+                    KVM_CAP_SYNC_MMU \
+                   "
+    if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) ; then
+      must_have_caps="$caps \
+                      KVM_CAP_SET_TSS_ADDR \
+                      KVM_CAP_EXT_CPUID \
+                      KVM_CAP_CLOCKSOURCE \
+                      KVM_CAP_NOP_IO_DELAY \
+                      KVM_CAP_PV_MMU \
+                      KVM_CAP_MP_STATE \
+                      KVM_CAP_USER_NMI \
+                     "
+    fi
+    for c in $must_have_caps ; do
+      cat >> $TMPC <<EOF
+#if !defined($c)
+#error Missing KVM capability $c
 #endif
+EOF
+    done
+    cat >> $TMPC <<EOF
 int main(void) { return 0; }
 EOF
   if test "$kerneldir" != "" ; then
@@ -1708,8 +1721,8 @@ EOF
 	| awk -F "error: " '{if (NR>1) printf(", "); printf("%s",$2);}'`
         if test "$kvmerr" != "" ; then
           echo -e "${kvmerr}\n\
-      NOTE: To enable KVM support, update your kernel to 2.6.29+ or install \
-  recent kvm-kmod from http://sourceforge.net/projects/kvm."
+NOTE: To enable KVM support, update your kernel to 2.6.29+ or install \
+recent kvm-kmod from http://sourceforge.net/projects/kvm."
         fi
       fi
       feature_not_found "kvm"
diff --git a/kvm-all.c b/kvm-all.c
index 8053f92..3a1f63b 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -63,9 +63,7 @@ struct KVMState
     int fd;
     int vmfd;
     int coalesced_mmio;
-#ifdef KVM_CAP_COALESCED_MMIO
     struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
-#endif
     int broken_set_mem_region;
     int migration_log;
     int vcpu_events;
@@ -82,6 +80,12 @@ struct KVMState
 
 static KVMState *kvm_state;
 
+static const KVMCapabilityInfo kvm_required_capabilites[] = {
+    KVM_CAP_INFO(USER_MEMORY),
+    KVM_CAP_INFO(DESTROY_MEMORY_REGION_WORKS),
+    KVM_CAP_LAST_INFO
+};
+
 static KVMSlot *kvm_alloc_slot(KVMState *s)
 {
     int i;
@@ -227,12 +231,10 @@ int kvm_init_vcpu(CPUState *env)
         goto err;
     }
 
-#ifdef KVM_CAP_COALESCED_MMIO
     if (s->coalesced_mmio && !s->coalesced_mmio_ring) {
         s->coalesced_mmio_ring =
             (void *)env->kvm_run + s->coalesced_mmio * PAGE_SIZE;
     }
-#endif
 
     ret = kvm_arch_init_vcpu(env);
     if (ret == 0) {
@@ -401,7 +403,6 @@ static int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
 int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
 {
     int ret = -ENOSYS;
-#ifdef KVM_CAP_COALESCED_MMIO
     KVMState *s = kvm_state;
 
     if (s->coalesced_mmio) {
@@ -412,7 +413,6 @@ int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
 
         ret = kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone);
     }
-#endif
 
     return ret;
 }
@@ -420,7 +420,6 @@ int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
 int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
 {
     int ret = -ENOSYS;
-#ifdef KVM_CAP_COALESCED_MMIO
     KVMState *s = kvm_state;
 
     if (s->coalesced_mmio) {
@@ -431,7 +430,6 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
 
         ret = kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone);
     }
-#endif
 
     return ret;
 }
@@ -481,6 +479,18 @@ static int kvm_check_many_ioeventfds(void)
 #endif
 }
 
+static const KVMCapabilityInfo *
+kvm_check_extension_list(KVMState *s, const KVMCapabilityInfo *list)
+{
+    while (list->name) {
+        if (!kvm_check_extension(s, list->value)) {
+            return list;
+        }
+        list++;
+    }
+    return NULL;
+}
+
 static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
                              ram_addr_t phys_offset)
 {
@@ -642,6 +652,7 @@ int kvm_init(void)
         "Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n"
         "(see http://sourceforge.net/projects/kvm).\n";
     KVMState *s;
+    const KVMCapabilityInfo *missing_cap;
     int ret;
     int i;
 
@@ -685,35 +696,19 @@ int kvm_init(void)
         goto err;
     }
 
-    /* initially, KVM allocated its own memory and we had to jump through
-     * hooks to make phys_ram_base point to this.  Modern versions of KVM
-     * just use a user allocated buffer so we can use regular pages
-     * unmodified.  Make sure we have a sufficiently modern version of KVM.
-     */
-    if (!kvm_check_extension(s, KVM_CAP_USER_MEMORY)) {
-        ret = -EINVAL;
-        fprintf(stderr, "kvm does not support KVM_CAP_USER_MEMORY\n%s",
-                upgrade_note);
-        goto err;
+    missing_cap = kvm_check_extension_list(s, kvm_required_capabilites);
+    if (!missing_cap) {
+        missing_cap =
+            kvm_check_extension_list(s, kvm_arch_required_capabilities);
     }
-
-    /* There was a nasty bug in < kvm-80 that prevents memory slots from being
-     * destroyed properly.  Since we rely on this capability, refuse to work
-     * with any kernel without this capability. */
-    if (!kvm_check_extension(s, KVM_CAP_DESTROY_MEMORY_REGION_WORKS)) {
+    if (missing_cap) {
         ret = -EINVAL;
-
-        fprintf(stderr,
-                "KVM kernel module broken (DESTROY_MEMORY_REGION).\n%s",
-                upgrade_note);
+        fprintf(stderr, "kvm does not support %s\n%s",
+                missing_cap->name, upgrade_note);
         goto err;
     }
 
-    s->coalesced_mmio = 0;
-#ifdef KVM_CAP_COALESCED_MMIO
     s->coalesced_mmio = kvm_check_extension(s, KVM_CAP_COALESCED_MMIO);
-    s->coalesced_mmio_ring = NULL;
-#endif
 
     s->broken_set_mem_region = 1;
 #ifdef KVM_CAP_JOIN_MEMORY_REGIONS_WORKS
@@ -845,7 +840,6 @@ static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
 
 void kvm_flush_coalesced_mmio_buffer(void)
 {
-#ifdef KVM_CAP_COALESCED_MMIO
     KVMState *s = kvm_state;
     if (s->coalesced_mmio_ring) {
         struct kvm_coalesced_mmio_ring *ring = s->coalesced_mmio_ring;
@@ -859,7 +853,6 @@ void kvm_flush_coalesced_mmio_buffer(void)
             ring->first = (ring->first + 1) % KVM_COALESCED_MMIO_MAX;
         }
     }
-#endif
 }
 
 static void do_kvm_cpu_synchronize_state(void *_env)
@@ -1059,13 +1052,7 @@ int kvm_vcpu_ioctl(CPUState *env, int type, ...)
 
 int kvm_has_sync_mmu(void)
 {
-#ifdef KVM_CAP_SYNC_MMU
-    KVMState *s = kvm_state;
-
-    return kvm_check_extension(s, KVM_CAP_SYNC_MMU);
-#else
-    return 0;
-#endif
+    return kvm_check_extension(kvm_state, KVM_CAP_SYNC_MMU);
 }
 
 int kvm_has_vcpu_events(void)
diff --git a/kvm.h b/kvm.h
index a971752..ca57517 100644
--- a/kvm.h
+++ b/kvm.h
@@ -32,6 +32,14 @@ extern int kvm_allowed;
 
 struct kvm_run;
 
+typedef struct KVMCapabilityInfo {
+    const char *name;
+    int value;
+} KVMCapabilityInfo;
+
+#define KVM_CAP_INFO(CAP) { "KVM_CAP_" stringify(CAP), KVM_CAP_##CAP }
+#define KVM_CAP_LAST_INFO { NULL, 0 }
+
 /* external API */
 
 int kvm_init(void);
@@ -86,6 +94,8 @@ int kvm_vcpu_ioctl(CPUState *env, int type, ...);
 
 /* Arch specific hooks */
 
+extern const KVMCapabilityInfo kvm_arch_required_capabilities[];
+
 int kvm_arch_post_run(CPUState *env, struct kvm_run *run);
 
 int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 016b67d..1db8227 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -54,12 +54,17 @@
 #define BUS_MCEERR_AO 5
 #endif
 
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+    KVM_CAP_INFO(SET_TSS_ADDR),
+    KVM_CAP_INFO(EXT_CPUID),
+    KVM_CAP_INFO(MP_STATE),
+    KVM_CAP_LAST_INFO
+};
+
 static bool has_msr_star;
 static bool has_msr_hsave_pa;
 static int lm_capable_kernel;
 
-#ifdef KVM_CAP_EXT_CPUID
-
 static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
 {
     struct kvm_cpuid2 *cpuid;
@@ -93,10 +98,6 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
     uint32_t ret = 0;
     uint32_t cpuid_1_edx;
 
-    if (!kvm_check_extension(env->kvm_state, KVM_CAP_EXT_CPUID)) {
-        return -1U;
-    }
-
     max = 1;
     while ((cpuid = try_get_cpuid(env->kvm_state, max)) == NULL) {
         max *= 2;
@@ -140,30 +141,14 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
     return ret;
 }
 
-#else
-
-uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
-                                      uint32_t index, int reg)
-{
-    return -1U;
-}
-
-#endif
-
 #ifdef CONFIG_KVM_PARA
 struct kvm_para_features {
     int cap;
     int feature;
 } para_features[] = {
-#ifdef KVM_CAP_CLOCKSOURCE
     { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
-#endif
-#ifdef KVM_CAP_NOP_IO_DELAY
     { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
-#endif
-#ifdef KVM_CAP_PV_MMU
     { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
-#endif
 #ifdef KVM_CAP_ASYNC_PF
     { KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF },
 #endif
@@ -542,15 +527,7 @@ int kvm_arch_init(KVMState *s)
 
     /* create vm86 tss.  KVM uses vm86 mode to emulate 16-bit code
      * directly.  In order to use vm86 mode, a TSS is needed.  Since this
-     * must be part of guest physical memory, we need to allocate it.  Older
-     * versions of KVM just assumed that it would be at the end of physical
-     * memory but that doesn't work with more than 4GB of memory.  We simply
-     * refuse to work with those older versions of KVM. */
-    ret = kvm_check_extension(s, KVM_CAP_SET_TSS_ADDR);
-    if (ret <= 0) {
-        fprintf(stderr, "kvm does not support KVM_CAP_SET_TSS_ADDR\n");
-        return ret;
-    }
+     * must be part of guest physical memory, we need to allocate it. */
 
     /* this address is 3 pages before the bios, and the bios should present
      * as unavaible memory.  FIXME, need to ensure the e820 map deals with
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 3c05630..710eca1 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -37,6 +37,10 @@
     do { } while (0)
 #endif
 
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+    KVM_CAP_LAST_INFO
+};
+
 static int cap_interrupt_unset = false;
 static int cap_interrupt_level = false;
 
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index b177e10..38823f5 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -70,6 +70,10 @@
 #define SCLP_CMDW_READ_SCP_INFO         0x00020001
 #define SCLP_CMDW_READ_SCP_INFO_FORCED  0x00120001
 
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+    KVM_CAP_LAST_INFO
+};
+
 int kvm_arch_init(KVMState *s)
 {
     return 0;
commit c5999bfcfdf66390c98115044cb6fd174fbcf36d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:22 2011 +0100

    kvm: x86: Only read/write MSR_KVM_ASYNC_PF_EN if supported
    
    If the kernel does not support KVM_CAP_ASYNC_PF, it also does not know
    about the related MSR. So skip it during state synchronization in that
    case. Fixes annoying kernel warnings.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index b2c5ee0..8e8880a 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -63,6 +63,9 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 
 static bool has_msr_star;
 static bool has_msr_hsave_pa;
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
+static bool has_msr_async_pf_en;
+#endif
 static int lm_capable_kernel;
 
 static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
@@ -164,6 +167,7 @@ static int get_para_features(CPUState *env)
             features |= (1 << para_features[i].feature);
         }
     }
+    has_msr_async_pf_en = features & (1 << KVM_FEATURE_ASYNC_PF);
     return features;
 }
 #endif
@@ -828,7 +832,10 @@ static int kvm_put_msrs(CPUState *env, int level)
                           env->system_time_msr);
         kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
 #if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
-        kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr);
+        if (has_msr_async_pf_en) {
+            kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN,
+                              env->async_pf_en_msr);
+        }
 #endif
     }
 #ifdef KVM_CAP_MCE
@@ -1064,7 +1071,9 @@ static int kvm_get_msrs(CPUState *env)
     msrs[n++].index = MSR_KVM_SYSTEM_TIME;
     msrs[n++].index = MSR_KVM_WALL_CLOCK;
 #if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
-    msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
+    if (has_msr_async_pf_en) {
+        msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
+    }
 #endif
 
 #ifdef KVM_CAP_MCE
commit d8f771d9124e9a295b564d47d7546d93e844b526
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:21 2011 +0100

    kvm: x86: Implicitly clear nmi_injected/pending on reset
    
    All CPUX86State variables before CPU_COMMON are automatically cleared on
    reset. Reorder nmi_injected and nmi_pending to avoid having to touch
    them explicitly.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index a457423..af701a4 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -699,6 +699,10 @@ typedef struct CPUX86State {
     uint32_t smbase;
     int old_exception;  /* exception in flight */
 
+    /* KVM states, automatically cleared on reset */
+    uint8_t nmi_injected;
+    uint8_t nmi_pending;
+
     CPU_COMMON
 
     /* processor features (e.g. for CPUID insn) */
@@ -726,8 +730,6 @@ typedef struct CPUX86State {
     int32_t exception_injected;
     int32_t interrupt_injected;
     uint8_t soft_interrupt;
-    uint8_t nmi_injected;
-    uint8_t nmi_pending;
     uint8_t has_error_code;
     uint32_t sipi_vector;
     uint32_t cpuid_kvm_features;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 72f9fdf..b2c5ee0 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -435,8 +435,6 @@ void kvm_arch_reset_vcpu(CPUState *env)
 {
     env->exception_injected = -1;
     env->interrupt_injected = -1;
-    env->nmi_injected = 0;
-    env->nmi_pending = 0;
     env->xcr0 = 1;
     if (kvm_irqchip_in_kernel()) {
         env->mp_state = cpu_is_bsp(env) ? KVM_MP_STATE_RUNNABLE :
commit b66042c722e4e7b2811a08873b1ecf2c2c1e5f0a
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:20 2011 +0100

    kvm: Do not use qemu_fair_mutex
    
    The imbalance in the hold time of qemu_global_mutex only exists in TCG
    mode. In contrast to TCG VCPUs, KVM drops the global lock during guest
    execution. We already avoid touching the fairness lock from the
    IO-thread in KVM mode, so also stop using it from the VCPU threads.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpus.c b/cpus.c
index 0309189..4c9928e 100644
--- a/cpus.c
+++ b/cpus.c
@@ -735,9 +735,7 @@ static sigset_t block_io_signals(void)
 void qemu_mutex_lock_iothread(void)
 {
     if (kvm_enabled()) {
-        qemu_mutex_lock(&qemu_fair_mutex);
         qemu_mutex_lock(&qemu_global_mutex);
-        qemu_mutex_unlock(&qemu_fair_mutex);
     } else {
         qemu_mutex_lock(&qemu_fair_mutex);
         if (qemu_mutex_trylock(&qemu_global_mutex)) {
commit b0c883b5e079a4f719c43f875034e5e665ccc232
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:19 2011 +0100

    kvm: Flush coalesced mmio buffer on IO window exits
    
    We must flush pending mmio writes if we leave kvm_cpu_exec for an IO
    window. Otherwise we risk to loose those requests when migrating to a
    different host during that window.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 3a1f63b..9976762 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -918,6 +918,8 @@ int kvm_cpu_exec(CPUState *env)
         cpu_single_env = env;
         kvm_arch_post_run(env, run);
 
+        kvm_flush_coalesced_mmio_buffer();
+
         if (ret == -EINTR || ret == -EAGAIN) {
             cpu_exit(env);
             DPRINTF("io window exit\n");
@@ -930,8 +932,6 @@ int kvm_cpu_exec(CPUState *env)
             abort();
         }
 
-        kvm_flush_coalesced_mmio_buffer();
-
         ret = 0; /* exit loop */
         switch (run->exit_reason) {
         case KVM_EXIT_IO:
commit 110761987d10c6e6983cc445618acfd158d7ce02
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:18 2011 +0100

    kvm: x86: Rework identity map and TSS setup for larger BIOS sizes
    
    In order to support loading BIOSes > 256K, reorder the code, adjusting
    the base if the kernel supports moving the identity map.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 1db8227..72f9fdf 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -493,27 +493,9 @@ static int kvm_get_supported_msrs(KVMState *s)
     return ret;
 }
 
-static int kvm_init_identity_map_page(KVMState *s)
-{
-#ifdef KVM_CAP_SET_IDENTITY_MAP_ADDR
-    int ret;
-    uint64_t addr = 0xfffbc000;
-
-    if (!kvm_check_extension(s, KVM_CAP_SET_IDENTITY_MAP_ADDR)) {
-        return 0;
-    }
-
-    ret = kvm_vm_ioctl(s, KVM_SET_IDENTITY_MAP_ADDR, &addr);
-    if (ret < 0) {
-        fprintf(stderr, "kvm_set_identity_map_addr: %s\n", strerror(ret));
-        return ret;
-    }
-#endif
-    return 0;
-}
-
 int kvm_arch_init(KVMState *s)
 {
+    uint64_t identity_base = 0xfffbc000;
     int ret;
     struct utsname utsname;
 
@@ -525,27 +507,42 @@ int kvm_arch_init(KVMState *s)
     uname(&utsname);
     lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0;
 
-    /* create vm86 tss.  KVM uses vm86 mode to emulate 16-bit code
-     * directly.  In order to use vm86 mode, a TSS is needed.  Since this
-     * must be part of guest physical memory, we need to allocate it. */
-
-    /* this address is 3 pages before the bios, and the bios should present
-     * as unavaible memory.  FIXME, need to ensure the e820 map deals with
-     * this?
-     */
     /*
-     * Tell fw_cfg to notify the BIOS to reserve the range.
+     * On older Intel CPUs, KVM uses vm86 mode to emulate 16-bit code directly.
+     * In order to use vm86 mode, an EPT identity map and a TSS  are needed.
+     * Since these must be part of guest physical memory, we need to allocate
+     * them, both by setting their start addresses in the kernel and by
+     * creating a corresponding e820 entry. We need 4 pages before the BIOS.
+     *
+     * Older KVM versions may not support setting the identity map base. In
+     * that case we need to stick with the default, i.e. a 256K maximum BIOS
+     * size.
      */
-    if (e820_add_entry(0xfffbc000, 0x4000, E820_RESERVED) < 0) {
-        perror("e820_add_entry() table is full");
-        exit(1);
+#ifdef KVM_CAP_SET_IDENTITY_MAP_ADDR
+    if (kvm_check_extension(s, KVM_CAP_SET_IDENTITY_MAP_ADDR)) {
+        /* Allows up to 16M BIOSes. */
+        identity_base = 0xfeffc000;
+
+        ret = kvm_vm_ioctl(s, KVM_SET_IDENTITY_MAP_ADDR, &identity_base);
+        if (ret < 0) {
+            return ret;
+        }
     }
-    ret = kvm_vm_ioctl(s, KVM_SET_TSS_ADDR, 0xfffbd000);
+#endif
+    /* Set TSS base one page after EPT identity map. */
+    ret = kvm_vm_ioctl(s, KVM_SET_TSS_ADDR, identity_base + 0x1000);
+    if (ret < 0) {
+        return ret;
+    }
+
+    /* Tell fw_cfg to notify the BIOS to reserve the range. */
+    ret = e820_add_entry(identity_base, 0x4000, E820_RESERVED);
     if (ret < 0) {
+        fprintf(stderr, "e820_add_entry() table is full\n");
         return ret;
     }
 
-    return kvm_init_identity_map_page(s);
+    return 0;
 }
 
 static void set_v8086_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
commit cad1e2827b616487e3574300f2eaeea13a355197
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:16 2011 +0100

    kvm: Drop smp_cpus argument from init functions
    
    No longer used.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 41decde..8053f92 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -636,7 +636,7 @@ static CPUPhysMemoryClient kvm_cpu_phys_memory_client = {
     .migration_log = kvm_client_migration_log,
 };
 
-int kvm_init(int smp_cpus)
+int kvm_init(void)
 {
     static const char upgrade_note[] =
         "Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n"
@@ -749,7 +749,7 @@ int kvm_init(int smp_cpus)
     s->xcrs = kvm_check_extension(s, KVM_CAP_XCRS);
 #endif
 
-    ret = kvm_arch_init(s, smp_cpus);
+    ret = kvm_arch_init(s);
     if (ret < 0) {
         goto err;
     }
diff --git a/kvm-stub.c b/kvm-stub.c
index 33d4476..88682f2 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -58,7 +58,7 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
     return 0;
 }
 
-int kvm_init(int smp_cpus)
+int kvm_init(void)
 {
     return -ENOSYS;
 }
diff --git a/kvm.h b/kvm.h
index ce08d42..a971752 100644
--- a/kvm.h
+++ b/kvm.h
@@ -34,7 +34,7 @@ struct kvm_run;
 
 /* external API */
 
-int kvm_init(int smp_cpus);
+int kvm_init(void);
 
 int kvm_has_sync_mmu(void);
 int kvm_has_vcpu_events(void);
@@ -105,7 +105,7 @@ int kvm_arch_get_registers(CPUState *env);
 
 int kvm_arch_put_registers(CPUState *env, int level);
 
-int kvm_arch_init(KVMState *s, int smp_cpus);
+int kvm_arch_init(KVMState *s);
 
 int kvm_arch_init_vcpu(CPUState *env);
 
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index feaf33d..016b67d 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -527,7 +527,7 @@ static int kvm_init_identity_map_page(KVMState *s)
     return 0;
 }
 
-int kvm_arch_init(KVMState *s, int smp_cpus)
+int kvm_arch_init(KVMState *s)
 {
     int ret;
     struct utsname utsname;
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 849b404..3c05630 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -56,7 +56,7 @@ static void kvm_kick_env(void *env)
     qemu_cpu_kick(env);
 }
 
-int kvm_arch_init(KVMState *s, int smp_cpus)
+int kvm_arch_init(KVMState *s)
 {
 #ifdef KVM_CAP_PPC_UNSET_IRQ
     cap_interrupt_unset = kvm_check_extension(s, KVM_CAP_PPC_UNSET_IRQ);
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index adf4a9e..b177e10 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -70,7 +70,7 @@
 #define SCLP_CMDW_READ_SCP_INFO         0x00020001
 #define SCLP_CMDW_READ_SCP_INFO_FORCED  0x00120001
 
-int kvm_arch_init(KVMState *s, int smp_cpus)
+int kvm_arch_init(KVMState *s)
 {
     return 0;
 }
diff --git a/vl.c b/vl.c
index 0292184..33f844f 100644
--- a/vl.c
+++ b/vl.c
@@ -2836,7 +2836,7 @@ int main(int argc, char **argv, char **envp)
     }
 
     if (kvm_allowed) {
-        int ret = kvm_init(smp_cpus);
+        int ret = kvm_init();
         if (ret < 0) {
             if (!kvm_available()) {
                 printf("KVM not supported for this target\n");
commit c3a3a7d356c4df2fe145037172ae52cba5f545a5
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:13 2011 +0100

    kvm: x86: Refactor msr_star/hsave_pa setup and checks
    
    Simplify kvm_has_msr_star/hsave_pa to booleans and push their one-time
    initialization into kvm_arch_init. Also handle potential errors of that
    setup procedure.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index c4a22dd..454ddb1 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -54,6 +54,8 @@
 #define BUS_MCEERR_AO 5
 #endif
 
+static bool has_msr_star;
+static bool has_msr_hsave_pa;
 static int lm_capable_kernel;
 
 #ifdef KVM_CAP_EXT_CPUID
@@ -459,13 +461,10 @@ void kvm_arch_reset_vcpu(CPUState *env)
     }
 }
 
-int has_msr_star;
-int has_msr_hsave_pa;
-
-static void kvm_supported_msrs(CPUState *env)
+static int kvm_get_supported_msrs(KVMState *s)
 {
     static int kvm_supported_msrs;
-    int ret;
+    int ret = 0;
 
     /* first time */
     if (kvm_supported_msrs == 0) {
@@ -476,9 +475,9 @@ static void kvm_supported_msrs(CPUState *env)
         /* Obtain MSR list from KVM.  These are the MSRs that we must
          * save/restore */
         msr_list.nmsrs = 0;
-        ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, &msr_list);
+        ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, &msr_list);
         if (ret < 0 && ret != -E2BIG) {
-            return;
+            return ret;
         }
         /* Old kernel modules had a bug and could write beyond the provided
            memory. Allocate at least a safe amount of 1K. */
@@ -487,17 +486,17 @@ static void kvm_supported_msrs(CPUState *env)
                                               sizeof(msr_list.indices[0])));
 
         kvm_msr_list->nmsrs = msr_list.nmsrs;
-        ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, kvm_msr_list);
+        ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, kvm_msr_list);
         if (ret >= 0) {
             int i;
 
             for (i = 0; i < kvm_msr_list->nmsrs; i++) {
                 if (kvm_msr_list->indices[i] == MSR_STAR) {
-                    has_msr_star = 1;
+                    has_msr_star = true;
                     continue;
                 }
                 if (kvm_msr_list->indices[i] == MSR_VM_HSAVE_PA) {
-                    has_msr_hsave_pa = 1;
+                    has_msr_hsave_pa = true;
                     continue;
                 }
             }
@@ -506,19 +505,7 @@ static void kvm_supported_msrs(CPUState *env)
         free(kvm_msr_list);
     }
 
-    return;
-}
-
-static int kvm_has_msr_hsave_pa(CPUState *env)
-{
-    kvm_supported_msrs(env);
-    return has_msr_hsave_pa;
-}
-
-static int kvm_has_msr_star(CPUState *env)
-{
-    kvm_supported_msrs(env);
-    return has_msr_star;
+    return ret;
 }
 
 static int kvm_init_identity_map_page(KVMState *s)
@@ -543,9 +530,13 @@ static int kvm_init_identity_map_page(KVMState *s)
 int kvm_arch_init(KVMState *s, int smp_cpus)
 {
     int ret;
-
     struct utsname utsname;
 
+    ret = kvm_get_supported_msrs(s);
+    if (ret < 0) {
+        return ret;
+    }
+
     uname(&utsname);
     lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0;
 
@@ -830,10 +821,10 @@ static int kvm_put_msrs(CPUState *env, int level)
     kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs);
     kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp);
     kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
-    if (kvm_has_msr_star(env)) {
+    if (has_msr_star) {
         kvm_msr_entry_set(&msrs[n++], MSR_STAR, env->star);
     }
-    if (kvm_has_msr_hsave_pa(env)) {
+    if (has_msr_hsave_pa) {
         kvm_msr_entry_set(&msrs[n++], MSR_VM_HSAVE_PA, env->vm_hsave);
     }
 #ifdef TARGET_X86_64
@@ -1076,10 +1067,10 @@ static int kvm_get_msrs(CPUState *env)
     msrs[n++].index = MSR_IA32_SYSENTER_CS;
     msrs[n++].index = MSR_IA32_SYSENTER_ESP;
     msrs[n++].index = MSR_IA32_SYSENTER_EIP;
-    if (kvm_has_msr_star(env)) {
+    if (has_msr_star) {
         msrs[n++].index = MSR_STAR;
     }
-    if (kvm_has_msr_hsave_pa(env)) {
+    if (has_msr_hsave_pa) {
         msrs[n++].index = MSR_VM_HSAVE_PA;
     }
     msrs[n++].index = MSR_IA32_TSC;
commit 1a5e9d2fafa5d31587e218cea462637bfad52b53
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:12 2011 +0100

    kvm: x86: Fix xcr0 reset mismerge
    
    For unknown reasons, xcr0 reset ended up in kvm_arch_update_guest_debug
    on upstream merge. Fix this and also remove the misleading comment (1 is
    THE reset value).
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 07c75c0..c4a22dd 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -450,6 +450,7 @@ void kvm_arch_reset_vcpu(CPUState *env)
     env->interrupt_injected = -1;
     env->nmi_injected = 0;
     env->nmi_pending = 0;
+    env->xcr0 = 1;
     if (kvm_irqchip_in_kernel()) {
         env->mp_state = cpu_is_bsp(env) ? KVM_MP_STATE_RUNNABLE :
                                           KVM_MP_STATE_UNINITIALIZED;
@@ -1759,8 +1760,6 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
                 ((uint32_t)len_code[hw_breakpoint[n].len] << (18 + n*4));
         }
     }
-    /* Legal xcr0 for loading */
-    env->xcr0 = 1;
 }
 #endif /* KVM_CAP_SET_GUEST_DEBUG */
 
commit 3390e7f79784cbc75df408740cda4edbcf57ac58
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:11 2011 +0100

    kvm: x86: Remove redundant mp_state initialization
    
    kvm_arch_reset_vcpu initializes mp_state, and that function is invoked
    right after kvm_arch_init_vcpu.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 531b69e..07c75c0 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -321,8 +321,6 @@ int kvm_arch_init_vcpu(CPUState *env)
     uint32_t signature[3];
 #endif
 
-    env->mp_state = KVM_MP_STATE_RUNNABLE;
-
     env->cpuid_features &= kvm_arch_get_supported_cpuid(env, 1, 0, R_EDX);
 
     i = env->cpuid_ext_features & CPUID_EXT_HYPERVISOR;
commit 521f0798d7e38c21983211a6585ebcf79de4c14a
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:15 2011 +0100

    kvm: x86: Fix !CONFIG_KVM_PARA build
    
    If we lack kvm_para.h, MSR_KVM_ASYNC_PF_EN is not defined. The change in
    kvm_arch_init_vcpu is just for consistency reasons.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 825af42..feaf33d 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -319,7 +319,7 @@ int kvm_arch_init_vcpu(CPUState *env)
     uint32_t limit, i, j, cpuid_i;
     uint32_t unused;
     struct kvm_cpuid_entry2 *c;
-#ifdef KVM_CPUID_SIGNATURE
+#ifdef CONFIG_KVM_PARA
     uint32_t signature[3];
 #endif
 
@@ -855,7 +855,7 @@ static int kvm_put_msrs(CPUState *env, int level)
         kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME,
                           env->system_time_msr);
         kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
-#ifdef KVM_CAP_ASYNC_PF
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
         kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr);
 #endif
     }
@@ -1091,7 +1091,7 @@ static int kvm_get_msrs(CPUState *env)
 #endif
     msrs[n++].index = MSR_KVM_SYSTEM_TIME;
     msrs[n++].index = MSR_KVM_WALL_CLOCK;
-#ifdef KVM_CAP_ASYNC_PF
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
     msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
 #endif
 
@@ -1167,7 +1167,7 @@ static int kvm_get_msrs(CPUState *env)
             }
 #endif
             break;
-#ifdef KVM_CAP_ASYNC_PF
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
         case MSR_KVM_ASYNC_PF_EN:
             env->async_pf_en_msr = msrs[i].data;
             break;
commit c14750e8ad4a9d8d7621e2594abda34df19a6eff
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:10 2011 +0100

    kvm: x86: Prepare kvm_get_mp_state for in-kernel irqchip
    
    This code path will not yet be taken as we still lack in-kernel irqchip
    support. But qemu-kvm can already make use of it and drop its own
    mp_state access services.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 9bb34ab..531b69e 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1198,6 +1198,9 @@ static int kvm_get_mp_state(CPUState *env)
         return ret;
     }
     env->mp_state = mp_state.mp_state;
+    if (kvm_irqchip_in_kernel()) {
+        env->halted = (mp_state.mp_state == KVM_MP_STATE_HALTED);
+    }
     return 0;
 }
 
commit ff5c186b8b6169bf25a6f30670a75fb9d4c945e3
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:14 2011 +0100

    kvm: x86: Reset paravirtual MSRs
    
    Make sure to write the cleared MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
    and MSR_KVM_ASYNC_PF_EN to the kernel state so that a freshly booted
    guest cannot be disturbed by old values.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    CC: Glauber Costa <glommer at redhat.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 454ddb1..825af42 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -845,6 +845,13 @@ static int kvm_put_msrs(CPUState *env, int level)
         if (smp_cpus == 1 || env->tsc != 0) {
             kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc);
         }
+    }
+    /*
+     * The following paravirtual MSRs have side effects on the guest or are
+     * too heavy for normal writeback. Limit them to reset or full state
+     * updates.
+     */
+    if (level >= KVM_PUT_RESET_STATE) {
         kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME,
                           env->system_time_msr);
         kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
commit 0d75a9ecd7ff77db0f1b5bfb3a3fee2438acefa4
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:09 2011 +0100

    kvm: x86: Align kvm_arch_put_registers code with comment
    
    The ordering doesn't matter in this case, but better keep it consistent.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0ba13fc..9bb34ab 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1388,12 +1388,12 @@ int kvm_arch_put_registers(CPUState *env, int level)
     if (ret < 0) {
         return ret;
     }
-    /* must be last */
-    ret = kvm_guest_debug_workarounds(env);
+    ret = kvm_put_debugregs(env);
     if (ret < 0) {
         return ret;
     }
-    ret = kvm_put_debugregs(env);
+    /* must be last */
+    ret = kvm_guest_debug_workarounds(env);
     if (ret < 0) {
         return ret;
     }
commit f5c848eed769b795ac9c06bfb315e4aa9116337c
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:08 2011 +0100

    x86: Optionally dump code bytes on cpu_dump_state
    
    Introduce the cpu_dump_state flag CPU_DUMP_CODE and implement it for
    x86. This writes out the code bytes around the current instruction
    pointer. Make use of this feature in KVM to help debugging fatal vm
    exits.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/cpu-all.h b/cpu-all.h
index 4ce4e83..ffbd6a4 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -765,6 +765,8 @@ int page_check_range(target_ulong start, target_ulong len, int flags);
 CPUState *cpu_copy(CPUState *env);
 CPUState *qemu_get_cpu(int cpu);
 
+#define CPU_DUMP_CODE 0x00010000
+
 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
                     int flags);
 void cpu_dump_statistics(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
diff --git a/kvm-all.c b/kvm-all.c
index 10e1194..41decde 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -832,7 +832,7 @@ static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
     if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
         fprintf(stderr, "emulation failure\n");
         if (!kvm_arch_stop_on_emulation_error(env)) {
-            cpu_dump_state(env, stderr, fprintf, 0);
+            cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
             return 0;
         }
     }
@@ -994,7 +994,7 @@ int kvm_cpu_exec(CPUState *env)
     } while (ret > 0);
 
     if (ret < 0) {
-        cpu_dump_state(env, stderr, fprintf, 0);
+        cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
         vm_stop(0);
         env->exit_request = 1;
     }
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 6dfa27d..1217452 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -249,6 +249,9 @@ done:
     cpu_fprintf(f, "\n");
 }
 
+#define DUMP_CODE_BYTES_TOTAL    50
+#define DUMP_CODE_BYTES_BACKWARD 20
+
 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
                     int flags)
 {
@@ -434,6 +437,24 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
                 cpu_fprintf(f, " ");
         }
     }
+    if (flags & CPU_DUMP_CODE) {
+        target_ulong base = env->segs[R_CS].base + env->eip;
+        target_ulong offs = MIN(env->eip, DUMP_CODE_BYTES_BACKWARD);
+        uint8_t code;
+        char codestr[3];
+
+        cpu_fprintf(f, "Code=");
+        for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) {
+            if (cpu_memory_rw_debug(env, base - offs + i, &code, 1, 0) == 0) {
+                snprintf(codestr, sizeof(codestr), "%02x", code);
+            } else {
+                snprintf(codestr, sizeof(codestr), "??");
+            }
+            cpu_fprintf(f, "%s%s%s%s", i > 0 ? " " : "",
+                        i == offs ? "<" : "", codestr, i == offs ? ">" : "");
+        }
+        cpu_fprintf(f, "\n");
+    }
 }
 
 /***********************************************************/
commit bb44e0d12df70bd4a653341db4446daf6a9326be
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:07 2011 +0100

    kvm: Improve reporting of fatal errors
    
    Report KVM_EXIT_UNKNOWN, KVM_EXIT_FAIL_ENTRY, and KVM_EXIT_EXCEPTION
    with more details to stderr. The latter two are so far x86-only, so move
    them into the arch-specific handler. Integrate the Intel real mode
    warning on KVM_EXIT_FAIL_ENTRY that qemu-kvm carries, but actually
    restrict it to Intel CPUs. Moreover, always dump the CPU state in case
    we fail.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index eaf9272..10e1194 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -817,22 +817,22 @@ static int kvm_handle_io(uint16_t port, void *data, int direction, int size,
 #ifdef KVM_CAP_INTERNAL_ERROR_DATA
 static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
 {
-
+    fprintf(stderr, "KVM internal error.");
     if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {
         int i;
 
-        fprintf(stderr, "KVM internal error. Suberror: %d\n",
-                run->internal.suberror);
-
+        fprintf(stderr, " Suberror: %d\n", run->internal.suberror);
         for (i = 0; i < run->internal.ndata; ++i) {
             fprintf(stderr, "extra data[%d]: %"PRIx64"\n",
                     i, (uint64_t)run->internal.data[i]);
         }
+    } else {
+        fprintf(stderr, "\n");
     }
-    cpu_dump_state(env, stderr, fprintf, 0);
     if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
         fprintf(stderr, "emulation failure\n");
         if (!kvm_arch_stop_on_emulation_error(env)) {
+            cpu_dump_state(env, stderr, fprintf, 0);
             return 0;
         }
     }
@@ -966,15 +966,8 @@ int kvm_cpu_exec(CPUState *env)
             ret = 1;
             break;
         case KVM_EXIT_UNKNOWN:
-            DPRINTF("kvm_exit_unknown\n");
-            ret = -1;
-            break;
-        case KVM_EXIT_FAIL_ENTRY:
-            DPRINTF("kvm_exit_fail_entry\n");
-            ret = -1;
-            break;
-        case KVM_EXIT_EXCEPTION:
-            DPRINTF("kvm_exit_exception\n");
+            fprintf(stderr, "KVM: unknown exit, hardware reason %" PRIx64 "\n",
+                    (uint64_t)run->hw.hardware_exit_reason);
             ret = -1;
             break;
 #ifdef KVM_CAP_INTERNAL_ERROR_DATA
@@ -1001,6 +994,7 @@ int kvm_cpu_exec(CPUState *env)
     } while (ret > 0);
 
     if (ret < 0) {
+        cpu_dump_state(env, stderr, fprintf, 0);
         vm_stop(0);
         env->exit_request = 1;
     }
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index dddcd74..a457423 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -874,6 +874,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
                    uint32_t *ecx, uint32_t *edx);
 int cpu_x86_register (CPUX86State *env, const char *cpu_model);
 void cpu_clear_apic_feature(CPUX86State *env);
+void host_cpuid(uint32_t function, uint32_t count,
+                uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
 
 /* helper.c */
 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 165045e..5382a28 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -103,9 +103,8 @@ typedef struct model_features_t {
 int check_cpuid = 0;
 int enforce_cpuid = 0;
 
-static void host_cpuid(uint32_t function, uint32_t count,
-                       uint32_t *eax, uint32_t *ebx,
-                       uint32_t *ecx, uint32_t *edx)
+void host_cpuid(uint32_t function, uint32_t count,
+                uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
 {
 #if defined(CONFIG_KVM)
     uint32_t vec[4];
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 6b4abaa..0ba13fc 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1525,8 +1525,19 @@ static int kvm_handle_halt(CPUState *env)
     return 1;
 }
 
+static bool host_supports_vmx(void)
+{
+    uint32_t ecx, unused;
+
+    host_cpuid(1, 0, &unused, &unused, &ecx, &unused);
+    return ecx & CPUID_EXT_VMX;
+}
+
+#define VMX_INVALID_GUEST_STATE 0x80000021
+
 int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
 {
+    uint64_t code;
     int ret = 0;
 
     switch (run->exit_reason) {
@@ -1537,6 +1548,28 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
     case KVM_EXIT_SET_TPR:
         ret = 1;
         break;
+    case KVM_EXIT_FAIL_ENTRY:
+        code = run->fail_entry.hardware_entry_failure_reason;
+        fprintf(stderr, "KVM: entry failed, hardware error 0x%" PRIx64 "\n",
+                code);
+        if (host_supports_vmx() && code == VMX_INVALID_GUEST_STATE) {
+            fprintf(stderr,
+                    "\nIf you're runnning a guest on an Intel machine without "
+                        "unrestricted mode\n"
+                    "support, the failure can be most likely due to the guest "
+                        "entering an invalid\n"
+                    "state for Intel VT. For example, the guest maybe running "
+                        "in big real mode\n"
+                    "which is not supported on less recent Intel processors."
+                        "\n\n");
+        }
+        ret = -1;
+        break;
+    case KVM_EXIT_EXCEPTION:
+        fprintf(stderr, "KVM: exception %d exit (error code 0x%x)\n",
+                run->ex.exception, run->ex.error_code);
+        ret = -1;
+        break;
     default:
         fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
         ret = -1;
commit 73aaec4a39b3cf11082303a6cf6bcde8796c09c6
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:06 2011 +0100

    kvm: Stop on all fatal exit reasons
    
    Ensure that we stop the guest whenever we face a fatal or unknown exit
    reason. If we stop, we also have to enforce a cpu loop exit.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/kvm-all.c b/kvm-all.c
index 86ddbd6..eaf9272 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -815,7 +815,7 @@ static int kvm_handle_io(uint16_t port, void *data, int direction, int size,
 }
 
 #ifdef KVM_CAP_INTERNAL_ERROR_DATA
-static void kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
+static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
 {
 
     if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {
@@ -833,13 +833,13 @@ static void kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
     if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
         fprintf(stderr, "emulation failure\n");
         if (!kvm_arch_stop_on_emulation_error(env)) {
-            return;
+            return 0;
         }
     }
     /* FIXME: Should trigger a qmp message to let management know
      * something went wrong.
      */
-    vm_stop(0);
+    return -1;
 }
 #endif
 
@@ -967,16 +967,19 @@ int kvm_cpu_exec(CPUState *env)
             break;
         case KVM_EXIT_UNKNOWN:
             DPRINTF("kvm_exit_unknown\n");
+            ret = -1;
             break;
         case KVM_EXIT_FAIL_ENTRY:
             DPRINTF("kvm_exit_fail_entry\n");
+            ret = -1;
             break;
         case KVM_EXIT_EXCEPTION:
             DPRINTF("kvm_exit_exception\n");
+            ret = -1;
             break;
 #ifdef KVM_CAP_INTERNAL_ERROR_DATA
         case KVM_EXIT_INTERNAL_ERROR:
-            kvm_handle_internal_error(env, run);
+            ret = kvm_handle_internal_error(env, run);
             break;
 #endif
         case KVM_EXIT_DEBUG:
@@ -997,6 +1000,10 @@ int kvm_cpu_exec(CPUState *env)
         }
     } while (ret > 0);
 
+    if (ret < 0) {
+        vm_stop(0);
+        env->exit_request = 1;
+    }
     if (env->exit_request) {
         env->exit_request = 0;
         env->exception_index = EXCP_INTERRUPT;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0aeb079..6b4abaa 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1537,6 +1537,10 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
     case KVM_EXIT_SET_TPR:
         ret = 1;
         break;
+    default:
+        fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
+        ret = -1;
+        break;
     }
 
     return ret;
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 5caa07c..849b404 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -307,6 +307,10 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
         dprintf("handle halt\n");
         ret = kvmppc_handle_halt(env);
         break;
+    default:
+        fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
+        ret = -1;
+        break;
     }
 
     return ret;
commit 646042e1aba31f377892e48f6145fbc8487d4481
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date:   Fri Jan 21 21:48:05 2011 +0100

    kvm: x86: Swallow KVM_EXIT_SET_TPR
    
    This exit only triggers activity in the common exit path, but we should
    accept it in order to be able to detect unknown exit types.
    
    Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index fda07d2..0aeb079 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1534,6 +1534,9 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
         DPRINTF("handle_hlt\n");
         ret = kvm_handle_halt(env);
         break;
+    case KVM_EXIT_SET_TPR:
+        ret = 1;
+        break;
     }
 
     return ret;
commit 225d02cd1a34d5d87e8acefbf8e244a5d12f5f8c
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Sun Jan 23 04:44:51 2011 +0100

    Avoid deadlock whith iothread and icount
    
    When using the iothread together with icount, make sure the
    qemu_icount counter makes forward progress when the vcpu is
    idle to avoid deadlocks.
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/qemu-timer.c b/qemu-timer.c
index 95814af..db1ec49 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -110,7 +110,6 @@ static int64_t cpu_get_clock(void)
     }
 }
 
-#ifndef CONFIG_IOTHREAD
 static int64_t qemu_icount_delta(void)
 {
     if (!use_icount) {
@@ -124,7 +123,6 @@ static int64_t qemu_icount_delta(void)
         return cpu_get_icount() - cpu_get_clock();
     }
 }
-#endif
 
 /* enable cpu_get_ticks() */
 void cpu_enable_ticks(void)
@@ -1077,9 +1075,17 @@ void quit_timers(void)
 
 int qemu_calculate_timeout(void)
 {
-#ifndef CONFIG_IOTHREAD
     int timeout;
 
+#ifdef CONFIG_IOTHREAD
+    /* When using icount, making forward progress with qemu_icount when the
+       guest CPU is idle is critical. We only use the static io-thread timeout
+       for non icount runs.  */
+    if (!use_icount) {
+        return 1000;
+    }
+#endif
+
     if (!vm_running)
         timeout = 5000;
     else {
@@ -1110,8 +1116,5 @@ int qemu_calculate_timeout(void)
     }
 
     return timeout;
-#else /* CONFIG_IOTHREAD */
-    return 1000;
-#endif
 }
 
commit 5d0bb8239d84292380d0024acd0d510cc957dae0
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Sun Jan 23 03:52:20 2011 +0100

    microblaze: cleanup helper_addkc
    
    Remove unused addition and rename to helper_carry.
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index 9c2a1e4..1696b88 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -2,7 +2,7 @@
 
 DEF_HELPER_1(raise_exception, void, i32)
 DEF_HELPER_0(debug, void)
-DEF_HELPER_FLAGS_3(addkc, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_3(carry, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
 DEF_HELPER_2(cmp, i32, i32, i32)
 DEF_HELPER_2(cmpu, i32, i32, i32)
 
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 59e4674..d75a53c 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -128,12 +128,9 @@ uint32_t helper_cmpu(uint32_t a, uint32_t b)
     return t;
 }
 
-uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t cf)
+uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf)
 {
-    uint32_t d, ncf;
-
-    d = a + b + cf;
-
+    uint32_t ncf;
     ncf = compute_carry(a, b, cf);
     return ncf;
 }
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 0c5edc3..2207431 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -232,13 +232,13 @@ static void dec_add(DisasContext *dc)
 
     if (dc->rd) {
         TCGv ncf = tcg_temp_new();
-        gen_helper_addkc(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
+        gen_helper_carry(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
         tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
         tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
         write_carry(dc, ncf);
         tcg_temp_free(ncf);
     } else {
-        gen_helper_addkc(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
+        gen_helper_carry(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
         write_carry(dc, cf);
     }
     tcg_temp_free(cf);
@@ -302,13 +302,13 @@ static void dec_sub(DisasContext *dc)
 
     if (dc->rd) {
         TCGv ncf = tcg_temp_new();
-        gen_helper_addkc(ncf, na, *(dec_alu_op_b(dc)), cf);
+        gen_helper_carry(ncf, na, *(dec_alu_op_b(dc)), cf);
         tcg_gen_add_tl(cpu_R[dc->rd], na, *(dec_alu_op_b(dc)));
         tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
         write_carry(dc, ncf);
         tcg_temp_free(ncf);
     } else {
-        gen_helper_addkc(cf, na, *(dec_alu_op_b(dc)), cf);
+        gen_helper_carry(cf, na, *(dec_alu_op_b(dc)), cf);
         write_carry(dc, cf);
     }
     tcg_temp_free(cf);
commit e0a42ebc0831e3ae18e965cc202b5d6649cc38f2
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Sat Jan 22 12:39:16 2011 +0100

    microblaze: Improve subkc
    
    Move code from the helper into the translator. The remaining
    helper parts can reuse helper_addkc, making it possible to
    remove helper_subkc entirely.
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index 4871406..9c2a1e4 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -3,7 +3,6 @@
 DEF_HELPER_1(raise_exception, void, i32)
 DEF_HELPER_0(debug, void)
 DEF_HELPER_FLAGS_3(addkc, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
-DEF_HELPER_4(subkc, i32, i32, i32, i32, i32)
 DEF_HELPER_2(cmp, i32, i32, i32)
 DEF_HELPER_2(cmpu, i32, i32, i32)
 
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index eb5a8b7..59e4674 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -138,28 +138,6 @@ uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t cf)
     return ncf;
 }
 
-uint32_t helper_subkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
-{
-    uint32_t d, cf = 1, ncf;
-
-    if (c)
-        cf = env->sregs[SR_MSR] >> 31; 
-    assert(cf == 0 || cf == 1);
-    d = b + ~a + cf;
-
-    if (!k) {
-        ncf = compute_carry(b, ~a, cf);
-        assert(ncf == 0 || ncf == 1);
-        if (ncf)
-            env->sregs[SR_MSR] |= MSR_C | MSR_CC;
-        else
-            env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
-    }
-    D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
-               d, a, b, cf, ncf, k, c));
-    return d;
-}
-
 static inline int div_prepare(uint32_t a, uint32_t b)
 {
     if (b == 0) {
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 264395b..0c5edc3 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -247,6 +247,7 @@ static void dec_add(DisasContext *dc)
 static void dec_sub(DisasContext *dc)
 {
     unsigned int u, cmp, k, c;
+    TCGv cf, na;
 
     u = dc->imm & 2;
     k = dc->opcode & 4;
@@ -261,24 +262,57 @@ static void dec_sub(DisasContext *dc)
             else
                 gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
         }
-    } else {
-        LOG_DIS("sub%s%s r%d, r%d r%d\n",
-                 k ? "k" : "",  c ? "c" : "", dc->rd, dc->ra, dc->rb);
+        return;
+    }
 
-        if (!k || c) {
-            TCGv t;
-            t = tcg_temp_new();
-            if (dc->rd)
-                gen_helper_subkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
-                                 tcg_const_tl(k), tcg_const_tl(c));
-            else
-                gen_helper_subkc(t, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
-                                 tcg_const_tl(k), tcg_const_tl(c));
-            tcg_temp_free(t);
-        }
-        else if (dc->rd)
+    LOG_DIS("sub%s%s r%d, r%d r%d\n",
+             k ? "k" : "",  c ? "c" : "", dc->rd, dc->ra, dc->rb);
+
+    /* Take care of the easy cases first.  */
+    if (k) {
+        /* k - keep carry, no need to update MSR.  */
+        /* If rd == r0, it's a nop.  */
+        if (dc->rd) {
             tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
+
+            if (c) {
+                /* c - Add carry into the result.  */
+                cf = tcg_temp_new();
+
+                read_carry(dc, cf);
+                tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
+                tcg_temp_free(cf);
+            }
+        }
+        return;
+    }
+
+    /* From now on, we can assume k is zero.  So we need to update MSR.  */
+    /* Extract carry. And complement a into na.  */
+    cf = tcg_temp_new();
+    na = tcg_temp_new();
+    if (c) {
+        read_carry(dc, cf);
+    } else {
+        tcg_gen_movi_tl(cf, 1);
+    }
+
+    /* d = b + ~a + c. carry defaults to 1.  */
+    tcg_gen_not_tl(na, cpu_R[dc->ra]);
+
+    if (dc->rd) {
+        TCGv ncf = tcg_temp_new();
+        gen_helper_addkc(ncf, na, *(dec_alu_op_b(dc)), cf);
+        tcg_gen_add_tl(cpu_R[dc->rd], na, *(dec_alu_op_b(dc)));
+        tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
+        write_carry(dc, ncf);
+        tcg_temp_free(ncf);
+    } else {
+        gen_helper_addkc(cf, na, *(dec_alu_op_b(dc)), cf);
+        write_carry(dc, cf);
     }
+    tcg_temp_free(cf);
+    tcg_temp_free(na);
 }
 
 static void dec_pattern(DisasContext *dc)
commit 7e9e4330080f40a964cfed2b334b5e231e967792
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Sat Jan 22 12:35:48 2011 +0100

    microblaze: Fix 3rd addkc arg when rd is r0
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index d983c8b..264395b 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -238,8 +238,7 @@ static void dec_add(DisasContext *dc)
         write_carry(dc, ncf);
         tcg_temp_free(ncf);
     } else {
-        gen_helper_addkc(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
-                         tcg_const_tl(cf));
+        gen_helper_addkc(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
         write_carry(dc, cf);
     }
     tcg_temp_free(cf);
commit 40cbf5b7098981f66ef161e6ce7a9f6770537ea4
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Sat Jan 22 12:02:53 2011 +0100

    microblaze: Improve addkc
    
    * Optimize handling when carry is not updated.
    * Optimize handling for adds with nop semantics.
    * Move code from helper_addkc to the translator making
      helper_addkc PURE and CONST.
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index 11ad1b6..4871406 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -2,7 +2,7 @@
 
 DEF_HELPER_1(raise_exception, void, i32)
 DEF_HELPER_0(debug, void)
-DEF_HELPER_4(addkc, i32, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_3(addkc, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
 DEF_HELPER_4(subkc, i32, i32, i32, i32, i32)
 DEF_HELPER_2(cmp, i32, i32, i32)
 DEF_HELPER_2(cmpu, i32, i32, i32)
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 97461ae..eb5a8b7 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -128,26 +128,14 @@ uint32_t helper_cmpu(uint32_t a, uint32_t b)
     return t;
 }
 
-uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
+uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t cf)
 {
-    uint32_t d, cf = 0, ncf;
+    uint32_t d, ncf;
 
-    if (c)
-        cf = env->sregs[SR_MSR] >> 31;
-    assert(cf == 0 || cf == 1);
     d = a + b + cf;
 
-    if (!k) {
-        ncf = compute_carry(a, b, cf);
-        assert(ncf == 0 || ncf == 1);
-        if (ncf)
-            env->sregs[SR_MSR] |= MSR_C | MSR_CC;
-        else
-            env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
-    }
-    D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
-               d, a, b, cf, ncf, k, c));
-    return d;
+    ncf = compute_carry(a, b, cf);
+    return ncf;
 }
 
 uint32_t helper_subkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index dd2865c..d983c8b 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -193,6 +193,7 @@ static inline TCGv *dec_alu_op_b(DisasContext *dc)
 static void dec_add(DisasContext *dc)
 {
     unsigned int k, c;
+    TCGv cf;
 
     k = dc->opcode & 4;
     c = dc->opcode & 2;
@@ -201,17 +202,47 @@ static void dec_add(DisasContext *dc)
             dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "",
             dc->rd, dc->ra, dc->rb);
 
-    if (k && !c && dc->rd)
+    /* Take care of the easy cases first.  */
+    if (k) {
+        /* k - keep carry, no need to update MSR.  */
+        /* If rd == r0, it's a nop.  */
+        if (dc->rd) {
+            tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
+
+            if (c) {
+                /* c - Add carry into the result.  */
+                cf = tcg_temp_new();
+
+                read_carry(dc, cf);
+                tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
+                tcg_temp_free(cf);
+            }
+        }
+        return;
+    }
+
+    /* From now on, we can assume k is zero.  So we need to update MSR.  */
+    /* Extract carry.  */
+    cf = tcg_temp_new();
+    if (c) {
+        read_carry(dc, cf);
+    } else {
+        tcg_gen_movi_tl(cf, 0);
+    }
+
+    if (dc->rd) {
+        TCGv ncf = tcg_temp_new();
+        gen_helper_addkc(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
         tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
-    else if (dc->rd)
-        gen_helper_addkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
-                         tcg_const_tl(k), tcg_const_tl(c));
-    else {
-        TCGv d = tcg_temp_new();
-        gen_helper_addkc(d, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
-                         tcg_const_tl(k), tcg_const_tl(c));
-        tcg_temp_free(d);
+        tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
+        write_carry(dc, ncf);
+        tcg_temp_free(ncf);
+    } else {
+        gen_helper_addkc(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
+                         tcg_const_tl(cf));
+        write_carry(dc, cf);
     }
+    tcg_temp_free(cf);
 }
 
 static void dec_sub(DisasContext *dc)
commit 2accfb5fa6f097845915973a06824bc72fb26e94
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Sat Jan 22 12:00:12 2011 +0100

    microblaze: Remove debug leftovers.
    
    No functional changes.
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index dcc867e..dd2865c 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -884,7 +884,6 @@ static void dec_load(DisasContext *dc)
                 tcg_gen_sub_tl(low, tcg_const_tl(3), low);
                 tcg_gen_andi_tl(t, t, ~3);
                 tcg_gen_or_tl(t, t, low);
-                tcg_gen_mov_tl(env_debug, low);
                 tcg_gen_mov_tl(env_imm, t);
                 tcg_temp_free(low);
                 break;
@@ -1010,7 +1009,6 @@ static void dec_store(DisasContext *dc)
                 tcg_gen_sub_tl(low, tcg_const_tl(3), low);
                 tcg_gen_andi_tl(t, t, ~3);
                 tcg_gen_or_tl(t, t, low);
-                tcg_gen_mov_tl(env_debug, low);
                 tcg_gen_mov_tl(env_imm, t);
                 tcg_temp_free(low);
                 break;
commit ee8b246f825efa0aa299fc33b8dcc8a8a862cc53
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Sat Jan 22 11:57:19 2011 +0100

    microblaze: Reorganize for future patches
    
    No functional changes.
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 4b6ae06..dcc867e 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -153,6 +153,23 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
     }
 }
 
+static void read_carry(DisasContext *dc, TCGv d)
+{
+    tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31);
+}
+
+static void write_carry(DisasContext *dc, TCGv v)
+{
+    TCGv t0 = tcg_temp_new();
+    tcg_gen_shli_tl(t0, v, 31);
+    tcg_gen_sari_tl(t0, t0, 31);
+    tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC));
+    tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR],
+                    ~(MSR_C | MSR_CC));
+    tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0);
+    tcg_temp_free(t0);
+}
+
 /* True if ALU operand b is a small immediate that may deserve
    faster treatment.  */
 static inline int dec_alu_op_b_is_small_imm(DisasContext *dc)
@@ -337,25 +354,6 @@ static void dec_xor(DisasContext *dc)
         tcg_gen_xor_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
 }
 
-static void read_carry(DisasContext *dc, TCGv d)
-{
-    tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31);
-}
-
-static void write_carry(DisasContext *dc, TCGv v)
-{
-    TCGv t0 = tcg_temp_new();
-    tcg_gen_shli_tl(t0, v, 31);
-    tcg_gen_sari_tl(t0, t0, 31);
-    tcg_gen_mov_tl(env_debug, t0);
-    tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC));
-    tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR],
-                    ~(MSR_C | MSR_CC));
-    tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0);
-    tcg_temp_free(t0);
-}
-
-
 static inline void msr_read(DisasContext *dc, TCGv d)
 {
     tcg_gen_mov_tl(d, cpu_SR[SR_MSR]);
commit 6f32e3d09d990fd50008756fcb446b55e0c0af79
Merge: f447f8c... 0f46d15...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Fri Jan 21 20:34:47 2011 -0200

    Merge branch 'upstream-merge'
    
    * upstream-merge: (221 commits)
      sm501: fix screen redraw
      checkpatch: adjust to QEMUisms
      Add checkpatch.pl from Linux kernel
      Add scripts directory
      gt64xxx: set isa_mem_base during registration
      hw/pl190.c: Fix writing of default vector address
      target-ppc: fix wrong NaN tests
      target-ppc: fix sNaN propagation
      pci: use qemu_malloc() in pcibus_get_dev_path()
      msix: simplify write config
      msi: simplify write config a bit.
      pci: deassert intx on reset.
      pxa2xx_lcd: restore updating of display
      pxa2xx: fix vmstate_pxa2xx_i2c
      scoop: fix access to registers from second instance
      mainstone: fix name of the allocated memory for roms
      add bepo (french dvorak) keyboard layout
      stc91c111: Implement save/restore
      pl080: Implement save/restore
      pl110: Implement save/restore
      ...
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

commit 0f46d152542a7186a01420b2bb22679a4dffa9f7
Merge: adb7637... b947c12...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Fri Jan 21 20:33:00 2011 -0200

    Merge commit 'b947c12c0bb217fe09968e652873e0d22b269d68' into upstream-merge
    
    * commit 'b947c12c0bb217fe09968e652873e0d22b269d68': (130 commits)
      sm501: fix screen redraw
      checkpatch: adjust to QEMUisms
      Add checkpatch.pl from Linux kernel
      Add scripts directory
      gt64xxx: set isa_mem_base during registration
      hw/pl190.c: Fix writing of default vector address
      target-ppc: fix wrong NaN tests
      target-ppc: fix sNaN propagation
      pci: use qemu_malloc() in pcibus_get_dev_path()
      msix: simplify write config
      msi: simplify write config a bit.
      pci: deassert intx on reset.
      pxa2xx_lcd: restore updating of display
      pxa2xx: fix vmstate_pxa2xx_i2c
      scoop: fix access to registers from second instance
      mainstone: fix name of the allocated memory for roms
      add bepo (french dvorak) keyboard layout
      stc91c111: Implement save/restore
      pl080: Implement save/restore
      pl110: Implement save/restore
      ...
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --cc configure
index f49a826,210670c..292cde7
--- a/configure
+++ b/configure
@@@ -3372,31 -3228,24 +3366,24 @@@ echo "QEMU_INCLUDES+=$includes" >> $con
  
  done # for target in $targets
  
- # build tree in object directory if source path is different from current one
- if test "$source_path_used" = "yes" ; then
-     DIRS="tests tests/cris slirp audio block net pc-bios/optionrom"
-     DIRS="$DIRS roms/seabios roms/vgabios"
-     DIRS="$DIRS fsdev ui"
-     FILES="Makefile tests/Makefile"
-     FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
-     FILES="$FILES tests/test-mmap.c"
-     FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
-     FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
-     for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
-         FILES="$FILES pc-bios/`basename $bios_file`"
-     done
-     for dir in $DIRS ; do
-             mkdir -p $dir
-     done
-     # remove the link and recreate it, as not all "ln -sf" overwrite the link
-     for f in $FILES ; do
-         rm -f $f
-         ln -s $source_path/$f $f
-     done
- fi
+ # build tree in object directory in case the source is not in the current directory
+ DIRS="tests tests/cris slirp audio block net pc-bios/optionrom"
+ DIRS="$DIRS roms/seabios roms/vgabios"
+ DIRS="$DIRS fsdev ui"
+ FILES="Makefile tests/Makefile"
+ FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
+ FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
+ FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
+ for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
+     FILES="$FILES pc-bios/`basename $bios_file`"
+ done
+ mkdir -p $DIRS
+ for f in $FILES ; do
+     test -e $f || symlink $source_path/$f $f
+ done
  
  # temporary config to build submodules
 -for rom in seabios vgabios ; do
 +for rom in seabios vgabios; do
      config_mak=roms/$rom/config.mak
      echo "# Automatically generated by configure - do not modify" > $config_mak
      echo "SRC_PATH=$source_path/roms/$rom" >> $config_mak
commit 5823947f9f1e55fb6599c9ed769ce25cdec38355
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date:   Fri Jan 21 23:12:42 2011 +0100

    ppc: Correct BookE tlb reads
    
    Call the tlb read helper (and not the write helper) for tlb
    reads.
    
    Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 74e06d7..89413c5 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -5874,7 +5874,7 @@ static void gen_tlbre_440(DisasContext *ctx)
     case 2:
         {
             TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
-            gen_helper_440_tlbwe(t0, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
+            gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], t0, cpu_gpr[rA(ctx->opcode)]);
             tcg_temp_free_i32(t0);
         }
         break;
commit adb76372d9b324468da0bf9ca707da94c0adf209
Merge: 966eb0d... 668643b...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Fri Jan 21 18:12:11 2011 -0200

    Merge commit '668643b025dcff72b9b18adb5df794be9e9be5dc' into upstream-merge
    
    * commit '668643b025dcff72b9b18adb5df794be9e9be5dc':
      acpi_piix4: expose no_hotplug attribute via i/o port
      document QEMU<->ACPIBIOS PCI hotplug interface
      virtio-serial-bus: bump up control vq size to 32
      ioeventfd: error handling cleanup
      docs: Document virtio PCI -device ioeventfd=on|off
      virtio-pci: Use ioeventfd for virtqueue notify
    
    Conflicts:
    	hw/acpi_piix4.c
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --cc hw/acpi_piix4.c
index d041e13,5bbc2b5..dde8646
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@@ -35,11 -35,10 +35,12 @@@
  #define ACPI_DBG_IO_ADDR  0xb044
  
  #define GPE_BASE 0xafe0
 +#define PROC_BASE 0xaf00
  #define PCI_BASE 0xae00
  #define PCI_EJ_BASE 0xae08
+ #define PCI_RMV_BASE 0xae0c
  
 +#define PIIX4_CPU_HOTPLUG_STATUS 4
  #define PIIX4_PCI_HOTPLUG_STATUS 2
  
  struct gpe_regs {
@@@ -596,8 -598,18 +618,20 @@@ static void pciej_write(void *opaque, u
      PIIX4_DPRINTF("pciej write %x <== %d\n", addr, val);
  }
  
+ static uint32_t pcirmv_read(void *opaque, uint32_t addr)
+ {
+     PIIX4PMState *s = opaque;
+ 
+     return s->pci0_hotplug_enable;
+ }
+ 
+ static void pcirmv_write(void *opaque, uint32_t addr, uint32_t val)
+ {
+     return;
+ }
+ 
 +extern const char *global_cpu_model;
 +
  static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
                                  PCIHotplugState state);
  
commit 966eb0dfc6c080e9b870615baa27925414ec7a51
Merge: 777c5d1... d2f2b8a...
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date:   Fri Jan 21 17:41:31 2011 -0200

    Merge commit 'd2f2b8a740c82319f9eea51ebed50815fbc3da3e' into upstream-merge
    
    * commit 'd2f2b8a740c82319f9eea51ebed50815fbc3da3e':
      kvm: test for ioeventfd support on old kernels
      virtio: move vmstate change tracking to core
      virtio-pci: Rename bugs field to flags
      qxl: tag as not hotpluggable
      vga: tag as not hotplugable.
      piix: tag as not hotpluggable.
      pci: allow devices being tagged as not hotpluggable.
      rtl8139: Use subsection to restrict migration after hotplug
      qdev: Track runtime machine modifications
    
    Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>

diff --cc qemu-kvm.c
index 471306b,0000000..76731fe
mode 100644,000000..100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@@ -1,1781 -1,0 +1,1783 @@@
 +/*
 + * qemu/kvm integration
 + *
 + * Copyright (C) 2006-2008 Qumranet Technologies
 + *
 + * Licensed under the terms of the GNU GPL version 2 or higher.
 + */
 +#include "config.h"
 +#include "config-host.h"
 +
 +#include <assert.h>
 +#include <string.h>
 +#include "hw/hw.h"
 +#include "sysemu.h"
 +#include "qemu-common.h"
 +#include "console.h"
 +#include "block.h"
 +#include "compatfd.h"
 +#include "gdbstub.h"
 +#include "monitor.h"
 +
 +#include "qemu-kvm.h"
 +#include "libkvm.h"
 +
 +#include <pthread.h>
 +#include <sys/utsname.h>
 +#include <sys/syscall.h>
 +#include <sys/mman.h>
 +#include <sys/ioctl.h>
 +#include "compatfd.h"
 +#include <sys/prctl.h>
 +
 +#define false 0
 +#define true 1
 +
 +#ifndef PR_MCE_KILL
 +#define PR_MCE_KILL 33
 +#endif
 +
 +#ifndef BUS_MCEERR_AR
 +#define BUS_MCEERR_AR 4
 +#endif
 +#ifndef BUS_MCEERR_AO
 +#define BUS_MCEERR_AO 5
 +#endif
 +
 +#define EXPECTED_KVM_API_VERSION 12
 +
 +#if EXPECTED_KVM_API_VERSION != KVM_API_VERSION
 +#error libkvm: userspace and kernel version mismatch
 +#endif
 +
 +int kvm_irqchip = 1;
 +int kvm_pit = 1;
 +int kvm_pit_reinject = 1;
 +int kvm_nested = 0;
 +
 +
 +KVMState *kvm_state;
 +kvm_context_t kvm_context;
 +
 +pthread_mutex_t qemu_mutex = PTHREAD_MUTEX_INITIALIZER;
 +pthread_cond_t qemu_vcpu_cond = PTHREAD_COND_INITIALIZER;
 +pthread_cond_t qemu_system_cond = PTHREAD_COND_INITIALIZER;
 +pthread_cond_t qemu_pause_cond = PTHREAD_COND_INITIALIZER;
 +pthread_cond_t qemu_work_cond = PTHREAD_COND_INITIALIZER;
 +__thread CPUState *current_env;
 +
 +static int qemu_system_ready;
 +
 +#define SIG_IPI (SIGRTMIN+4)
 +
 +pthread_t io_thread;
 +static int io_thread_sigfd = -1;
 +
 +static CPUState *kvm_debug_cpu_requested;
 +
 +#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
 +/* The list of ioperm_data */
 +static QLIST_HEAD(, ioperm_data) ioperm_head;
 +#endif
 +
 +#define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1))
 +
 +int kvm_abi = EXPECTED_KVM_API_VERSION;
 +int kvm_page_size;
 +
 +#ifdef KVM_CAP_SET_GUEST_DEBUG
 +static int kvm_debug(CPUState *env,
 +                     struct kvm_debug_exit_arch *arch_info)
 +{
 +    int handle = kvm_arch_debug(arch_info);
 +
 +    if (handle) {
 +        kvm_debug_cpu_requested = env;
 +        env->stopped = 1;
 +    }
 +    return handle;
 +}
 +#endif
 +
 +static int handle_unhandled(uint64_t reason)
 +{
 +    fprintf(stderr, "kvm: unhandled exit %" PRIx64 "\n", reason);
 +    return -EINVAL;
 +}
 +
 +#define VMX_INVALID_GUEST_STATE 0x80000021
 +
 +static int handle_failed_vmentry(uint64_t reason)
 +{
 +    fprintf(stderr, "kvm: vm entry failed with error 0x%" PRIx64 "\n\n", reason);
 +
 +    /* Perhaps we will need to check if this machine is intel since exit reason 0x21
 +       has a different interpretation on SVM */
 +    if (reason == VMX_INVALID_GUEST_STATE) {
 +        fprintf(stderr, "If you're runnning a guest on an Intel machine without\n");
 +        fprintf(stderr, "unrestricted mode support, the failure can be most likely\n");
 +        fprintf(stderr, "due to the guest entering an invalid state for Intel VT.\n");
 +        fprintf(stderr, "For example, the guest maybe running in big real mode\n");
 +        fprintf(stderr, "which is not supported on less recent Intel processors.\n\n");
 +    }
 +
 +    return -EINVAL;
 +}
 +
 +static inline void set_gsi(kvm_context_t kvm, unsigned int gsi)
 +{
 +    uint32_t *bitmap = kvm->used_gsi_bitmap;
 +
 +    if (gsi < kvm->max_gsi)
 +        bitmap[gsi / 32] |= 1U << (gsi % 32);
 +    else
 +        DPRINTF("Invalid GSI %u\n", gsi);
 +}
 +
 +static inline void clear_gsi(kvm_context_t kvm, unsigned int gsi)
 +{
 +    uint32_t *bitmap = kvm->used_gsi_bitmap;
 +
 +    if (gsi < kvm->max_gsi)
 +        bitmap[gsi / 32] &= ~(1U << (gsi % 32));
 +    else
 +        DPRINTF("Invalid GSI %u\n", gsi);
 +}
 +
 +static int kvm_create_context(void);
 +
 +int kvm_init(int smp_cpus)
 +{
 +    int fd;
 +    int r, gsi_count;
 +
 +
 +    fd = open("/dev/kvm", O_RDWR);
 +    if (fd == -1) {
 +        perror("open /dev/kvm");
 +        return -1;
 +    }
 +    r = ioctl(fd, KVM_GET_API_VERSION, 0);
 +    if (r == -1) {
 +        fprintf(stderr,
 +                "kvm kernel version too old: "
 +                "KVM_GET_API_VERSION ioctl not supported\n");
 +        goto out_close;
 +    }
 +    if (r < EXPECTED_KVM_API_VERSION) {
 +        fprintf(stderr, "kvm kernel version too old: "
 +                "We expect API version %d or newer, but got "
 +                "version %d\n", EXPECTED_KVM_API_VERSION, r);
 +        goto out_close;
 +    }
 +    if (r > EXPECTED_KVM_API_VERSION) {
 +        fprintf(stderr, "kvm userspace version too old\n");
 +        goto out_close;
 +    }
 +    kvm_abi = r;
 +    kvm_page_size = getpagesize();
 +    kvm_state = qemu_mallocz(sizeof(*kvm_state));
 +    kvm_context = &kvm_state->kvm_context;
 +
 +    kvm_state->fd = fd;
 +    kvm_state->vmfd = -1;
 +    kvm_context->opaque = cpu_single_env;
 +    kvm_context->dirty_pages_log_all = 0;
 +    kvm_context->no_irqchip_creation = 0;
 +    kvm_context->no_pit_creation = 0;
 +
 +#ifdef KVM_CAP_SET_GUEST_DEBUG
 +    QTAILQ_INIT(&kvm_state->kvm_sw_breakpoints);
 +#endif
 +
 +    gsi_count = kvm_get_gsi_count(kvm_context);
 +    if (gsi_count > 0) {
 +        int gsi_bits, i;
 +
 +        /* Round up so we can search ints using ffs */
 +        gsi_bits = ALIGN(gsi_count, 32);
 +        kvm_context->used_gsi_bitmap = qemu_mallocz(gsi_bits / 8);
 +        kvm_context->max_gsi = gsi_bits;
 +
 +        /* Mark any over-allocated bits as already in use */
 +        for (i = gsi_count; i < gsi_bits; i++) {
 +            set_gsi(kvm_context, i);
 +        }
 +    }
 +
 +    kvm_cpu_register_phys_memory_client();
 +
 +    pthread_mutex_lock(&qemu_mutex);
 +    return kvm_create_context();
 +
 +  out_close:
 +    close(fd);
 +    return -1;
 +}
 +
 +static void kvm_finalize(KVMState *s)
 +{
 +    /* FIXME
 +       if (kvm->vcpu_fd[0] != -1)
 +           close(kvm->vcpu_fd[0]);
 +       if (kvm->vm_fd != -1)
 +           close(kvm->vm_fd);
 +     */
 +    close(s->fd);
 +    free(s);
 +}
 +
 +void kvm_disable_irqchip_creation(kvm_context_t kvm)
 +{
 +    kvm->no_irqchip_creation = 1;
 +}
 +
 +void kvm_disable_pit_creation(kvm_context_t kvm)
 +{
 +    kvm->no_pit_creation = 1;
 +}
 +
 +static void kvm_reset_vcpu(void *opaque)
 +{
 +    CPUState *env = opaque;
 +
 +    kvm_arch_cpu_reset(env);
 +}
 +
 +static void kvm_create_vcpu(CPUState *env, int id)
 +{
 +    long mmap_size;
 +    int r;
 +    KVMState *s = kvm_state;
 +
 +    r = kvm_vm_ioctl(kvm_state, KVM_CREATE_VCPU, id);
 +    if (r < 0) {
 +        fprintf(stderr, "kvm_create_vcpu: %m\n");
 +        fprintf(stderr, "Failed to create vCPU. Check the -smp parameter.\n");
 +        goto err;
 +    }
 +
 +    env->kvm_fd = r;
 +    env->kvm_state = kvm_state;
 +
 +    mmap_size = kvm_ioctl(kvm_state, KVM_GET_VCPU_MMAP_SIZE, 0);
 +    if (mmap_size < 0) {
 +        fprintf(stderr, "get vcpu mmap size: %m\n");
 +        goto err_fd;
 +    }
 +    env->kvm_run =
 +        mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, env->kvm_fd,
 +             0);
 +    if (env->kvm_run == MAP_FAILED) {
 +        fprintf(stderr, "mmap vcpu area: %m\n");
 +        goto err_fd;
 +    }
 +
 +#ifdef KVM_CAP_COALESCED_MMIO
 +    if (s->coalesced_mmio && !s->coalesced_mmio_ring)
 +        s->coalesced_mmio_ring = (void *) env->kvm_run +
 +               s->coalesced_mmio * PAGE_SIZE;
 +#endif
 +
 +    r = kvm_arch_init_vcpu(env);
 +    if (r == 0) {
 +        qemu_register_reset(kvm_reset_vcpu, env);
 +    }
 +
 +    return;
 +  err_fd:
 +    close(env->kvm_fd);
 +  err:
 +    /* We're no good with semi-broken states. */
 +    abort();
 +}
 +
 +static int kvm_set_boot_vcpu_id(kvm_context_t kvm, uint32_t id)
 +{
 +#ifdef KVM_CAP_SET_BOOT_CPU_ID
 +    int r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_SET_BOOT_CPU_ID);
 +    if (r > 0) {
 +        return kvm_vm_ioctl(kvm_state, KVM_SET_BOOT_CPU_ID, id);
 +    }
 +    return -ENOSYS;
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_create_vm(kvm_context_t kvm)
 +{
 +    int fd;
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    kvm->irq_routes = qemu_mallocz(sizeof(*kvm->irq_routes));
 +    kvm->nr_allocated_irq_routes = 0;
 +#endif
 +
 +    fd = kvm_ioctl(kvm_state, KVM_CREATE_VM, 0);
 +    if (fd < 0) {
 +        fprintf(stderr, "kvm_create_vm: %m\n");
 +        return -1;
 +    }
 +    kvm_state->vmfd = fd;
 +    return 0;
 +}
 +
 +static int kvm_create_default_phys_mem(kvm_context_t kvm,
 +                                       unsigned long phys_mem_bytes,
 +                                       void **vm_mem)
 +{
 +#ifdef KVM_CAP_USER_MEMORY
 +    int r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_USER_MEMORY);
 +    if (r > 0)
 +        return 0;
 +    fprintf(stderr,
 +            "Hypervisor too old: KVM_CAP_USER_MEMORY extension not supported\n");
 +#else
 +#error Hypervisor too old: KVM_CAP_USER_MEMORY extension not supported
 +#endif
 +    return -1;
 +}
 +
 +void kvm_create_irqchip(kvm_context_t kvm)
 +{
 +    int r;
 +
 +    kvm->irqchip_in_kernel = 0;
 +#ifdef KVM_CAP_IRQCHIP
 +    if (!kvm->no_irqchip_creation) {
 +        r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_IRQCHIP);
 +        if (r > 0) {            /* kernel irqchip supported */
 +            r = kvm_vm_ioctl(kvm_state, KVM_CREATE_IRQCHIP);
 +            if (r >= 0) {
 +                kvm->irqchip_inject_ioctl = KVM_IRQ_LINE;
 +#if defined(KVM_CAP_IRQ_INJECT_STATUS) && defined(KVM_IRQ_LINE_STATUS)
 +                r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION,
 +                              KVM_CAP_IRQ_INJECT_STATUS);
 +                if (r > 0) {
 +                    kvm->irqchip_inject_ioctl = KVM_IRQ_LINE_STATUS;
 +                }
 +#endif
 +                kvm->irqchip_in_kernel = 1;
 +            } else
 +                fprintf(stderr, "Create kernel PIC irqchip failed\n");
 +        }
 +    }
 +#endif
 +    kvm_state->irqchip_in_kernel = kvm->irqchip_in_kernel;
 +}
 +
 +int kvm_create(kvm_context_t kvm, unsigned long phys_mem_bytes, void **vm_mem)
 +{
 +    int r, i;
 +
 +    r = kvm_create_vm(kvm);
 +    if (r < 0) {
 +        return r;
 +    }
 +    r = kvm_arch_create(kvm, phys_mem_bytes, vm_mem);
 +    if (r < 0) {
 +        return r;
 +    }
 +    for (i = 0; i < ARRAY_SIZE(kvm_state->slots); i++) {
 +        kvm_state->slots[i].slot = i;
 +    }
 +
 +    r = kvm_create_default_phys_mem(kvm, phys_mem_bytes, vm_mem);
 +    if (r < 0) {
 +        return r;
 +    }
 +
 +    kvm_create_irqchip(kvm);
 +
 +    return 0;
 +}
 +
 +#ifdef KVM_CAP_IRQCHIP
 +
 +int kvm_set_irq_level(kvm_context_t kvm, int irq, int level, int *status)
 +{
 +    struct kvm_irq_level event;
 +    int r;
 +
 +    if (!kvm->irqchip_in_kernel) {
 +        return 0;
 +    }
 +    event.level = level;
 +    event.irq = irq;
 +    r = kvm_vm_ioctl(kvm_state, kvm->irqchip_inject_ioctl, &event);
 +    if (r < 0) {
 +        perror("kvm_set_irq_level");
 +    }
 +
 +    if (status) {
 +#ifdef KVM_CAP_IRQ_INJECT_STATUS
 +        *status =
 +            (kvm->irqchip_inject_ioctl == KVM_IRQ_LINE) ? 1 : event.status;
 +#else
 +        *status = 1;
 +#endif
 +    }
 +
 +    return 1;
 +}
 +
 +int kvm_get_irqchip(kvm_context_t kvm, struct kvm_irqchip *chip)
 +{
 +    int r;
 +
 +    if (!kvm->irqchip_in_kernel) {
 +        return 0;
 +    }
 +    r = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, chip);
 +    if (r < 0) {
 +        perror("kvm_get_irqchip\n");
 +    }
 +    return r;
 +}
 +
 +int kvm_set_irqchip(kvm_context_t kvm, struct kvm_irqchip *chip)
 +{
 +    int r;
 +
 +    if (!kvm->irqchip_in_kernel) {
 +        return 0;
 +    }
 +    r = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip);
 +    if (r < 0) {
 +        perror("kvm_set_irqchip\n");
 +    }
 +    return r;
 +}
 +
 +#endif
 +
 +static int handle_debug(CPUState *env)
 +{
 +#ifdef KVM_CAP_SET_GUEST_DEBUG
 +    struct kvm_run *run = env->kvm_run;
 +
 +    return kvm_debug(env, &run->debug.arch);
 +#else
 +    return 0;
 +#endif
 +}
 +
 +int kvm_get_regs(CPUState *env, struct kvm_regs *regs)
 +{
 +    return kvm_vcpu_ioctl(env, KVM_GET_REGS, regs);
 +}
 +
 +int kvm_set_regs(CPUState *env, struct kvm_regs *regs)
 +{
 +    return kvm_vcpu_ioctl(env, KVM_SET_REGS, regs);
 +}
 +
 +#ifdef KVM_CAP_MP_STATE
 +int kvm_get_mpstate(CPUState *env, struct kvm_mp_state *mp_state)
 +{
 +    int r;
 +
 +    r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_MP_STATE);
 +    if (r > 0) {
 +        return kvm_vcpu_ioctl(env, KVM_GET_MP_STATE, mp_state);
 +    }
 +    return -ENOSYS;
 +}
 +
 +int kvm_set_mpstate(CPUState *env, struct kvm_mp_state *mp_state)
 +{
 +    int r;
 +
 +    r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_MP_STATE);
 +    if (r > 0) {
 +        return kvm_vcpu_ioctl(env, KVM_SET_MP_STATE, mp_state);
 +    }
 +    return -ENOSYS;
 +}
 +#endif
 +
 +static int handle_mmio(CPUState *env)
 +{
 +    unsigned long addr = env->kvm_run->mmio.phys_addr;
 +    struct kvm_run *kvm_run = env->kvm_run;
 +    void *data = kvm_run->mmio.data;
 +
 +    /* hack: Red Hat 7.1 generates these weird accesses. */
 +    if ((addr > 0xa0000 - 4 && addr <= 0xa0000) && kvm_run->mmio.len == 3) {
 +        return 0;
 +    }
 +
 +    cpu_physical_memory_rw(addr, data, kvm_run->mmio.len, kvm_run->mmio.is_write);
 +    return 0;
 +}
 +
 +int handle_io_window(kvm_context_t kvm)
 +{
 +    return 1;
 +}
 +
 +int handle_shutdown(kvm_context_t kvm, CPUState *env)
 +{
 +    /* stop the current vcpu from going back to guest mode */
 +    env->stopped = 1;
 +
 +    qemu_system_reset_request();
 +    return 1;
 +}
 +
 +static inline void push_nmi(kvm_context_t kvm)
 +{
 +#ifdef KVM_CAP_USER_NMI
 +    kvm_arch_push_nmi(kvm->opaque);
 +#endif                          /* KVM_CAP_USER_NMI */
 +}
 +
 +void post_kvm_run(kvm_context_t kvm, CPUState *env)
 +{
 +    pthread_mutex_lock(&qemu_mutex);
 +    kvm_arch_post_run(env, env->kvm_run);
 +    cpu_single_env = env;
 +}
 +
 +int pre_kvm_run(kvm_context_t kvm, CPUState *env)
 +{
 +    kvm_arch_pre_run(env, env->kvm_run);
 +
 +    pthread_mutex_unlock(&qemu_mutex);
 +    return 0;
 +}
 +
 +int kvm_is_ready_for_interrupt_injection(CPUState *env)
 +{
 +    return env->kvm_run->ready_for_interrupt_injection;
 +}
 +
 +int kvm_run(CPUState *env)
 +{
 +    int r;
 +    kvm_context_t kvm = &env->kvm_state->kvm_context;
 +    struct kvm_run *run = env->kvm_run;
 +    int fd = env->kvm_fd;
 +
 +  again:
 +    if (env->kvm_vcpu_dirty) {
 +        kvm_arch_load_regs(env, KVM_PUT_RUNTIME_STATE);
 +        env->kvm_vcpu_dirty = 0;
 +    }
 +    push_nmi(kvm);
 +#if !defined(__s390__)
 +    if (!kvm->irqchip_in_kernel) {
 +        run->request_interrupt_window = kvm_arch_try_push_interrupts(env);
 +    }
 +#endif
 +
 +    r = pre_kvm_run(kvm, env);
 +    if (r) {
 +        return r;
 +    }
 +    if (env->exit_request) {
 +        env->exit_request = 0;
 +        pthread_kill(env->kvm_cpu_state.thread, SIG_IPI);
 +    }
 +    r = ioctl(fd, KVM_RUN, 0);
 +
 +    if (r == -1 && errno != EINTR && errno != EAGAIN) {
 +        r = -errno;
 +        post_kvm_run(kvm, env);
 +        fprintf(stderr, "kvm_run: %s\n", strerror(-r));
 +        return r;
 +    }
 +
 +    post_kvm_run(kvm, env);
 +
 +    kvm_flush_coalesced_mmio_buffer();
 +
 +#if !defined(__s390__)
 +    if (r == -1) {
 +        r = handle_io_window(kvm);
 +        goto more;
 +    }
 +#endif
 +    if (1) {
 +        switch (run->exit_reason) {
 +        case KVM_EXIT_UNKNOWN:
 +            r = handle_unhandled(run->hw.hardware_exit_reason);
 +            break;
 +        case KVM_EXIT_FAIL_ENTRY:
 +            r = handle_failed_vmentry(run->fail_entry.hardware_entry_failure_reason);
 +            break;
 +        case KVM_EXIT_EXCEPTION:
 +            fprintf(stderr, "exception %d (%x)\n", run->ex.exception,
 +                    run->ex.error_code);
 +            kvm_show_regs(env);
 +            kvm_show_code(env);
 +            abort();
 +            break;
 +        case KVM_EXIT_IO:
 +            r = kvm_handle_io(run->io.port,
 +                                (uint8_t *)run + run->io.data_offset,
 +                                run->io.direction,
 +                                run->io.size,
 +                                run->io.count);
 +            r = 0;
 +            break;
 +        case KVM_EXIT_DEBUG:
 +            r = handle_debug(env);
 +            break;
 +        case KVM_EXIT_MMIO:
 +            r = handle_mmio(env);
 +            break;
 +        case KVM_EXIT_HLT:
 +            r = kvm_arch_halt(env);
 +            break;
 +        case KVM_EXIT_IRQ_WINDOW_OPEN:
 +            break;
 +        case KVM_EXIT_SHUTDOWN:
 +            r = handle_shutdown(kvm, env);
 +            break;
 +#if defined(__s390__)
 +        case KVM_EXIT_S390_SIEIC:
 +            r = kvm_s390_handle_intercept(kvm, env, run);
 +            break;
 +        case KVM_EXIT_S390_RESET:
 +            r = kvm_s390_handle_reset(kvm, env, run);
 +            break;
 +#endif
 +	case KVM_EXIT_INTERNAL_ERROR:
 +            kvm_handle_internal_error(env, run);
 +            r = 1;
 +	    break;
 +        default:
 +            if (kvm_arch_run(env)) {
 +                fprintf(stderr, "unhandled vm exit: 0x%x\n", run->exit_reason);
 +                kvm_show_regs(env);
 +                abort();
 +            }
 +            break;
 +        }
 +    }
 +more:
 +    if (!r) {
 +        goto again;
 +    }
 +    return r;
 +}
 +
 +int kvm_inject_irq(CPUState *env, unsigned irq)
 +{
 +    struct kvm_interrupt intr;
 +
 +    intr.irq = irq;
 +    return kvm_vcpu_ioctl(env, KVM_INTERRUPT, &intr);
 +}
 +
 +int kvm_inject_nmi(CPUState *env)
 +{
 +#ifdef KVM_CAP_USER_NMI
 +    return kvm_vcpu_ioctl(env, KVM_NMI);
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_init_coalesced_mmio(kvm_context_t kvm)
 +{
 +    int r = 0;
 +    kvm_state->coalesced_mmio = 0;
 +#ifdef KVM_CAP_COALESCED_MMIO
 +    r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO);
 +    if (r > 0) {
 +        kvm_state->coalesced_mmio = r;
 +        return 0;
 +    }
 +#endif
 +    return r;
 +}
 +
 +#ifdef KVM_CAP_DEVICE_ASSIGNMENT
 +int kvm_assign_pci_device(kvm_context_t kvm,
 +                          struct kvm_assigned_pci_dev *assigned_dev)
 +{
 +    return kvm_vm_ioctl(kvm_state, KVM_ASSIGN_PCI_DEVICE, assigned_dev);
 +}
 +
 +static int kvm_old_assign_irq(kvm_context_t kvm,
 +                              struct kvm_assigned_irq *assigned_irq)
 +{
 +    return kvm_vm_ioctl(kvm_state, KVM_ASSIGN_IRQ, assigned_irq);
 +}
 +
 +#ifdef KVM_CAP_ASSIGN_DEV_IRQ
 +int kvm_assign_irq(kvm_context_t kvm, struct kvm_assigned_irq *assigned_irq)
 +{
 +    int ret;
 +
 +    ret = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_ASSIGN_DEV_IRQ);
 +    if (ret > 0) {
 +        return kvm_vm_ioctl(kvm_state, KVM_ASSIGN_DEV_IRQ, assigned_irq);
 +    }
 +
 +    return kvm_old_assign_irq(kvm, assigned_irq);
 +}
 +
 +int kvm_deassign_irq(kvm_context_t kvm, struct kvm_assigned_irq *assigned_irq)
 +{
 +    return kvm_vm_ioctl(kvm_state, KVM_DEASSIGN_DEV_IRQ, assigned_irq);
 +}
 +#else
 +int kvm_assign_irq(kvm_context_t kvm, struct kvm_assigned_irq *assigned_irq)
 +{
 +    return kvm_old_assign_irq(kvm, assigned_irq);
 +}
 +#endif
 +#endif
 +
 +#ifdef KVM_CAP_DEVICE_DEASSIGNMENT
 +int kvm_deassign_pci_device(kvm_context_t kvm,
 +                            struct kvm_assigned_pci_dev *assigned_dev)
 +{
 +    return kvm_vm_ioctl(kvm_state, KVM_DEASSIGN_PCI_DEVICE, assigned_dev);
 +}
 +#endif
 +
 +int kvm_reinject_control(kvm_context_t kvm, int pit_reinject)
 +{
 +#ifdef KVM_CAP_REINJECT_CONTROL
 +    int r;
 +    struct kvm_reinject_control control;
 +
 +    control.pit_reinject = pit_reinject;
 +
 +    r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_REINJECT_CONTROL);
 +    if (r > 0) {
 +        return kvm_vm_ioctl(kvm_state, KVM_REINJECT_CONTROL, &control);
 +    }
 +#endif
 +    return -ENOSYS;
 +}
 +
 +int kvm_has_gsi_routing(void)
 +{
 +    int r = 0;
 +
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    r = kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING);
 +#endif
 +    return r;
 +}
 +
 +int kvm_get_gsi_count(kvm_context_t kvm)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    return kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING);
 +#else
 +    return -EINVAL;
 +#endif
 +}
 +
 +int kvm_clear_gsi_routes(void)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    kvm_context_t kvm = kvm_context;
 +
 +    kvm->irq_routes->nr = 0;
 +    return 0;
 +#else
 +    return -EINVAL;
 +#endif
 +}
 +
 +int kvm_add_routing_entry(struct kvm_irq_routing_entry *entry)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    kvm_context_t kvm = kvm_context;
 +    struct kvm_irq_routing *z;
 +    struct kvm_irq_routing_entry *new;
 +    int n, size;
 +
 +    if (kvm->irq_routes->nr == kvm->nr_allocated_irq_routes) {
 +        n = kvm->nr_allocated_irq_routes * 2;
 +        if (n < 64) {
 +            n = 64;
 +        }
 +        size = sizeof(struct kvm_irq_routing);
 +        size += n * sizeof(*new);
 +        z = realloc(kvm->irq_routes, size);
 +        if (!z) {
 +            return -ENOMEM;
 +        }
 +        kvm->nr_allocated_irq_routes = n;
 +        kvm->irq_routes = z;
 +    }
 +    n = kvm->irq_routes->nr++;
 +    new = &kvm->irq_routes->entries[n];
 +    memset(new, 0, sizeof(*new));
 +    new->gsi = entry->gsi;
 +    new->type = entry->type;
 +    new->flags = entry->flags;
 +    new->u = entry->u;
 +
 +    set_gsi(kvm, entry->gsi);
 +
 +    return 0;
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_add_irq_route(int gsi, int irqchip, int pin)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    struct kvm_irq_routing_entry e;
 +
 +    e.gsi = gsi;
 +    e.type = KVM_IRQ_ROUTING_IRQCHIP;
 +    e.flags = 0;
 +    e.u.irqchip.irqchip = irqchip;
 +    e.u.irqchip.pin = pin;
 +    return kvm_add_routing_entry(&e);
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_del_routing_entry(struct kvm_irq_routing_entry *entry)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    kvm_context_t kvm = kvm_context;
 +    struct kvm_irq_routing_entry *e, *p;
 +    int i, gsi, found = 0;
 +
 +    gsi = entry->gsi;
 +
 +    for (i = 0; i < kvm->irq_routes->nr; ++i) {
 +        e = &kvm->irq_routes->entries[i];
 +        if (e->type == entry->type && e->gsi == gsi) {
 +            switch (e->type) {
 +            case KVM_IRQ_ROUTING_IRQCHIP:{
 +                    if (e->u.irqchip.irqchip ==
 +                        entry->u.irqchip.irqchip
 +                        && e->u.irqchip.pin == entry->u.irqchip.pin) {
 +                        p = &kvm->irq_routes->entries[--kvm->irq_routes->nr];
 +                        *e = *p;
 +                        found = 1;
 +                    }
 +                    break;
 +                }
 +            case KVM_IRQ_ROUTING_MSI:{
 +                    if (e->u.msi.address_lo ==
 +                        entry->u.msi.address_lo
 +                        && e->u.msi.address_hi ==
 +                        entry->u.msi.address_hi
 +                        && e->u.msi.data == entry->u.msi.data) {
 +                        p = &kvm->irq_routes->entries[--kvm->irq_routes->nr];
 +                        *e = *p;
 +                        found = 1;
 +                    }
 +                    break;
 +                }
 +            default:
 +                break;
 +            }
 +            if (found) {
 +                /* If there are no other users of this GSI
 +                 * mark it available in the bitmap */
 +                for (i = 0; i < kvm->irq_routes->nr; i++) {
 +                    e = &kvm->irq_routes->entries[i];
 +                    if (e->gsi == gsi)
 +                        break;
 +                }
 +                if (i == kvm->irq_routes->nr) {
 +                    clear_gsi(kvm, gsi);
 +                }
 +
 +                return 0;
 +            }
 +        }
 +    }
 +    return -ESRCH;
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_update_routing_entry(struct kvm_irq_routing_entry *entry,
 +                             struct kvm_irq_routing_entry *newentry)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    kvm_context_t kvm = kvm_context;
 +    struct kvm_irq_routing_entry *e;
 +    int i;
 +
 +    if (entry->gsi != newentry->gsi || entry->type != newentry->type) {
 +        return -EINVAL;
 +    }
 +
 +    for (i = 0; i < kvm->irq_routes->nr; ++i) {
 +        e = &kvm->irq_routes->entries[i];
 +        if (e->type != entry->type || e->gsi != entry->gsi) {
 +            continue;
 +        }
 +        switch (e->type) {
 +        case KVM_IRQ_ROUTING_IRQCHIP:
 +            if (e->u.irqchip.irqchip == entry->u.irqchip.irqchip &&
 +                e->u.irqchip.pin == entry->u.irqchip.pin) {
 +                memcpy(&e->u.irqchip, &newentry->u.irqchip,
 +                       sizeof e->u.irqchip);
 +                return 0;
 +            }
 +            break;
 +        case KVM_IRQ_ROUTING_MSI:
 +            if (e->u.msi.address_lo == entry->u.msi.address_lo &&
 +                e->u.msi.address_hi == entry->u.msi.address_hi &&
 +                e->u.msi.data == entry->u.msi.data) {
 +                memcpy(&e->u.msi, &newentry->u.msi, sizeof e->u.msi);
 +                return 0;
 +            }
 +            break;
 +        default:
 +            break;
 +        }
 +    }
 +    return -ESRCH;
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_del_irq_route(int gsi, int irqchip, int pin)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    struct kvm_irq_routing_entry e;
 +
 +    e.gsi = gsi;
 +    e.type = KVM_IRQ_ROUTING_IRQCHIP;
 +    e.flags = 0;
 +    e.u.irqchip.irqchip = irqchip;
 +    e.u.irqchip.pin = pin;
 +    return kvm_del_routing_entry(&e);
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_commit_irq_routes(void)
 +{
 +#ifdef KVM_CAP_IRQ_ROUTING
 +    kvm_context_t kvm = kvm_context;
 +
 +    kvm->irq_routes->flags = 0;
 +    return kvm_vm_ioctl(kvm_state, KVM_SET_GSI_ROUTING, kvm->irq_routes);
 +#else
 +    return -ENOSYS;
 +#endif
 +}
 +
 +int kvm_get_irq_route_gsi(void)
 +{
 +    kvm_context_t kvm = kvm_context;
 +    int i, bit;
 +    uint32_t *buf = kvm->used_gsi_bitmap;
 +
 +    /* Return the lowest unused GSI in the bitmap */
 +    for (i = 0; i < kvm->max_gsi / 32; i++) {
 +        bit = ffs(~buf[i]);
 +        if (!bit) {
 +            continue;
 +        }
 +
 +        return bit - 1 + i * 32;
 +    }
 +
 +    return -ENOSPC;
 +}
 +
 +static void kvm_msix_routing_entry(struct kvm_irq_routing_entry *e,
 +                                   uint32_t gsi, uint32_t addr_lo,
 +                                   uint32_t addr_hi, uint32_t data)
 +
 +{
 +    e->gsi = gsi;
 +    e->type = KVM_IRQ_ROUTING_MSI;
 +    e->flags = 0;
 +    e->u.msi.address_lo = addr_lo;
 +    e->u.msi.address_hi = addr_hi;
 +    e->u.msi.data = data;
 +}
 +
 +int kvm_add_msix(uint32_t gsi, uint32_t addr_lo,
 +                        uint32_t addr_hi, uint32_t data)
 +{
 +    struct kvm_irq_routing_entry e;
 +
 +    kvm_msix_routing_entry(&e, gsi, addr_lo, addr_hi, data);
 +    return kvm_add_routing_entry(&e);
 +}
 +
 +int kvm_del_msix(uint32_t gsi, uint32_t addr_lo,
 +                        uint32_t addr_hi, uint32_t data)
 +{
 +    struct kvm_irq_routing_entry e;
 +
 +    kvm_msix_routing_entry(&e, gsi, addr_lo, addr_hi, data);
 +    return kvm_del_routing_entry(&e);
 +}
 +
 +int kvm_update_msix(uint32_t old_gsi, uint32_t old_addr_lo,
 +                    uint32_t old_addr_hi, uint32_t old_data,
 +                    uint32_t new_gsi, uint32_t new_addr_lo,
 +                    uint32_t new_addr_hi, uint32_t new_data)
 +{
 +    struct kvm_irq_routing_entry e1, e2;
 +
 +    kvm_msix_routing_entry(&e1, old_gsi, old_addr_lo, old_addr_hi, old_data);
 +    kvm_msix_routing_entry(&e2, new_gsi, new_addr_lo, new_addr_hi, new_data);
 +    return kvm_update_routing_entry(&e1, &e2);
 +}
 +
 +
 +#ifdef KVM_CAP_DEVICE_MSIX
 +int kvm_assign_set_msix_nr(kvm_context_t kvm,
 +                           struct kvm_assigned_msix_nr *msix_nr)
 +{
 +    return kvm_vm_ioctl(kvm_state, KVM_ASSIGN_SET_MSIX_NR, msix_nr);
 +}
 +
 +int kvm_assign_set_msix_entry(kvm_context_t kvm,
 +                              struct kvm_assigned_msix_entry *entry)
 +{
 +    return kvm_vm_ioctl(kvm_state, KVM_ASSIGN_SET_MSIX_ENTRY, entry);
 +}
 +#endif
 +
 +#if defined(KVM_CAP_IRQFD) && defined(CONFIG_EVENTFD)
 +
 +#include <sys/eventfd.h>
 +
 +static int _kvm_irqfd(kvm_context_t kvm, int fd, int gsi, int flags)
 +{
 +    struct kvm_irqfd data = {
 +        .fd = fd,
 +        .gsi = gsi,
 +        .flags = flags,
 +    };
 +
 +    return kvm_vm_ioctl(kvm_state, KVM_IRQFD, &data);
 +}
 +
 +int kvm_irqfd(kvm_context_t kvm, int gsi, int flags)
 +{
 +    int r;
 +    int fd;
 +
 +    if (!kvm_check_extension(kvm_state, KVM_CAP_IRQFD))
 +        return -ENOENT;
 +
 +    fd = eventfd(0, 0);
 +    if (fd < 0) {
 +        return -errno;
 +    }
 +
 +    r = _kvm_irqfd(kvm, fd, gsi, 0);
 +    if (r < 0) {
 +        close(fd);
 +        return -errno;
 +    }
 +
 +    return fd;
 +}
 +
 +#else                           /* KVM_CAP_IRQFD */
 +
 +int kvm_irqfd(kvm_context_t kvm, int gsi, int flags)
 +{
 +    return -ENOSYS;
 +}
 +
 +#endif                          /* KVM_CAP_IRQFD */
 +unsigned long kvm_get_thread_id(void)
 +{
 +    return syscall(SYS_gettid);
 +}
 +
 +static void qemu_cond_wait(pthread_cond_t *cond)
 +{
 +    CPUState *env = cpu_single_env;
 +
 +    pthread_cond_wait(cond, &qemu_mutex);
 +    cpu_single_env = env;
 +}
 +
 +static void sig_ipi_handler(int n)
 +{
 +}
 +
 +static void sigbus_reraise(void)
 +{
 +    sigset_t set;
 +    struct sigaction action;
 +
 +    memset(&action, 0, sizeof(action));
 +    action.sa_handler = SIG_DFL;
 +    if (!sigaction(SIGBUS, &action, NULL)) {
 +        raise(SIGBUS);
 +        sigemptyset(&set);
 +        sigaddset(&set, SIGBUS);
 +        sigprocmask(SIG_UNBLOCK, &set, NULL);
 +    }
 +    perror("Failed to re-raise SIGBUS!\n");
 +    abort();
 +}
 +
 +static void sigbus_handler(int n, struct qemu_signalfd_siginfo *siginfo,
 +                           void *ctx)
 +{
 +    if (kvm_on_sigbus(siginfo->ssi_code, (void *)(intptr_t)siginfo->ssi_addr))
 +        sigbus_reraise();
 +}
 +
 +void on_vcpu(CPUState *env, void (*func)(void *data), void *data)
 +{
 +    struct qemu_work_item wi;
 +
 +    if (env == current_env) {
 +        func(data);
 +        return;
 +    }
 +
 +    wi.func = func;
 +    wi.data = data;
 +    if (!env->kvm_cpu_state.queued_work_first) {
 +        env->kvm_cpu_state.queued_work_first = &wi;
 +    } else {
 +        env->kvm_cpu_state.queued_work_last->next = &wi;
 +    }
 +    env->kvm_cpu_state.queued_work_last = &wi;
 +    wi.next = NULL;
 +    wi.done = false;
 +
 +    pthread_kill(env->kvm_cpu_state.thread, SIG_IPI);
 +    while (!wi.done) {
 +        qemu_cond_wait(&qemu_work_cond);
 +    }
 +}
 +
 +static void do_kvm_cpu_synchronize_state(void *_env)
 +{
 +    CPUState *env = _env;
 +
 +    if (!env->kvm_vcpu_dirty) {
 +        kvm_arch_save_regs(env);
 +        env->kvm_vcpu_dirty = 1;
 +    }
 +}
 +
 +void kvm_cpu_synchronize_state(CPUState *env)
 +{
 +    if (!env->kvm_vcpu_dirty) {
 +        on_vcpu(env, do_kvm_cpu_synchronize_state, env);
 +    }
 +}
 +
 +void kvm_cpu_synchronize_post_reset(CPUState *env)
 +{
 +    kvm_arch_load_regs(env, KVM_PUT_RESET_STATE);
 +    env->kvm_vcpu_dirty = 0;
 +}
 +
 +void kvm_cpu_synchronize_post_init(CPUState *env)
 +{
 +    kvm_arch_load_regs(env, KVM_PUT_FULL_STATE);
 +    env->kvm_vcpu_dirty = 0;
 +}
 +
 +static void inject_interrupt(void *data)
 +{
 +    cpu_interrupt(current_env, (long) data);
 +}
 +
 +void kvm_inject_interrupt(CPUState *env, int mask)
 +{
 +    on_vcpu(env, inject_interrupt, (void *) (long) mask);
 +}
 +
 +void kvm_update_interrupt_request(CPUState *env)
 +{
 +    int signal = 0;
 +
 +    if (env) {
 +        if (!current_env || !current_env->created) {
 +            signal = 1;
 +        }
 +        /*
 +         * Testing for created here is really redundant
 +         */
 +        if (current_env && current_env->created &&
 +            env != current_env && !env->kvm_cpu_state.signalled) {
 +            signal = 1;
 +        }
 +
 +        if (signal) {
 +            env->kvm_cpu_state.signalled = 1;
 +            if (env->kvm_cpu_state.thread) {
 +                pthread_kill(env->kvm_cpu_state.thread, SIG_IPI);
 +            }
 +        }
 +    }
 +}
 +
 +int kvm_cpu_exec(CPUState *env)
 +{
 +    int r;
 +
 +    r = kvm_run(env);
 +    if (r < 0) {
 +        printf("kvm_run returned %d\n", r);
 +        vm_stop(0);
 +    }
 +
 +    return 0;
 +}
 +
 +int kvm_cpu_is_stopped(CPUState *env)
 +{
 +    return !vm_running || env->stopped;
 +}
 +
 +static void flush_queued_work(CPUState *env)
 +{
 +    struct qemu_work_item *wi;
 +
 +    if (!env->kvm_cpu_state.queued_work_first) {
 +        return;
 +    }
 +
 +    while ((wi = env->kvm_cpu_state.queued_work_first)) {
 +        env->kvm_cpu_state.queued_work_first = wi->next;
 +        wi->func(wi->data);
 +        wi->done = true;
 +    }
 +    env->kvm_cpu_state.queued_work_last = NULL;
 +    pthread_cond_broadcast(&qemu_work_cond);
 +}
 +
 +static void kvm_main_loop_wait(CPUState *env, int timeout)
 +{
 +    struct timespec ts;
 +    int r, e;
 +    siginfo_t siginfo;
 +    sigset_t waitset;
 +    sigset_t chkset;
 +
 +    ts.tv_sec = timeout / 1000;
 +    ts.tv_nsec = (timeout % 1000) * 1000000;
 +    sigemptyset(&waitset);
 +    sigaddset(&waitset, SIG_IPI);
 +    sigaddset(&waitset, SIGBUS);
 +
 +    do {
 +        pthread_mutex_unlock(&qemu_mutex);
 +
 +        r = sigtimedwait(&waitset, &siginfo, &ts);
 +        e = errno;
 +
 +        pthread_mutex_lock(&qemu_mutex);
 +
 +        if (r == -1 && !(e == EAGAIN || e == EINTR)) {
 +            printf("sigtimedwait: %s\n", strerror(e));
 +            exit(1);
 +        }
 +
 +        switch (r) {
 +        case SIGBUS:
 +            if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr))
 +                sigbus_reraise();
 +            break;
 +        default:
 +            break;
 +        }
 +
 +        r = sigpending(&chkset);
 +        if (r == -1) {
 +            printf("sigpending: %s\n", strerror(e));
 +            exit(1);
 +        }
 +    } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
 +
 +    cpu_single_env = env;
 +    flush_queued_work(env);
 +
 +    if (env->stop) {
 +        env->stop = 0;
 +        env->stopped = 1;
 +        pthread_cond_signal(&qemu_pause_cond);
 +    }
 +
 +    env->kvm_cpu_state.signalled = 0;
 +}
 +
 +static int all_threads_paused(void)
 +{
 +    CPUState *penv = first_cpu;
 +
 +    while (penv) {
 +        if (penv->stop) {
 +            return 0;
 +        }
 +        penv = (CPUState *) penv->next_cpu;
 +    }
 +
 +    return 1;
 +}
 +
 +static void pause_all_threads(void)
 +{
 +    CPUState *penv = first_cpu;
 +
 +    while (penv) {
 +        if (penv != cpu_single_env) {
 +            penv->stop = 1;
 +            pthread_kill(penv->kvm_cpu_state.thread, SIG_IPI);
 +        } else {
 +            penv->stop = 0;
 +            penv->stopped = 1;
 +            cpu_exit(penv);
 +        }
 +        penv = (CPUState *) penv->next_cpu;
 +    }
 +
 +    while (!all_threads_paused()) {
 +        qemu_cond_wait(&qemu_pause_cond);
 +    }
 +}
 +
 +static void resume_all_threads(void)
 +{
 +    CPUState *penv = first_cpu;
 +
 +    assert(!cpu_single_env);
 +
 +    while (penv) {
 +        penv->stop = 0;
 +        penv->stopped = 0;
 +        pthread_kill(penv->kvm_cpu_state.thread, SIG_IPI);
 +        penv = (CPUState *) penv->next_cpu;
 +    }
 +}
 +
 +static void kvm_vm_state_change_handler(void *context, int running, int reason)
 +{
 +    if (running) {
 +        resume_all_threads();
 +    } else {
 +        pause_all_threads();
 +    }
 +}
 +
 +static void setup_kernel_sigmask(CPUState *env)
 +{
 +    sigset_t set;
 +
 +    sigemptyset(&set);
 +    sigaddset(&set, SIGUSR2);
 +    sigaddset(&set, SIGIO);
 +    sigaddset(&set, SIGALRM);
 +    sigprocmask(SIG_BLOCK, &set, NULL);
 +
 +    sigprocmask(SIG_BLOCK, NULL, &set);
 +    sigdelset(&set, SIG_IPI);
 +    sigdelset(&set, SIGBUS);
 +
 +    kvm_set_signal_mask(env, &set);
 +}
 +
 +static void qemu_kvm_system_reset(void)
 +{
 +    pause_all_threads();
 +
 +    qemu_system_reset();
 +
 +    resume_all_threads();
 +}
 +
 +static void process_irqchip_events(CPUState *env)
 +{
 +    kvm_arch_process_irqchip_events(env);
 +    if (kvm_arch_has_work(env))
 +        env->halted = 0;
 +}
 +
 +static int kvm_main_loop_cpu(CPUState *env)
 +{
 +    while (1) {
 +        int run_cpu = !kvm_cpu_is_stopped(env);
 +        if (run_cpu && !kvm_irqchip_in_kernel()) {
 +            process_irqchip_events(env);
 +            run_cpu = !env->halted;
 +        }
 +        if (run_cpu) {
 +            kvm_cpu_exec(env);
 +            kvm_main_loop_wait(env, 0);
 +        } else {
 +            kvm_main_loop_wait(env, 1000);
 +        }
 +    }
 +    pthread_mutex_unlock(&qemu_mutex);
 +    return 0;
 +}
 +
 +static void *ap_main_loop(void *_env)
 +{
 +    CPUState *env = _env;
 +    sigset_t signals;
 +#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
 +    st